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

Java Android-在应用程序项目中拥有提供商权限,java,android,android-contentprovider,android-library,authority,Java,Android,Android Contentprovider,Android Library,Authority,android库项目包含几个提供者,其权限在合同类中定义如下: public static final String CONTENT_AUTHORITY = "my.com.library.providers.tester"; private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); 现在有很多应用程序项目使用这个库项目。我目前面临的问题是,对于每个应用程序项目,我都需要在库

android库项目包含几个提供者,其权限在合同类中定义如下:

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

现在有很多应用程序项目使用这个库项目。我目前面临的问题是,对于每个应用程序项目,我都需要在库项目中为每个应用程序设置一个单独的分支,以获得唯一的内容授权。这造成了一些版本管理问题(比如将特性/错误修复从一个分支传播到另一个分支等等)。相反,我想将定义内容权限的责任委托给应用程序项目。有什么方法可以做到这一点吗?

该应用程序是唯一一个绝对需要了解权限的应用程序,因为它是在清单中用
android:authorities
属性声明
的应用程序

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

  • 那些静态数据成员(现在移动到托管应用程序)
  • UriMatcher
    (自己滚动一些不检查权限的内容,但关注剩余的
    Uri
如果出于某种原因,您绝对确定您的提供商需要了解其权限,那么应用程序必须在提供商用于实际工作之前向提供商提供该权限。可能的方法包括:

  • 由于
    ContentProvider
    是一个自然的单例,因此将其分配给静态数据成员,然后通过自定义
    应用程序
    类中的自定义方法向其提供权限字符串(因为首先初始化了提供程序,所以这应该可以工作)

  • 如果您仅支持API级别11+,请让自定义
    应用程序
    类在
    ContentResolver
    上使用
    call()
    ContentProvider
    提供权限

  • 假设只有真正的调用(例如,到
    query()
    insert()
    )是有效的,只需根据您看到的第一个
    Uri
    中的内容初始化您的权限


我知道这是一个老话题,但今天遇到了这个问题,我们已经开发了相当长的一段时间,所以还没有准备好检查我们的内容提供商合同中的所有静态内容并对其进行更改,这也是因为我们的内容提供商和DB是由生成的(是的,我也是作者!)

我提出的解决方案是在生成的契约中添加一个静态初始值设定项,该契约使用反射来查找类,并在该类上使用一个静态CONTENT\u 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);
// ...

另外,别忘了更改您的舱单中的权限也

这可能是的副本,但到目前为止还没有人回答。我几乎回答完这个问题了。。。然后我看到“1个新答案”弹出,当然是Commonware,它的答案涵盖了我提到的所有内容和更多内容。只是我的运气…:P@AlexLockwood:对不起。如果这能让你感觉好一点,我也一样。此外,当这种事情发生时,不要害怕直接发布你的答案。与现有答案相比,你的措辞或其他东西可能会与提问者产生更好的共鸣。此外,如果你费尽周折输入(大部分)答案,你也可以发表它。我明白了。我在考虑在编译时修改代码。这不是一种可能性吗?如果这是可能的,那么它将比这种方法简单。@500865:“这不是一种可能性吗?”--嗯,不太容易,除非你要滚动你自己的Ant任务或制作库副本的东西,调整源代码,调整托管应用程序的
项目.properties
以指向副本,等等。“如果这是可能的,那么它将比这种方法简单。”——我认为在编译时修改代码将要复杂几个数量级。毕竟,基于第一个
查询()
,等等。调用应少于10行代码。上述解决方案对我都不起作用:1.更正ContentProvider是单例的,但如果在具有小部件的库中使用ContentProvider,现在用户将不会打开应用程序将小部件放在屏幕上,因此ContentProvider权限将不会用公共静态常量初始化nt.2.ContentResolver的call方法I不能按照@DraškoKokić的建议使用:3.如果我在做query()呢来自库本身而非应用程序的调用在这种情况下,第三个解决方案也无法与我实现的解决方案接近。感谢分享!!谢谢,现在我可以发布了!@Ian Warwick事实上我是Android新手我与Android Studio为我工作同样的权限问题你能通过一些示例帮助我吗?这个解决方案很简单太棒了!非常感谢
package com.example.app.data;

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