Closed mlynch closed 2 years ago
Thank you for this! I'm not sure if this is a Capacitor or iOS issue, but I've noticed that my iOS builds are several times larger than my Android ones (~15mb vs ~4mb). It's the same code base so the only difference is I have a lot more app icon and splash icon sizes and formats on iOS. Is there any way to make it so that only the icons that are relevant to the user's device get downloaded? It seems like this would dramatically reduce the download size of apps on iOS. Maybe I'm adding too many icon options and there's a single icon format that would work for all iOS device types. In this case, just making that clearer would be extremely helpful.
I have not used this tool before, but the most difficult part of shipping on Android is creating a 9 patch splash screen.
As far as I understand it it's supposed to fit on any Android screen, but from my experience it gets squashed no matter what I do π
Would love a better way to work around that issue.
Hope that helps!
@alexandermorgan hard to say without looking at it but either way I think I already cut a number of generated images, I need to see.
The size difference is likely due to embedding Swift libraries. The work Apple did in the App Store means the actual size that users download can be much smaller since it can strip away a lot of that especially in recent versions of Swift.
@creativiii yea I need to assess where we are with 9 patches, there is definitely work to be done for better Android Adaptive icon support
Hey boss! I'd love support for PWA manifest images to be included as well. This would fit Ionic's cross-platform/"build once" mantra of supporting web, ios, android out-of-the-box. Other tools do exist to create these though, so it's not a must-have.
@dotNetkow great point. IIRC I already added this into my WIP branch a few months ago so this is definitely happening
It's been a few months since the last time I used cordova-res, but I remember that I had an issue with folders that are missing in Android while I was generating the splash screen & app icon. I'm not sure if it's solved now, so I would already be satisfied if I don't have this problem with Capacitor Assets haha.
I would like that we incorporate notification icon in this new plugin, it is not handled by cordova-res. If I remember well, for iOS, no notification icon is required but for Android, you need to have the same icon than the app icon but in white, the color of the icon is added in the code somewhere in Android config files.
@JulienLecoq great idea. Seems we should support Notification, Settings, and Spotlight icons at least for iOS, not sure if there are additional ones we should support for Android:
https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/
The other feature what we need here is the Adaptive Icons
support for the Android devices: There are lot of open issues for this:
Yes good point that will be a key focus for this
Can someone verify my understanding here: on iOS if you want to provide a different icon for notifications and settings, you should modify the smaller sizes of your icons listed here: https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/
There is no special icon set for notifications/etc. right? They are just taken from your main AppIcons?
In that case I think we'll overwrite those smaller icons if you provide specific notification/settings ones in your assets
Hey everyone, the first alpha release of @capacitor/assets
is ready for testing. It supports generating assets for iOS, Android, and PWA. For Android it supports Adaptive Icons and legacy icons. Both iOS and Android also support generating light and dark mode splash screens.
I know there is still work to be done on the tool, but I would really love some help testing and some feedback on things that are still missing.
To get started, check out the readme for the 1.x
branch and I look forward to your feedback:
https://github.com/ionic-team/capacitor-assets/blob/1.x/README.md
@mlynch thanks a lot for this i just give it a try and some feedback:
{
"scripts": {
"capacitor-assets": "capacitor-assets"
}
}
but it should be
{
"scripts": {
"capacitor-assets": "capacitor-assets generate"
}
}
resources
folder but that wrong it's a assets
I have made a PR for theses : https://github.com/ionic-team/capacitor-assets/pull/296
Otherwise, the tool worked well, and way faster than the old one ! I will love to have this tool also create the notification icon for Android platform.
I good addition i would love to have: A quick generator, most of my app use the logo in centre in the spashscreen background is same in icon and splash. So have a way to generate all from a colour and foreground icon would make our life easier.
@riderx for the last addition, meaning you just take a logo and it and generates the other assets for you so you don't have to create the source splash.png
etc?
This would be primarily for splash screens?
Seems reasonable
Yes Exactly :)
@riderx Got the iOS side of that done, moving to android + pwa
@mlynch amazing !
i just try my Android app and all assets got broken link.
i think migrate from old asset's system to new one has issue on Android.
I'm trying to understand why i get Invalid resource directory name
, i event try to remove android folder and add again to see if that come from one of my config but still same issue
@riderx 1.0.0-next.2 is out and it supports generating all assets from a single logo file.
Check out the new Easy Mode docs, curious to get your feedback π https://github.com/ionic-team/capacitor-assets/tree/1.x#usage---easy-mode
Made my day! I just discovered quasar has same kind of features, have a check there lot of interesting stuff! I will check tomorrow :)
@mlynch i tryed capacitor-assets generate --iconBackgroundColor '#FFFFFF' --iconBackgroundColorDark '#111111' --splashBackgroundColor '#FFFFFF' --splashBackgroundColorDark '#111111'
with the last version 1.0.0-next.1
and this logo :
and got some errors:
Unable to generate assets TypeError: Cannot use 'in' operator to search for 'alpha' in true
at new Color (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/color@4.2.1/node_modules/color/index.js:77:15)
at Color (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/color@4.2.1/node_modules/color/index.js:26:10)
at Sharp._createInputDescriptor (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/sharp@0.29.3/node_modules/sharp/lib/input.js:216:30)
at new Sharp (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/sharp@0.29.3/node_modules/sharp/lib/constructor.js:289:29)
at Sharp (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/sharp@0.29.3/node_modules/sharp/lib/constructor.js:137:12)
at AndroidAssetGenerator._generateAdaptiveIconsFromLogo (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/@capacitor+assets@1.0.0-next.1_e79e62fe450383fd2d418267dc75e645/node_modules/@capacitor/assets/dist/platforms/android/index.js:81:52)
at AndroidAssetGenerator.generateFromLogo (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/@capacitor+assets@1.0.0-next.1_e79e62fe450383fd2d418267dc75e645/node_modules/@capacitor/assets/dist/platforms/android/index.js:50:51)
at AndroidAssetGenerator.generate (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/@capacitor+assets@1.0.0-next.1_e79e62fe450383fd2d418267dc75e645/node_modules/@capacitor/assets/dist/platforms/android/index.js:25:29)
at InputAsset.generate (/Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/@capacitor+assets@1.0.0-next.1_e79e62fe450383fd2d418267dc75e645/node_modules/@capacitor/assets/dist/input-asset.js:41:25)
at /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/node_modules/.pnpm/@capacitor+assets@1.0.0-next.1_e79e62fe450383fd2d418267dc75e645/node_modules/@capacitor/assets/dist/tasks/generate.js:51:63
It seems from the log i cannot have alpha channel in my logo. Edit: i tried to use a logo with background and same issue.
Okay thanks for the report will look at this right now @riderx
@mlynch there a need to change the folder name from ressources
to assets
?
i see some cordova tools rely on the name of the folder.
Maybe we can keep it for compatibility reason ?
@riderx haven't fixed that issue yet but will soon once I finish up the pwa splash generation which is the last big task. I can easily support resources or assets
Thanks to keep me posted π
@riderx can you try @capacitor/assets@1.0.0-next.4@next
? I made a bunch of changes and fixed the issue you reported above (I wasn't correctly implementing the command flags).
I added easy mode/logo generation to all platforms and this is just about getting close to a 1.0 release I think
This go to the end again and seems correct with splash and icon but i'm back with the issue in android.
2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/android/app/src/main/res/drawable-night-port-xhdpi: Error: Invalid resource directory name
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:187)
at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:268)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:185)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:173)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:408)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:395)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:388)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:374)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: com.android.build.gradle.tasks.ResourceException: /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/android/app/src/main/res/drawable-night-port-xhdpi: Error: Invalid resource directory name
at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:312)
Caused by: com.android.build.gradle.tasks.ResourceException: /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/android/app/src/main/res/drawable-night-port-xhdpi: Error: Invalid resource directory name
at com.android.build.gradle.internal.tasks.IncrementalTask.handleIncrementalInputs(IncrementalTask.kt:110)
at com.android.build.gradle.internal.tasks.IncrementalTask.access$handleIncrementalInputs(IncrementalTask.kt:65)
at com.android.build.gradle.internal.tasks.IncrementalTask$taskAction$$inlined$recordTaskAction$1.invoke(BaseTask.kt:62)
at com.android.build.gradle.internal.tasks.Blocks.recordSpan(Blocks.java:51)
at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction$gradle_core(IncrementalTask.kt:137)
at jdk.internal.reflect.GeneratedMethodAccessor722.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
at org.gradle.api.internal.project.taskfactory.IncrementalTaskInputsTaskAction.doExecute(IncrementalTaskInputsTaskAction.java:47)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
at org.gradle.api.internal.project.taskfactory.AbstractIncrementalTaskAction.execute(AbstractIncrementalTaskAction.java:25)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.run(ExecuteActionsTaskExecuter.java:498)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:483)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:466)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:105)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:270)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:248)
at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:83)
at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:37)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:50)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:47)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:47)
at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:37)
at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:68)
at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:38)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:50)
at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:36)
at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:29)
at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:54)
at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:35)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:60)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:27)
at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:174)
at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:74)
at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:45)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:40)
at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:29)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22)
at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:99)
at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:92)
at java.base/java.util.Optional.map(Optional.java:265)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:84)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:41)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:91)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:78)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:49)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:105)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:50)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:86)
at java.base/java.util.Optional.orElseGet(Optional.java:369)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:86)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:32)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:43)
at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:31)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:40)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution$2.withWorkspace(ExecuteActionsTaskExecuter.java:283)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:40)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:49)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:35)
at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:76)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:184)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:173)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:74)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:408)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:395)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:388)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:374)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/android/app/src/main/res/drawable-night-port-xhdpi: Error: Invalid resource directory name
at com.android.ide.common.resources.MergingException.throwIfNonEmpty(MergingException.java:170)
at com.android.ide.common.resources.DataSet.loadFromFiles(DataSet.java:264)
at com.android.build.gradle.tasks.MergeResources.lambda$doFullTaskAction$0(MergeResources.java:261)
at com.android.build.gradle.internal.tasks.Blocks.recordSpan(Blocks.java:51)
at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:255)
Caused by: /Users/martindonadieu/Documents/Projects.nosync/Capacitor/capgo/android/app/src/main/res/drawable-night-port-xhdpi: Error: Invalid resource directory name
... 133 more
==============================================================================
it's seems there only one issue for drawable-night-port-xhdpi
i have try to remove the platform and do it from fresh platform and the issue still happen
I really love how fast it is to get the assets !
Cool I get the same issue so will fix here shortly. Making progress π€
@riderx 1.0.0-next.5@next
should have this fixed
@mlynch after remove the platform and add again it works! Thanks a lot for this work, a new stone for our mobile app to don't need cordova stuff anymore! I still have a tiny issue related to that, it how the splash look when we start a new Capacitor app:
https://user-images.githubusercontent.com/4084527/160916734-693fc75f-2a47-45e6-85da-a7f863b55a28.mp4
The splash screen doesn't have the appropriate size by default on many phones, and after a few seconds it works. it give a bad feeling of dev who start to use Capacitor.
i know that a matter of settings in Android, but maybe since the tool you did could be added to the capacitor CLI. If you make this setting default, that will improve the feeling of Capacitor is a strong solution ready to go :) You can find a stack overflow post about it here : https://stackoverflow.com/questions/66285483/ionic-capacitor-android-splash-screen-responsiveness
@riderx if you follow the steps in that linked solution does it resolve the scaling issue for you?
@mlynch it does, but just by making the first image as color, so we saw only the second one, not really optimal in my memory.
@riderx I don't understand, can you elaborate?
I have tried many solutions and the only one I found who was working, was replacing the first broken image by a background color, and then when the second one load everything is good. I can check later tonight if you need additional information. You can see there : https://github.com/ionic-team/capacitor/issues/1627 it is a recurring problem with a lot of solution, that why I was thinking if capacitor-assets setup it, then no more discussion :)
Thanks, I think this is out of scope of the current work I'm doing on this tool, but I'll share that with the team.
Ignoring that issue, is everything else working for you then? My tests are good, so I might cut a 1.0 soon and update the main branch to point to the new Capacitor version. let me know.
yes i understand! It was a bonus one ahh! i do think it's feature complete and well documented. Just still have a warning about the folder renaming, but otherwise this is good for me to release.
@mlynch got a new issue in IOS, when I upload to the app store it says some mandatory assets are missing.
It's possible to create Android 9-Patch splash screens with sharp:
Here's a sample code from my cordova legacy repo: https://gist.github.com/piotr-cz/1a3f1360d189231792db21756cb4a72d
Actually there is a difference when only one platform is choosen. In the README the command is listed with npm run capacitor-assets generate ios
and the platform is added as argument, while the command currently only accepts the platform as an option to work: npm run capacitor-assets generate -- --ios
:
I would have fixed the typo in the README directly as PR, but I wasn't sure if the actual intention to list the platform as argument is already correct and instead the code should be updated...
@piotr-cz are 9 patches still used for splash/icons?
@SimonGolms fixed thanks
@riderx will fix, thanks for the note
@piotr-cz are 9 patches still used for splash/icons?
@mlynch I'm a seasonal mobile developer so I'm not sure about current trend Given so many android devices and screen resolutions it's very convenient to use 9-patch for splash screens (or at least transparent logo with solid background)
Hey I tried easy mode with "@capacitor/assets": "^1.0.0-next.5"
and wow, icon creation is incredible.
EDIT: My stretching issues were fixed by using the following SplashScreen plugin settings:
SplashScreen: {
launchAutoHide: false,
androidScaleType: 'CENTER_CROP',
backgroundColor: '#fff',
},
Might be worth mentioning the optimal capacitor config setup to use the generated files? Either way, fantastic tool!
I'm also experiencing the issue mentioned in riderX's post, solution mentioned in the stackoverflow works π
Thanks for this great tool π
I am using "@capacitor/assets": "^1.0.0-next.5",
and noticed that not all AppIcon and Splash sizes are generated.
My assets
dir looks like this:
When I now execute capacitor-assets generate --ios
the following 17 AppIcons and 1 Splash screen is generated.
The following 14 AppIcons and 3 Splash Screens sizes are not generated, which are included by the default capacitor ios app:
Do you plan on supporting the other sizes? Are those sizes not necessary anymore?
I receive the following error when I try to upload the App to TestFlight, when I remove the default Capacitor AppIcons
Missing App Icon. An app icon measuring 1024 by 1024 pixels in PNG format must be included in the Asset Catalog of apps built for iOS, iPadOS, or watchOS. Without this icon, apps cannot be submitted for review. For details, see https://developer.apple.com/ios/human-interface-guidelines/icons-and-images/app-icon/.
The AppIcon with the name AppIcon-512@2x.png
is in that size 1024x1024px, but is not generated with capacitor-assets.
Looks like the same error as @riderx received while uploading to the Apple Store.
However, capacitor-assets generates the following AppIcon including AppIcon-1024x1024.png
which is 1024x1024px, so why does Apple complain about this missing AppIcon size?
One workaround which allows me to upload too TestFlight is to copy AppIcon-1024x1024.png
and rename it to AppIcon-512@2x.png
.
Feedback:
To the extend that iOS/Android support it (I don't know how good their SVG support is), it would be nice if we could set a 'minimum API version' and only generate the assets needed for such an app. For example, if our minimum android version is above a version that supports SVG assets, only SVG assets would be generated.
Obviously related, but if SVG as input files in easy mode isn't already supported, it would be good if it was.
Great with easy mode and using hex codes for splash screen backgrounds! Most splash screens only need a solid color anyway.
Would be nice if it would accept HSL values too. Not too complicated to convert to HEX. You could use these snippets as util methods (it's just math).
https://stackoverflow.com/questions/36721830/convert-hsl-to-rgb-and-hex https://css-tricks.com/converting-color-spaces-in-javascript/
One workaround which allows me to upload too TestFlight is to copy
AppIcon-1024x1024.png
and rename it toAppIcon-512@2x.png
.
This workaround is perfect for now, thanks @marcjulian !
The easy mode is a really great feature to generate the resources! Unfortunately I have some challenges.
My input files (512x512):
/assets/logo.svg
/assets/logo-dark.svg
"dependencies": {
"@capacitor/android": "4.1.0",
"@capacitor/core": "4.1.0",
"@capacitor/ios": "4.1.0",
},
"devDependencies": {
"@capacitor/assets": "1.0.0-next.5",
}
Thanks for your work!
Additionally: As I am using the new Android 12 Splash Screen API, I switched from the generated drawables to simple vector assets with svg content (background color + logo vector centered). Would it be possible to add an option to this library to just generate the logo assets?
Appreciate the feedback everyone. I had to put this on the backburner for a bit over the summer but taking a fresh look at it
Hi everyone,
I am going to be working on getting the Capacitor Assets (formerly
cordova-res
) tool updated and modernized, to enable developers to more efficiently manage their app icon/splash assets.I would love to hear what you hope to get out of this tool or how you were using the
cordova-res
project.A few goals that we have for the new version of this project:
@capacitor/configure
and@capacitor/project
tools to go beyond asset generation to actually configuring and managing your native Capacitor projects with the appropriate assetsWith this in mind, I'd love feedback and thoughts on the use cases you have for image/asset generation and ideas on how we can make this tool more useful for you.