在 ContentProvider 中使用 @string 作为 android:authorities 是什么意思?

20

我在清单文件中有一个ContentProvider,当我使用硬编码的字符串完全定义它们时,它可以工作。例如:

<provider android:name="com.myprovider" android:authorities="com.myprovider"/>

代码完美运行,但是ContentProviders是在一个被多个项目使用的库中,我不想出现权限冲突,因此我尝试了以下操作。

<provider android:name="com.myprovider" android:authorities="@string/myProviderAuthority">

我应该能够在单个strings.xml文件中定义所有权限,而不会因为每个应用程序都可以使用资源覆盖系统进行更改而导致冲突。

然而,当我尝试使用@string进行构建时,它会给出“malformed manifest error”错误,并说“Provider does not INCUDE authorities tribute”。

我不能使用资源字符串来表示权限吗?每次需要在两个位置上维护常量都让我感到很不舒服。对于我们的QA部门来说,权限冲突很难捕捉,我不想让事情变得不同步或者引起混乱。有人有任何想法,为什么我的代码不能工作吗?


1
我自己也遇到了这个问题,我发现在2.2+版本中这个方法可以正常工作。当然,如果有人指出如何在2.1及之前的版本中使其正常工作,那就太好了。 - dmon
我已经转移到字符串,但是你可以将android:minSdkVersion设置为7或其他目标,并使用较新的API作为构建目标,类似于将appsToSd编译为支持2.1的应用程序。 - HaMMeReD
我认为那样做不会起作用,因为实际的手机在安装时会出现问题,而编译时并不会失败。最终我用Maven手动替换了字符串。虽然很糟糕,但目前它可以工作。我想一旦2.1版本到达生命周期的尽头,我就可以把它改回来 :) - dmon
顺便提一下,provider 属性应该是 android:authorities(另请参阅http://developer.android.com/guide/topics/manifest/provider-element.html#auth)。 - scessor
@dmon “我最终用Maven手动替换了字符串” - 我需要这样做。我已经替换/覆盖了资源文件夹,那么我该如何替换auth字符串? - Aiden Fry
2个回答

11

我遇到了类似的问题,但是是针对android:versionCode属性。当我尝试在资源中定义版本代码并在清单文件中使用引用时,Android市场甚至禁止我发布应用程序。这种行为的原因相当简单,因为资源可以根据当前配置而更改,而此值在任何情况下都必须相同。

可能这就是授权引用的内容提供者也不起作用的原因所在。并且我认为不使用这样的引用是不太明智的,因为不能保证在应用程序中授权资源只有一个值。我知道你可以足够小心地保持此资源的单个实例,但是没有特殊的编译器或系统检查可供信任。


这是不启用它的一个很好的理由,但它显然在后续版本中可以工作,只是在2.1中不能工作,因此“一致性”不是它不能工作的原因。 - dmon

8
许多清单属性不能作为字符串引用指定,必须指定为明确的字符串值。
解析清单的代码位于:frameworks/base/core/java/android/content/pm/PackageParser.java。该类调用了其他方法,包括getNonConfigurationString()和getNonResourceString()(这些方法在frameworks/base/core/java/android/content/res/TypedArray.java中实现)。
getNonConfigurationString()自述如下:
Retrieve the string value of an attribute that is not allowed to change with the given configurations.

getNonResourceString()的描述如下:

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.

以下是PackageParser不允许从资源或不同配置中获取的清单属性列表。
这些属性在com.android.internal.R.styleable中定义。manifest.xml元素属性名称通常是正式名称中最后一个'_'之后的部分。例如,在manifest.xml中的元素中,android:authorities属性是AndroidManifestProvider_authorities,或者是com.android.internal.R.styleable.AndroidManifestProvider_authorities。(下面属性名称列表中的数字是PackageParser.java版本4.1.1中相关代码的行号)
由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)

通过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)

因此,manifest.xml文件中的许多属性必须指定为显式字符串值(即在引号中),而不是对strings.xml中字符串的引用。

1
我明白了。这个设计防止在某些情况下使用资源字符串。如果我在AndroidManifestProvider_authorities的清单中使用显式字符串,那么在应用程序中是否有一种方法可以访问该字符串,主要是为了在一个地方定义字符串并在整个应用程序中使用一致的字符串? - Les

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接