Using @string for android:authorities in a ContentProvider
Asked Answered
R

2

20

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?

Rufe answered 23/6, 2011 at 23:24 Comment(5)
I just ran into this problem myself, and I found that this works just fine 2.2+. Of course, it would be great if someone pointed out how to get this to work in 2.1 and before.Pedroza
I've moved to strings, but perhaps you can use a newer API as a build target while setting android:minSdkVersion to 7 or whatever you are targetting, similar to getting appsToSd to compile into apps that support 2.1.Rufe
I don't think that will work, because it's the actual phones that complain when installing, it doesn't fail when compiling. I ended up replacing the string "manually" with Maven. It sucks but it works, for now. I guess I can take it back once 2.1 reaches end of life :)Pedroza
By the way, the provider-attribute should be android:authorities (see also http://developer.android.com/guide/topics/manifest/provider-element.html#auth).Connubial
@Pedroza "I ended up replacing the string "manually" with Maven" - I need to do this. I already replace/override the resource folder how would i repleace the auth string?Vinson
L
11

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.

Lustring answered 12/7, 2011 at 20:25 Comment(1)
This is a good reason for no enabling it, but it clearly works in later versions, just not 2.1, so "consistency" is not the reason it doesn't work.Pedroza
B
8

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.

Balustrade answered 3/9, 2014 at 16:57 Comment(1)
I get it. The design prevents using resource strings in certain cases. If I use and explicit string in the manifest for AndroidManifestProvider_authorities, is there a way in the App that I can access that string, mainly for the sake of defining the string in one place and using a consistent string throughout?Cocteau

© 2022 - 2024 — McMap. All rights reserved.