Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: Copy resource files in the correct folder #1753

Open
3 tasks
GitToTheHub opened this issue Dec 21, 2024 · 6 comments
Open
3 tasks

Android: Copy resource files in the correct folder #1753

GitToTheHub opened this issue Dec 21, 2024 · 6 comments

Comments

@GitToTheHub
Copy link

GitToTheHub commented Dec 21, 2024

Bug Report

I want to copy resources to the res directory of the android app.

Problem

I followed the documentation for the resource-file tag of the config.xml, where it shows an example to copy a resource file to res/values/ for Android:

<resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" />

When I use this code, the resource file gets copied to platforms/android/res/values, but the correct folder would be platforms/android/app/src/main/res/values.

When I do the same for iOS with

<platform name="ios">
    <resource-file src="FooPluginStrings.xml" target="FooPluginStrings.xml" />
</platform>

It gets correctly copied to platforms/iOS/[AppName]/Resources (using cordova-ios 7.1.1).

Should there be not a similar behavior for Android? Must the documentation be updated to the correct path, or is this an issue in the Cordova-cli?

What is expected to happen?

The resource file should be put in the correct folder like the documentation says.

What does actually happen?

The resource file is copied in the wrong place.

Information

Command or Code

Environment, Platform, Device

Version information

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above
@dpogue
Copy link
Member

dpogue commented Dec 21, 2024

There's some history here that's worth knowing. The Android platform moved from being an Eclipse (ant) project to being an Android Studio (gradle) project, and the project structure changed. Previously, res was a top-level folder, but now it's nested under app/src/main.

To avoid breaking all the existing plugins, there's a remapping system in cordova-android that will take "old" paths and rewrite them to the newer paths. That remapping appears to be used unconditionally resource-file in plugins, but not for resource-file declarations in config.xml.

The workaround is to specify the full path that you want for the file, i.e. app/src/main/res/values/FooPluginStrings.xml

It's not feasible to automatically prefix all resource files with app/src/main (which is what plugins are doing) because that prevents app authors from doing something like copying a google-service.json file into the app folder.
Maybe we could add a check for target paths that start with res/ and remap those?

@GitToTheHub
Copy link
Author

I understand. On my opinion checking for res/ would be good, than it would be also backward compatible. The app developer should not care about the real res path, because the path can also change in future changes.

@dpogue dpogue transferred this issue from apache/cordova-docs Dec 21, 2024
@breautek
Copy link
Contributor

When I use this code, the resource file gets copied to platforms/android/res/values,

Android has a concept of build variants so i don't think it's a good idea to auto prefix and assume app/src/main.

app here is the module name, and main is the build type. Complex projects could make use of these.

So I think we should consider this a doc issue.

@GitToTheHub
Copy link
Author

Thank you @breautek, I didn't know about this. Could this path nevertheless automatically calculated for build variants? Is it really needed do decide in which build variant a resource file will be copied? Does cordova-android support build variants anyway?

@breautek
Copy link
Contributor

breautek commented Jan 1, 2025

Could this path nevertheless automatically calculated for build variants?

I don't think so. Android has a few reserved ones, main, androidTest (for connected android device/simulator testing), and test (unit tests that runs in a standard JVM, for code that doesn't depend on android SDKs). main is the default/fallback. All other build variants will get merged with main's assets and configurations.

So outside of those 3, the build variant name is entirely up to the developer. Cordova CLI only ever uses main and doesn't make use of build variants, not even the test variants, but it doesn't mean that complex projects adds their own build variants and projects using resource-file would assume current behaviour.

Even if we conditionally prefix and assume main build variant there is going to be a lot of ambiguity as android assets are split into several folders, depending on the purpose, for example:

  • res/values/x.xml
  • res/xml/x.xml
  • res/layouts/x.xml
  • res/drawable/x.xml

And each one of those directories can have variants as well, for localization, themes, device form factors, etc:

  • res/values-fr/x.xml (for french)
  • res/values-night/x.xml (for dark mode)

And each of these variants can be compounded, for example: res/values-fr-night/x.xml for dark mode, french locale device configuration, or res/values-fr-night-v24/x.xml for french, dark mode, on API 24+ devices. Android about 20 different variant types, so I trust you can see how this can be problematic.

I think if we WERE going to do any sort of prefixing, the path must begin with /res/... (or res/...) then we can assume app/src/main/ should be prefixed. Otherwise we should attempt to use the path as is. The resource type (xml, drawable, values, etc) must be explicitly defined along with the resource file name.

<resource-file src="Foo.xml" target="res/values/Foo.xml" /> <!-- goes to app/src/main/res/values/Foo.xml -->
<resource-file src="Foo.xml" target="/res/values/Foo.xml" /> <!-- goes to app/src/main/res/values/Foo.xml -->
<resource-file src="Foo.xml" target="app/src/main/res/xml/Foo.xml" /> <!-- goes to app/src/main/res/xml/Foo.xml -->
<resource-file src="Foo.xml" target="/bar/res/values/Foo.xml" /> <!-- goes to bar/res/values/Foo.xml which is not really a valid location -->
<resource-file src="Foo.xml" target="app/src/bar/res/values/Foo.xml" /> <!-- goes to app/src/bar/res/values/Foo.xml -->
<resource-file src="Foo.xml" target="foobar/src/main/res/values/Foo.xml" /> <!-- goes to foobar/src/main/res/values/Foo.xml which is valid only if something has created the foobar android module -->

The key point here is we should be careful not to prefix something seems be an absolute path to a particular android module and/or build variant.

Does cordova-android support build variants anyway?

We don't have any explicit directives or anything to create build variants but it can be done via <config-file> or <edit-config> or hooks, etc.

@GitToTheHub
Copy link
Author

GitToTheHub commented Jan 1, 2025

Hi @breautek,

thank you for your very detailed answer and explanation.

I know about these resource identifiers and my thought was also that the path should start with res. After this, the user can define, whatever he want.

When Cordova is used for building or preparing, I think it should know where the destination is, otherwise it could not build/prepare? So if Cordova knows it builds to android/app it can assume that res/[resource-path]must be copied to android/app/src/main/res[resource-path]. If Cordova is not used for building, then resource-file could not be used. If it is possible to build or prepare with Cordova to another build variant, other then main, it should know where to copy resource files?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants