Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 动态设置ContentProvider的权限_Java_Android_Android Contentprovider - Fatal编程技术网

Java 动态设置ContentProvider的权限

Java 动态设置ContentProvider的权限,java,android,android-contentprovider,Java,Android,Android Contentprovider,也许这个标题有点误导。我的问题是,我有一个Android库项目,由两个标准的Android项目共享:一个是免费版本的应用程序,另一个是付费版本的应用程序。该库当前具有ContentProvider的代码,包括一个包含多个静态字符串变量的契约类,这些变量用于URI和列名等。现在,我希望URI的“权限”根据使用库的应用程序而改变。想到的一个解决方案是将权限存储为字符串资源,并在运行时将该字符串加载到静态final string变量中。但是,我不确定如何执行此操作,因为契约类有一个私有构造函数,并且没

也许这个标题有点误导。我的问题是,我有一个Android库项目,由两个标准的Android项目共享:一个是免费版本的应用程序,另一个是付费版本的应用程序。该库当前具有ContentProvider的代码,包括一个包含多个静态字符串变量的契约类,这些变量用于URI和列名等。现在,我希望URI的“权限”根据使用库的应用程序而改变。想到的一个解决方案是将权限存储为字符串资源,并在运行时将该字符串加载到静态final string变量中。但是,我不确定如何执行此操作,因为契约类有一个私有构造函数,并且没有上下文对象来加载字符串资源。还有什么其他选择可以解决我的问题?

为什么要更改权限?你不需要导出提供者,这意味着除了解构应用程序,没有人能看到授权名称。即使这样,他们也无法访问提供商

如果是为了您自己的内部便利,那么我会使用相同的权限,但在URI上设置不同的安全性


简言之,你的想法很有趣,但我不会那样做。太乱了。

如果用户试图安装两个版本,免费和付费版本使用不同的权限是有意义的。 我为清单中的两个版本定义了不同的权限,如下所示:

<provider
    android:name="MyApp.MyProvider"
    android:authorities="MyApp.MyProvider.free"
    android:grantUriPermissions="true"/>
当然,您需要在清单中定义MyApplication。 这允许您从应用程序中的任何位置访问字符串和其他资源。 但有两个例外:

  • 内容提供者。ContentProviders可以在应用程序启动之前启动,因此您将没有可用的应用程序上下文。但这没有问题,因为ContentProviders通过getContext()获得自己的上下文
  • 静态代码:在Android组件(活动、片段、广播接收器、服务等)的生命周期之外,上下文可能不可用。因此,依赖于应用程序上下文的静态初始值设定项不是一个好主意。但这也不是一个真正的问题,因为无论如何都不允许在Android组件的生命周期之外使用上下文,访问上下文的静态方法总是在该生命周期内调用。例如,如果某个活动需要知道ContentProvider的权限,它将在您的合同类中调用一个静态方法,该调用将来自该活动的onXYZ()方法之一,如onCreate()或onStart(),这将确保上下文已初始化。因此,您所需要做的就是惰性地初始化合同类中的变量,并确保调用方仅在明确之前调用过Application.onCreate()时才检索变量。当然,您可以从活动中直接检索字符串资源。当您需要其他类/对象中的资源时,我的方法的真正优势将变得显而易见。这些对象仍然与某些Android组件的生命周期有关,但您不必将上下文传递给所有这些对象,这1)非常麻烦,2)在泄漏上下文时非常容易出错,这可能导致内存使用问题(Android应用程序最常见的问题之一)

  • 对于使用较新版本的构建工具的用户,这里有一个更好的解决方案:使权限相对于您的应用程序ID。您可以使用
    ${applicationId}
    自动执行此操作,它在构建过程中被扩展到您的应用程序ID中

    <provider
        android:name=".MyContentProvider"
        android:authorities="${applicationId}.provider"/>
    
    
    
    假设您的应用程序ID是
    com.example.app.paid
    com.example.app.free
    。当您构建应用程序时,权限将相应地变成
    com.example.app.paid.provider
    com.example.app.free.provider


    要在代码中引用提供者权限,请使用
    BuildConfig.APPLICATION\u ID+“.provider”

    如果用户同时安装了两个版本,会发生什么情况?免费版本还公开只读提供者,以允许付费版本导入现有数据。最终,免费和付费版本中的提供者都将由游标加载程序在内部使用。如果我理解正确,我不需要为以后的用例添加标签,因为它是每个应用程序的内部标签。我的测试表明,即使提供商没有导出,权限也必须是全球唯一的(在电话上)。感谢您的建议。我认为创建一个应用程序子类听起来是一个不错的选择。当我从“contract”类中的静态初始值设定项调用
    MyApplication.getContext()
    时,需要注意哪些问题?另外,您能否在
    android:authorities
    属性中使用
    @string/my\u provider\u authority
    ,以减少重复?我修改了我的答案,以解决您对在静态初始值设定项中使用应用程序上下文的担忧。答案基本上是延迟初始化从字符串资源读取的变量,并确保您不会从应用程序生命周期之外调用getter方法。根据这个答案:您不应该使用@string引用来定义提供者的权限,但您可以(至少在安卓版本2.1以上)。但我同意那里的答案,即这是危险的,可能应该忽略。你介意检查我的答案,让我知道它是否回答了你的问题,或者是否有什么问题吗?@EmanuelMoecklin我培养了你的A,但自从我问了这个问题后,就没有时间玩我的应用。这是一个爱好应用程序,工作一直在妨碍我;-(一旦我有机会找出哪一个最有用,我会接受答案。感谢Android Studio和gradle构建链提供的功能更新。此外,我如何从
    public class MyApplication extends Application {
        private static Context sContext;
    
        @Override
        public void onCreate() {
            super.onCreate();
            sContext = this;
        }
    
        public static Context getContext() {
            return sContext;
        }
    }
    
    <provider
        android:name=".MyContentProvider"
        android:authorities="${applicationId}.provider"/>