Resource not found when creating a project from a custom Android Studio template

Planned

Hi,

I am creating a plugin for Android Studio which adds a custom project template. The project created from this template must contain some resources. The RecipeExecutor.copy method allows to copy a source file into a destination file. However, when running Android Studio with my plugin, the following error appears : "resource relative to com.android.tools.idea.wizard.template.TemplateBuilder not found." The resource's path is correct but the error is still present. How can I add this resource ?   

0
5 comments

Hi Denis Bedin,

Error message `com.android.tools.idea.wizard.template.TemplateBuilder not found.` suggests that this is not about `copy` method. Do you have `thumb` in your template? E.g.

val myAwesomeTemplate {
get() = template {
...
   thumb { File("template-leanback-TV.png") } // <= thumb
...
 }
}

If not - could you please post full stacktrace for IllegalArgumentException("resource %s relative to %s not found.")?

0

Hi Andrei Kuznetsov and thanks for your answer,

I do have `thumb` in my template. Here is the stacktrace :

java.lang.IllegalArgumentException: resource /my-image.png relative to com.android.tools.idea.wizard.template.TemplateBuilder not found.
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:441)
    at com.google.common.io.Resources.getResource(Resources.java:208)
    at com.android.tools.idea.wizard.template.TemplateHelpersKt.findResource(TemplateHelpers.kt:215)
    at com.android.tools.idea.wizard.template.TemplateBuilder$thumb$2$1.invoke(TemplateDSL.kt:66)
    at com.android.tools.idea.wizard.template.TemplateBuilder$thumb$2$1.invoke(TemplateDSL.kt:66)
    at com.android.tools.idea.npw.ui.ActivityGallery.getTemplateIcon(ActivityGallery.kt:38)
    at com.android.tools.idea.npw.project.ChooseAndroidProjectStep$NewTemplateRendererWithDescription.getIcon(ChooseAndroidProjectStep.kt:225)
    at com.android.tools.idea.npw.project.ChooseAndroidProjectStep$Companion$createGallery$1.invoke(ChooseAndroidProjectStep.kt:253)
    at com.android.tools.idea.npw.project.ChooseAndroidProjectStep$Companion$createGallery$1.invoke(ChooseAndroidProjectStep.kt:253)
    at com.android.tools.idea.npw.ui.WizardGallery$1.apply(WizardGallery.kt:34)
    at com.android.tools.idea.npw.ui.WizardGallery$1.apply(WizardGallery.kt:34)
    at com.android.tools.adtui.ASGallery.lambda$setIconProvider$0(ASGallery.java:307)
    at com.android.tools.adtui.ASGallery$ToOptionalFunction.apply(ASGallery.java:336)
    at com.android.tools.adtui.ASGallery$ToOptionalFunction.apply(ASGallery.java:323)
    at com.google.common.cache.CacheLoader$FunctionToCacheLoader.load(CacheLoader.java:165)
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3529)
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2278)
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2155)
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2045)
    at com.google.common.cache.LocalCache.get(LocalCache.java:3951)
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
    at com.android.tools.adtui.ASGallery.getCellIcon(ASGallery.java:357)
    at com.android.tools.adtui.ASGallery.access$300(ASGallery.java:72)
    at com.android.tools.adtui.ASGallery$GalleryCellRenderer.createCellRendererComponent(ASGallery.java:411)
    at com.android.tools.adtui.ASGallery$GalleryCellRenderer.getListCellRendererComponent(ASGallery.java:403)
    at com.intellij.ui.ExpandedItemListCellRendererWrapper.getListCellRendererComponent(ExpandedItemListCellRendererWrapper.java:24)
    at java.desktop/javax.swing.plaf.basic.BasicListUI.paintCell(BasicListUI.java:270)
    at com.intellij.ui.components.WideSelectionListUI.paintCell(WideSelectionListUI.java:64)
    at java.desktop/javax.swing.plaf.basic.BasicListUI.paintImpl(BasicListUI.java:378)
    at java.desktop/javax.swing.plaf.basic.BasicListUI.paint(BasicListUI.java:301)
    at com.intellij.ui.components.WideSelectionListUI.paint(WideSelectionListUI.java:33)
    at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
    at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:797)
    at com.intellij.ui.components.JBList.paintComponent(JBList.java:174)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
    at com.intellij.ui.components.JBList.paint(JBList.java:106)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JViewport.paint(JViewport.java:737)
    at com.intellij.ui.components.JBViewport.paint(JBViewport.java:241)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
    at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
    at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:246)
    at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
    at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
    at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
    at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
    at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1890)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:976)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:843)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:454)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:762)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$9(IdeEventQueue.java:453)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:497)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:117)
    at java.desktop/java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:190)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:235)
    at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:233)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.desktop/java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:233)
    at java.desktop/java.awt.Dialog.show(Dialog.java:1070)
    at com.intellij.openapi.ui.impl.DialogWrapperPeerImpl$MyDialog.show(DialogWrapperPeerImpl.java:694)
    at com.intellij.openapi.ui.impl.DialogWrapperPeerImpl.show(DialogWrapperPeerImpl.java:435)
    at com.intellij.openapi.ui.DialogWrapper.doShow(DialogWrapper.java:1715)
    at com.intellij.openapi.ui.DialogWrapper.show(DialogWrapper.java:1674)
    at com.android.tools.idea.actions.AndroidNewProjectAction.actionPerformed(AndroidNewProjectAction.kt:50)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:281)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAwareWithCallbacks(ActionUtil.java:275)
    at com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenActionsUtil.performAnActionForComponent(WelcomeScreenActionsUtil.java:99)
    at com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenActionsUtil$LargeIconWithTextWrapper.lambda$new$0(WelcomeScreenActionsUtil.java:128)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
    at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6635)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3342)
    at java.desktop/java.awt.Component.processEvent(Component.java:6400)
    at java.desktop/java.awt.Container.processEvent(Container.java:2263)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5011)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2321)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4918)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4547)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4488)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2307)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2772)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4843)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:772)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:95)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:743)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:976)
    at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.java:911)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:840)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$8(IdeEventQueue.java:454)
    at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:773)
    at com.intellij.ide.IdeEventQueue.lambda$dispatchEvent$9(IdeEventQueue.java:453)
    at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:828)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:507)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

However, in addition to this error message, I also have an error when using `copy` method : `resource relative to com.android.tools.idea.wizard.template.ModuleTemplateData not found.` As the two errors are quite similar I thought it was due to the resources not being placed in the right folder, but it does not seem to be the case.     

0

For `thumb` workaround is to use `thumb` property instead of `thumb()` function:

  thumb = {Thumb { URL("...") }} // works. You can also use helper com.android.tools.idea.wizard.template.TemplateHelpersKt#findResource
//thumb { File("thumb.png") } // does not work

Second one (ModuleTemplateData) is about copy indeed. To me this looks like a bug. Please report it to Android Studio issues tracker: https://issuetracker.google.com/issues/new?component=192708&template=840533

The problem is (in my opinion) that wrong context class is passed to `com.android.tools.idea.wizard.template.TemplateHelpersKt#findResource` when this method is invoked from an extension located outside the Android plugin. But I didn't find an easy way to force IDE using different context class.

0

As a workaround for `copy` method you can use plain java.io API, IntelliJ API (e.g., `com.intellij.openapi.fileEditor.FileDocumentManager`), or try `com.android.tools.idea.wizard.template.RecipeExecutor#save`. BTW, `copy` uses IntelliJ API underneath. See https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-main:android-templates/src/com/android/tools/idea/templates/recipe/DefaultRecipeExecutor.kt;l=291

0

Thanks to your two workarounds, I don't have these two issues anymore, and now everything works as expected, thank you.

0

Please sign in to leave a comment.