getIdentifier not working to get id of resource - android

I am using getIdentifier to get the id of a raw resource by name. It is not working though, and I am certain to be using it correctly. Is there something that I am missing?
I have verified that the raw resources exist under the string I am giving it. I have also cleaned the project to make sure that R.java is correct.
id = ctx.getResources().getIdentifier("file_name", null , ctx.getPackageName());

Looks like the methods needs the type/ (or defType) param. Should be something like drawable or layout depending on the resource directory.
You can include it in the first String parameter :
id = ctx.getResources().getIdentifier("drawable/file_name", null , ctx.getPackageName());
or pass it as the second parameter :
id = ctx.getResources().getIdentifier("file_name", "drawable", ctx.getPackageName());
Also, be sure to exclude the file extension from the file name you're passing. If the methods still returns 0, check if file_name corresponds to an id somewhere in your R.java file.

Way late, but I think this issue is related to an incorrect application id.
It is configured in you app's module build.gradle file:
android{
defaultConfig {
applicationId "your application id goes here"
From what I have observered, It seems the packageName for the generated R file is base on the value of the packageName in the Manifest.xml file. However the context.GetPackageName seems to be returning the value of the configured applicationId. If they are the same, then there's no issue. If they are different than a call to resources.getIdentifier(…,..., ctx.getPackageName()) will fail to find the identifier.
I'm not sure that the above paragraph is totally correct. What I actually observed was that If I changed the applicationId to match name of the PackageName in the Manifest.xml file then the issue I had on not getting a resource identifier using the getIdentifer method went away. I have to admit, I was somewhat surprised that corrected my problem.

Related

Resources - NotFoundException when accessing literals

No one of the translated strings are working at this moment, so the app always take the main strings file key.
Debugging, if i try to see the id of a key it returns a value. For example R.string.app_name returns 1900088 but getString(R.string.app_name) returns Method threw 'android.content.res.Resources$NotFoundException' exception. with cause android.content.res.Resources$NotFoundException: String resource ID #0x1cfe38.
The strings files have no errors. I really dont know how to proceed with this
EDIT:
using the same files in a new project worked perfectly
OK, the problem was in the gradle for the app module. There was a resConfig "zz" than can lead to this. Removing this line avoids all translation problems

Are integer value of view IDs are always constant in android?

Are int value of R.id.view is always same?
I tried printed it in two devices and it was same.
I also changed name of id but still the value was same.
But will it stay the same in all scenarios?
For any particular app resource, the particular R class associated resource ID will be the same in all scenarios during runtime as this resource ID is generated by aapt during compile time.
From Android Documentation:
Once you provide a resource in your application, you can apply it by referencing its resource ID. All resource IDs are defined in your project's R class, which the aapt tool automatically generates. When your application is compiled, aapt generates the R class, which contains resource IDs for all the resources in your res/ directory.
Thus printing it in two devices will result the same int value, provided that the same apk is used. Also note that the resource id is final in the respective R subclass.
From this answer:
Note that aapt by default makes no attempt to keep these identifiers
the same between builds. Each time the resources change, they can all
get new identifiers. Each time they are built, a new R.java is created
with the current identifiers so your code gets the correct values.
Because of this, you must never persist resource identifiers anywhere
where they can be used across different builds of your app.
Any changes to the resource might make the resource get an new R class resource ID.
Based on the way in which the R class Resource ID are calculated, as described in that answer, I think since you only changed the name of the XML resource ID, and didn't change the type of the resource nor the placement of the respective View object declaration in the respective XML file, the same R class Resource ID is being calculated.
A View ID is generated during Compilation, so Yes the ID will be the same in each Device if the APK is the same. Pay attention that "different compilations could generate different IDs".

Android maven plugin: renameManifestPackage results in Resources$NotFoundException

I encountered the following problem:
The app I implemented includes another project as a dependency (of type aar). Both projects share the same parent pom. The dependency includes resources, which the app is using. To access the resources within the library project, the resource id is fetched by calling context.getResources().getIdentifier(resourceKey, resourceType, packageName). I get the package name by calling getPackageName() on the given context object.
Before changing the package names of the projects by using
<renameManifestPackage>com.example.newpackagename</renameManifestPackage>
accessing the library resources worked fine. But after renaming the package name of the app I get a android.content.res.Resources$NotFoundException because the getIdentifier() call still expects the old package name of the app and calling getPackageName() returns the new one (as expected).
Now I wonder if I'm missing something or if this a bug in the android maven plugin? https://github.com/simpligility/android-maven-plugin
The answer is: I missed something. I opened a ticket regarding this problem at the project site (https://github.com/simpligility/android-maven-plugin/issues/736). It turned out that what I've seen as a problem is expected behavior of the renameManifestPackage configuration, since renaming not only the manifest package but also the resources is out of scope for this configuration.
There is, however, a not too ugly workaround for this:
Instead of retrieving the package name from the Context object, it is possible to retrieve it from the Resources object. Here comes the part where it gets a bit ugly: A resource with the single purpose of retrieving the package name needs to be added since other resources are usually subjects to change:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- The only purpose of this resource is to retrieve the resource package name -->
<item name="used_for_package_name_retrieval" type="id"/>
</resources>
Now you can retrieve the resource package name as follows:
Resources resources = context.getResources();
String packageName = resources.getResourcePackageName(R.id.used_for_package_name_retrieval);
Credit goes to: http://www.piwai.info/renaming-android-manifest-package/

Using #string for android:authorities in a ContentProvider

I have a ContentProvider in my manifest, when I define them fully with hardcoded strings it works. E.g.
<provider android:name="com.myprovider" android:authorities="com.myprovider"/>
Works perfect, however the ContentProviders are in a library that gets used by multiple projects, and I don't want authority conflicts, so I attempted to do the following.
<provider android:name="com.myprovider" android:authorities="#string/myProviderAuthority">
This way I should be able to define all my authorities in a single strings.xml file and not have conflicts between apps since I should be able to change them using each apps resource override system.
However, it appears that when I try to build with #string, it gives me a malformed manifest error and says "Provider does not INCUDE (yes it says INCUDE) authorities tribute"
Can I not use a resource string for the authorities tribute, I feel sick everytime I need to maintain constants in two locations. Authority conflicts can be hard to catch by our QA dept, and I don't want things to become out of sync or it could cause confusion. Anybody have any ideas why my code isn't working?
I faced a similar problem but with the android:versionCode attribute. When I tried to define the version code in resources and use a reference to it in the manifest Android Market even forbade me to publish the application. The reason of such behavior turned out to be rather simple. Resources can change depending on current configuration and this value have to be the same in any case.
Probably, this is the reason why content providers with authority references do not work too. And it seems to me that it's not a good idea to use such a reference because there's no guarantee that there will be the only one value for an authority resource in an app. I understand that you can be careful enough to keep a single instance of this resource but there's no special compiler or system checks for this so it cannot be trusted.
Many manifest attributes cannot be specified as a reference to a string -- they must be specified as explicit string values.
The code that parses the manifest is in: frameworks/base/core/java/android/content/pm/PackageParser.java. That class calls, among others, getNonConfigurationString() and getNonResourceString() (which are implemented in: frameworks/base/core/java/android/content/res/TypedArray.java).
getNonConfigurationString() describes itself as:
Retrieve the string value of an attribute that is not allowed to change with the given configurations.
getNonResourceString() describes itself as:
Retrieve the string value for an attribute, but only if that string comes from an immediate value in an XML file. That is, this does not allow references to string resources, string attributes, or conversions from other types. As such, this method will only return strings that come from attributes in an XML file.
The manifest attributes that PackageParser doesn't allow to be taken from resources or from different configurations are listed below.
These attributes are defined in com.android.internal.R.styleable The manifest.xml element attribute name is usually the part of the name after the last '_' in the formal name. For example, the android:authorities attribute in a element in manifest.xml is AndroidManifestProvider_authorities, or com.android.internal.R.styleable.AndroidManifestProvider_authorities. (The number in the lists of attribute names below are the line number of the relevant code in version 4.1.1 of PackageParser.java)
Attributes read by getNonConfigurationString:
917: AndroidManifest_versionName
922: AndroidManifest_sharedUserId
2057: AndroidManifestActivity_parentActivityName
2071: AndroidManifestActivity_permission
2079: AndroidManifestActivity_taskAffinity
2247: AndroidManifestActivityAlias_targetActivity
2330: AndroidManifestActivityAlias_permission
2336: AndroidManifestActivityAlias_parentActivityName
1672: AndroidManifestApplication_name
1683: AndroidManifestApplication_manageSpaceActivity
1697: AndroidManifestApplication_backupAgent
1795: AndroidManifestApplication_permission
1800: AndroidManifestApplication_taskAffinity
1815: AndroidManifestApplication_process
3005: AndroidManifestData_mimeType
3017: AndroidManifestData_scheme
3023: AndroidManifestData_host
3025: AndroidManifestData_port
3031: AndroidManifestData_path
3037: AndroidManifestData_pathPrefix
3043: AndroidManifestData_pathPattern
2527: AndroidManifestGrantUriPermission_path
2533: AndroidManifestGrantUriPermission_pathPrefix
2539: AndroidManifestGrantUriPermission_pathPattern
2579: AndroidManifestPathPermission_permission
2581: AndroidManifestPathPermission_readPermission
2586: AndroidManifestPathPermission_writePermission
2615: AndroidManifestPathPermission_path
2622: AndroidManifestPathPermission_pathPrefix
2629: AndroidManifestPathPermission_pathPattern
2434: AndroidManifestProvider_authorities
2441: AndroidManifestProvider_permission
2443: AndroidManifestProvider_readPermission
2454: AndroidManifestProvider_writePermission
2713: AndroidManifestService_permission
2832: AndroidManifestMetaData_name
1225: AndroidManifestOriginalPackage_name
1981: (parsePackageItemInfo -- I can't tell list of all names)
3258: (Component constructor args.nameres -- I can't tell list of all names)
Attributes read by getNonResourceString:
1806: AndroidManifestApplication_taskAffinity
1821: AndroidManifestApplication_process
1632: AndroidManifestInstrumentation_targetPackage
2891: AndroidManifestPackageVerifier_name
2894: AndroidManifestPackageVerifier_publicKey
1512: AndroidManifestPermission_permissionGroup
1200: AndroidManifestProtectedBroadcast_name
1927: AndroidManifestUsesLibrary_name
1054: AndroidManifestUsesFeature_name
1004: AndroidManifestUsesPermission_name
3308: (Component constructor args.processRes -- I can't tell list of all names)
So, alot of attributes in the manifest.xml file must be specified as explicit string values (ie in quotes) rather than references to strings in strings.xml.

what does the "#+android:id/title" mean?

In normal, we should use #+id/ to define an id and use #id to reference an id. Today I found #+android:id/title in apps/settings/res/layout/preferenc_progress.xml.
How to understand it and how to use it?
It is used for resources that are shipped with the SDK.
You can take a look at them by browsing to
[PATH TO ANDROID SDK]/platforms/android-[VERSION]/data/res
By using the android in android.R.whatever you just specify the R file to look up. For more information you should read Accessing Platform Resources.
That belongs to the app preferences activity screen definition.
title and summary are standard Android fields of a TextView preference item.
I think it does the same thing. It's just a more formal way of saying it by specifying where the namespace is.
I've never met this way of giving id, but in theory this means adding new id title to android package. So you'll be able to use it in your code like android.R.id.title. But I'm not sure resource compiler will really create any id in android package. I think it can be used only with predefined ids. But I'll give you more precise answer later, when I'll be able to check it.
EDIT: I've checked it and found some differences. Firstly, if you define Android's id using #+android:id/some_id, which is already present in SDK, this id will not be defined in your R.java file. If it's not present in SDK, it will be defined in R.java, but with different kind of value. Secondly, if you'll try to convert id from its string representation to int value, Resources.getIdentifier() method will return 0 in case of #+android:id format.
This means it will create an id in your resource file.

Categories

Resources