Can I use a build.gradle generated String in strings.xml? - android

Our app name is defined in my build.gradle flavors as
appNameFlavor{
resValue "string", "app_name", "MyApp"
}
This is necessary due to a trademark issue in another country.
The name is also used a lot in our strings.xml file by using
<!DOCTYPE resources [
<!ENTITY appname "MyApp">
]>
<resources>
<string name="activity_intro" translatable="true">&appname; Tour</string>
</resources>
This is not ideal because the string is hard coded and needs to be switched for every flavor.
I tried using #strings/app_name instead of MyApp in the entity and while Android Studio actually rendered it correctly, the build failed.
There are several StackOverflow answers mentioning that I should use <!ENTITY % ents SYSTEM "./res/raw/entities.ent"> instead and simply create those files for each flavor, but the file cannot be resolved.
How could I solve this issue of having a variable app name without putting all the strings that reference the app name into a flavor specific strings.xml file, preferably sticking to the way the app name is currently defined?

Related

Android instrumented test - test resource not resolved

I want to have androidTest resources specific to each app flavor. I found an answer on this site that indicated you can just make a resource directory androidTestFlavorName and it will be managed like all the other resources. So I have a directory app/src/androidTestFlavorName/res/values and a file strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="test_sec_code">aStringValue</string>
</resources>
I have a test class app/src/androidTest/java/com/company/package/StartupTest.kt. In that class:
val code = context.getString(R.string.test_sec_code)
test_sec_code is red, so the IDE doesn't like it, and the compiler reports: Unresolved reference: test_sec_code
My selected build variant is flavorNameDebug. So am I setting up these resources wrong, or is my goal not possible?
Edit:
I tried putting the resource in app/src/androidTest/res/values/strings.xml and it can't be found there either. Surely there must be a way to define test resources right? Hello, is this thing on?

Get application Id in XML dynamically

I'm using shortcuts in my application and I have multiple product flavors. I want to get the application Id dynamically for target package.
I've given ${applicationId}, but it's not working. I tried with ${packageName} didn't work. any other alternative?
<shortcut
android:enabled="true"
android:icon="#drawable/ic_barcode_icon"
android:shortcutId="bar_code"
android:shortcutShortLabel="#string/shortcuts_my_bar_code">
<intent
android:action="android.intent.action.VIEW.myBarCode"
android:targetClass="com.appemirates.clubapparel.home.HomeActivity"
android:targetPackage="${applicationId}" />
</shortcut>
Manifest placeholders like ${applicationId} are only supported for the manifest, not arbitrary other XML files, such as shortcut metadata resources.
You could try:
Have a copy of your shortcut XML in each product flavor's source set, where that copy has the hardcoded application ID
Use resValue in Gradle to set up a string resource with the application ID (per flavor), and use #string/... notation to refer to it in the shortcut XML
The first one definitely works but is tedious due to the code duplication. I have not tried the second one.
Otherwise, you would be looking at building your own Gradle plugin or similar processor that could dynamically generate these resources from a template.
you can create BuildConfig parameter through gradle.
You need to add below in specific build flavor
resValue "string", "APP_ID", "com.example.myapp.india"
that will generate string resource as per your build flavor.And you can directly use it as below in your code.
<shortcut
android:enabled="true"
android:icon="#drawable/ic_barcode_icon"
android:shortcutId="bar_code"
android:shortcutShortLabel="#string/shortcuts_my_bar_code">
<intent
android:action="android.intent.action.VIEW.myBarCode"
android:targetClass="com.appemirates.clubapparel.home.HomeActivity"
android:targetPackage="#string/APP_ID" />
</shortcut>
Let me know for more help :)
In your app's build.gradle.kts (Gradle Kotlin DSL) you could add:
android {
// your setup...
androidComponents {
onVariants { variant ->
variant.resValues.put(
variant.makeResValueKey("string", "app_id"),
ResValue(variant.applicationId.get())
}
}
}
Which will write a string into the resources with the name app_id and use the application ID of the variant. You will then be able to reference the string resource using #string/app_id inside your XML resource files. ${applicationId} unfortunately only works in Manifest files, as has been mentioned in the other answers.
This solution should also work with flavours and build types which augment the application ID by using applicationIdSuffix, and thus answers the comment from Get application Id in XML dynamically.

String resources are removed after build

I have a project with following locale values directory:
values
values-en-rHK
values-en-rTH
values and values-en-rHK contains:
<string name="currency">$</string>
values-en-rTH contains:
<string name="currency">฿</string>
After the APK is compiled, it removed the currency key from the values-en-rHK directory. I have verified this by decompiling the APK and looking into the resources.
This causes the app to show ฿, even when the locale is en-HK. Also noticed that all the strings with same text as in values were removed from values-en-rHK in the compiled APK.
Your localized directories are not named correctly. They should follow the pattern specified here:
<resource type>-b+<language code>[+<country code>]
I'm not entirely sure what you were attempting, the following could possibly work:
values
values-b+en+HK
values-b+en+TH
Values that are identical in different localization versions may be removed when compiling the APK, since there is no point to have the same value in multiple resources.

Cannot build the contacts app in android open source project with android studio

The first error I got was the String.xml file contains more than one items with same name. It seems to be a common pattern across almost all the system apps you can check it here
The string value will have this format:
<string name="photoPickerNotFoundText" products="xxx">string value</string>
where xxx could be "tablet" or "default", etc.
How could I set up the Gradle to get the project built on my machine?
Thank!
UPDATE
I think that the solution is using the --product option of the aapt (android asset packaging tool). The current gradle android plugin doesn't support this aapt's option yet so maybe modifying the plugin could be a work around.
Every string should be identified by a unique ID. So you could not use same name for every string.
For example the below code wouldn't allow the gradle to build the project
<string name="abc" products="xxx">string value</string>
<string name="abc" products="xxx">string value</string>
Change one of the string ID as shown below
<string name="abc" products="xxx">string value</string>
<string name="def" products="xxx">string value</string>
Update: "You cannot use same string name while building from Eclipse. This type of naming is used only for building apps preloaded on platform. The correct string resource is preloaded according to PRODUCT_CHARACTERISTICS defined for a specific target build."
Reference: Android resource for a specific product

Android Lint: how to ignore missing translation warnings in a regional locale string file that purposely only overrides some default translations?

Is it possible to translate some strings, but not all, in a separate resource file without Lint complaining about MissingTranslation?
For example: my app's strings are all in res/values/strings.xml. One of the strings is
<string name="postal_code">Postal Code</string>
Since "postal code" is usually called "zip code" in the US, I want to add another resource res/values-en-rUS/strings.xml with contents:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="postal_code">Zip Code</string>
</resources>
However, Lint complains about other strings in values/strings.xml but not in values-en-rUS/strings.xml
I realize you can suppress the warnings by specifying tools:ignore in values/strings.xml. But this is undesirable because the Lint warning is actually useful when translating to another language.
Instead, is it possible to suppress the warning in the values-en-rUS/strings.xml file, as in, telling Lint not to use that file as criteria when looking for missing translations?
A nice way to disable MissingTranslations check is to add the option in module specific build.gradle file .
android {
lintOptions{
disable 'MissingTranslation'
}
//other build tags
}
If the strings are not present in locale specific Strings file, it will take the strings from the default file which generally is strings.xml.
I found a better solution according to this answer: https://stackoverflow.com/a/13797364/190309
Just add ignore="MissingTranslation" to your string.xml, for example:
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation" >
<!-- your strings here; no need now for the translatable attribute -->
</resources>
Lint supports partial regional translations, but needs to know what language the default strings are. That way, it can distinguish a partial regional translation from missing translations in a different locale.
To specify the locale in values/strings.xml:
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="en">
Quote from the lint command-line tool, when running lint --show:
By default this detector allows regions of a language to just provide a
subset of the strings and fall back to the standard language strings. [...]
You can tell lint (and other tools) which language is the default language
in your res/values/ folder by specifying tools:locale="languageCode" for
the root <resources> element in your resource file. (The tools prefix
refers to the namespace declaration http://schemas.android.com/tools.)
Source: https://android.googlesource.com/platform/tools/base/+/master/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/TranslationDetector.java#88
Add the locale specification to your default language file, and you shouldn't get that error for en-rUS, but will still be informed of any other missing translations.
This seems to not answered yet, so I show you one solution:
In your DEFAULT xml file, you can define strings, that don't need translations like following:
<string name="developer" translatable="false">Developer Name</string>
This string does not need to be translated and lint will not complain about it either...
This is a Swiss knife answer, so you can ignore the missing translations message depending on which situation you are:
Ignore all MissingTranslation message:
Edit your build.gradle file:
android {
lintOptions{
disable 'MissingTranslation'
}
}
Ignore all MissingTranslation messages in a concrete resources.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation">
<!-- your strings here; no need now for the translatable attribute -->
</resources>
Ignore MissingTranslation message for only one string:
<string name="developer" translatable="false">Developer Name</string>
If you are using Eclipse, please look at the toolbar buttons of the Lint warnings view. One of them is called "Ignore in file". This should help, but only if Lint assigns the error to your "US" file. That button simply modifies the lint.xml file in your project, so you can investigate (and undo) that easily.
More details about that file specific suppression are at http://tools.android.com/tips/lint/suppressing-lint-warnings
For the lint configuration file lint.xml:
<issue id="MissingTranslation" severity="ignore" />
If case of using gradle 7 :
lint {
disable("MissingTranslation")
}

Categories

Resources