Android instrumented test - test resource not resolved - android

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?

Related

Android Runtime Resource Overlay with custom attributes

I'm trying to use the Runtime Resource Overlay (RRO) mechanism to overlay an xml resource, which is using custom attributes and custom namespace. When building the overlay APK the aapt2 (link) throws an attribute not found error.
How do I make known the custom attribute from the main application to the overlay?
Is it even possible to use custom attributes in an overlay?
Details:
The overlay contains of two files:
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.test.simpleappoverlay">
<overlay
android:targetPackage="de.test.simpleapp"
android:targetName="Test"/>
</manifest>
and the xml file res/xml/my_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<MyConfig xmlns:app="http://schemas.android.com/apk/res/de.test.simpleapp"
app:text="hello">
</MyConfig>
<!-- I also tried: xmlns:app="http://schemas.android.com/apk/res-auto" -->
The main application defines the attribute text in res/values/attrs.xml:
...
<declare-styleable name="MyConfig">
<attr name="text" format="string" />
</declare-styleable>
Furthermore it defines the overlayable tag in res/values/overlayable.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<overlayable name="Test">
<policy type="public">
<item type="xml" name="my_config"/>
</policy>
</overlayable>
</resources>
To build the overlay I do this:
aapt2 compile -v --dir app/src/main/res/ -o SimpleAppOverlay.flata
and
aapt2 link -v --no-resource-removal
-I ~/Library/Android/sdk/platforms/android-29/android.jar
--manifest app/src/main/AndroidManifest.xml
-o sao.apk SimpleAppOverlay.flata
Which leads to the following output:
note: including /Users/bernd/Library/Android/sdk/platforms/android-29/android.jar
aapt2 W 09-01 14:33:06 20083 694697 ApkAssets.cpp:138] resources.arsc in APK '/Users/bernd/Library/Android/sdk/platforms/android-29/android.jar' is
compressed
note: linking package 'de.test.simpleappoverlay' using package ID 7f note: merging archive SimpleAppOverlay.flata
note: merging 'xml/my_config' from compiled file app/src/main/res/xml/my_config.xml
note: enabling pre-O feature split ID rewriting AndroidManifest.xml:
note: writing to archive (keep_raw_values=false)
note: writing AndroidManifest.xml to archive
note: linking app/src/main/res/xml/my_config.xml (de.test.simpleappoverlay:xml/my_config)
app/src/main/res/xml/my_config.xml:2: error: attribute text (aka
de.test.simpleappoverlay:text) not found
error: failed linking file resources.
I had a similar problem to this where I was trying to overlay an app with custom attributes in Android 10 and have a solution. There are two changes that are needed:
Part 1
It looks like your app name is de.test.simpleapp so your my_config.xml file should look like:
<?xml version="1.0" encoding="utf-8"?>
<MyConfig xmlns:app="http://schemas.android.com/apk/prv/res/de.test.simpleapp"
app:text="hello">
</MyConfig>
The important piece is specifying the 'prv/res/app.packagename' so it uses the namespace of the base app for the private attributes. If you used 'apk/res-auto' that would not work as it resolves to the name of your app (which in this case is the overlay app de.test.simpleappoverlay) which does not contain the definition of the private attributes.
Part 2
Since you now have a dependency on the main app when linking, you have to include it in the link command with a -I simpleapp.apk (or whatever the APK name is of the base app). Right now you are just including android.jar in the aapt2 link step which only contains the 'android' namespace and attributes. Therefore, you now need to add your base app in the include step so it can link properly against its namespace and attributes.
Like some of the other answers said though, this problem goes away in Android 11, but if you're stuck on Android 10 like I am hopefully this helps.
I don't think including new ids is supported in the current implementation of the RROs (at least in Android Q).
Regarding your error, aapt uses the android.jar to generate the apk for your overlay. Since it cannot find your new attribute, it throws an error. For this to work I believe you would need to use a modified android.jar including your attribute. One way of doing this is by modifying the Android SDK in the AOSP and creating your own version that you would then use for the aapt command.
Some time ago I switched my AOSP environment from Android 10 to 11. Google made quite a few changes to the Overlay mechanism. To my big surprise these changes fixed the problems I had when trying to "overlay" custom attributes.
With the Android 10 environment I observed while debugging that the Android XML parser returns "null" when trying to read the mentioned attributes. With idmap I was able to confirm that the attributes were present in the overlay and the target app, and that they were properly mapped.
Also all the linker errors were gone.

Espresso: How to use R.string resources of androidTest folder

I want to put data in xml file of androidTest/res/values/string.xml folder. I have created the file say test.xml with below contents.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="test">hello</string>
</resources>
When i am trying to access the field test via R.string.test. It is not accessible and says "cannot resolve symbol test". Can someone please advice me here.
This is how you do it:
import com.my.example.test.R;
Resources resources = InstrumentationRegistry.getContext().getResources();
String terms = resources.getString(R.string.test);
androidx.test.platform.app.InstrumentationRegistry is deprecated use androidx.test.core.app.ApplicationProvider
val targetContext = ApplicationProvider.getApplicationContext<Context>()
val test: String = targetContext.resources.getString(R.string.test)
I have a longstanding Android library project in which I had renamed my sources' package at some point from a.b.c.d to a.b.c but I had forgot to change the package value in my library's AndroidManifest.xml file likewise. This led to some confusion when I added a res/values/strings.xml file to my library's androidTest folder but I was unable to see an a.b.c.test.R object in my test classes.
The solution for me was to rename the package value in my library's AndroidManifest.xml file to match my sources' package (i.e. a.b.c). I am now able to see an a.b.c.test.R object in my test classes and I am able to access the string resources defined in androidTest/res/values/strings.xml via the InstrumentationRegistry.getInstrumentation().context.getString(resId:) method.

R.java is not being created?

I dowloaded google-play-services from sdk manager and copy pasted all the code from admob samplebut it is not working. Everything seems perfect only errors produced are R can't be resolved to a variable.
Here is a sample error
Error: No resource found that matches the given name (at 'text' with value '#string/load_interstitial').
Here is strings.xml file
<resources>
<string name="app_name">Google Ads SDK Sample</string>
<string name="ad_unit_id">INSERT_YOUR_AD_UNIT_ID_HERE</string>
<string name="load_interstitial">Load Interstitial</string>
<string name="interstitial_not_ready">Interstitial Not Ready</string>
<string name="banner_in_xml">Banner in XML</string>
<string name="banner_in_code">Banner in Code</string>
<string name="interstitial">Interstitial</string>
</resources>
Try to delete the import line import com.your.package.name.app.R, then, any resource calls such as mView= (View) mView.findViewById(R.id.resource_name); will highlight the 'R' with an error, a 'Quick fix' will prompt you to import R, and there will be at least two options:
android.R
your.package.name.R
Select the R corresponding to your package name, and you should be good to go. Hope that helps.
Or.....second region,
Each time I had a problem with R not been generated, or even disappeared, this was due to some problem in the XML layout file that prevented the application from being built.
The error in res folder cause missing of R.java filevso please check your res folder for any error.
The error may be with image too any capital letter or blank space can cause missing of R.java file.
Also check all the XML file ,error with res files only

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")
}

Setting android:versionName as reference to string resource leads to NullPointerException under the emulator

I'm trying to set the android:versionName in my android manifest as a reference to string resource stored in external resource file.
Below is an excerpt from my AndroidManifest.xml:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.toycorporation"
android:versionCode="#integer/version_code"
android:versionName="#string/version_name"
>
and the content of build.xml file located under res/values disrectory of my project:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item type="string" name="build_date">03/15/2012</item>
<item type="integer" name="version_code">315281</item>
<item type="string" name="version_name">3.15.28.1</item>
</resources>
Later I attempt to retrieve the version number to display it on the About screen of my application.
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(),0);
Log.d("PackageInfo", "Version name: " + String.valueOf(packageInfo.versionName));
Problem description:
When I build the application and automatically install it on my HTC device everything works perfect. Version name gets passed by reference and on the About screen I get version name value logged in the logcat.
But when I attempt to build the application and launch it on the emulator I get null instead of the version name value.
I have already tried to build and install the app to emulator using Eclipse and IDEA.
So it seems the issue is not related to IDE.
UPDATE:
One additional thing appeared which doesn't work with such use of versionName and versionCode. Application can not be deployed to the Google Play. The following error appears:
The file is invalid: ERROR getting 'android:versionCode' attribute:
attribute is not an integer value
I think there is a mix of issues with this approach / how you are using it.
1.) if you can compile and upload the APK to the android market and the correct version number and name is used then you are able to use resource references for the android:versionCode="#integer/version_code" android:versionName="#string/version_name"
If you can't then you shouldn't be using rerences.
2.) If you are going to take this approach, why then try to retrieve them from the packageinfo over using getResources().getString(R.string.version_name)?
All in all I don't see much of an advantage of this approach beyond being able to swap out a resources file by a build box. In which case you may need to for the latter approach to populate your about screen.
You can set versionName in manifest as a reference to string resource, but not versionCode.
This should work. in dimensions.xml add the following.
<resources>
<item name="version_number" format="float" type="dimen">2.8</item>
<item name="version_code" format="integer" type="dimen">8</item>
</resources>
In your manifest add the following.
android:versionCode="#dimen/version_code"
android:versionName="#dimen/version_number"

Categories

Resources