Android - 在应用项目中拥有提供商权限

一个 android 库项目包含一些提供程序,其权限在合约类中定义如下:

public static final String CONTENT_AUTHORITY = "my.com.library.providers.tester";
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

现在有很多应用程序项目使用此库项目。我目前遇到的问题是,对于每个应用程序项目,我需要在每个应用程序的库项目中都有一个单独的分支,只是为了拥有唯一的内容权限。这会产生一些版本管理问题(例如将功能/错误修复从一个分支传播到其他每个分支等)。相反,我想将定义内容权限的责任委派给应用项目。有没有办法做到这一点?


答案 1

我知道这是一个古老的话题,但今天遇到了这个问题,我们已经开发了很长一段时间,所以还没有准备好在我们的内容提供商合同中遍历所有静态并更改它们,也因为我们的内容提供商和数据库是由Eclipse的Mechanoid插件生成的(是的,我也是作者!:))

我想出的解决方案是将静态初始值设定项添加到我们生成的协定中,该协定使用反射来查找类,并在该类上使用静态CONTENT_AUTHORITY字段(如果存在,如果不能回退到默认值):

public class QuxContract  {
    public static final String CONTENT_AUTHORITY = initAuthority();

    private static String initAuthority() {
        String authority = "com.example.app.data.qux";

        try {

            ClassLoader loader = QuxContract.class.getClassLoader();

            Class<?> clz = loader.loadClass("com.example.app.data.QuxContentProviderAuthority");
            Field declaredField = clz.getDeclaredField("CONTENT_AUTHORITY");

            authority = declaredField.get(null).toString();
        } catch (ClassNotFoundException e) {} 
        catch (NoSuchFieldException e) {} 
        catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }

        return authority;
    }

    private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
// ...

现在,在每个链接到库项目的项目中,都可以提供自己的权限:

package com.example.app.data;

public class QuxContentProviderAuthority {
    public static final String CONTENT_AUTHORITY = "com.example.app.data.baz";
}

另外,不要忘记更改清单中的权限


答案 2

应用是唯一一个绝对需要了解权限的应用,因为它是使用属性在清单中声明 the 的应用。<provider>android:authorities

因此,原则上,只要您从提供程序中删除所有特定于权限的逻辑,它应该“正常工作”,例如:

  • 那些静态数据成员(现在移动到托管应用程序)
  • UriMatcher(自己滚动一些东西,不检查权威,但专注于其余的Uri)

如果出于某种原因,您绝对确定您的提供商需要知道其权限,则在将提供商用于实际工作之前,应用程序必须将其提供给提供商。可能的方法是:

  • 由于 a 是自然的单例,因此请将其分配给静态数据成员,然后通过自定义类中的自定义方法向其提供权限字符串(因为提供程序首先初始化,因此这应该有效)ContentProviderApplication

  • 如果仅支持 API 级别 11+,请使用 on 的自定义类向Applicationcall()ContentResolverContentProvider

  • 假设唯一真正的调用(例如,to , )是有效的,并且只是根据你看到的第一个进入的内容来懒惰地初始化你的权限。query()insert()Uri


推荐