也许标题有点误导。我的问题是我有一个 Android 库项目,它在两个标准 Android 项目之间共享:一个用于应用程序的免费版本,另一个用于付费版本。该库当前具有 ContentProvider 的代码,包括一个带有几个静态字符串变量的合同类,用于诸如 URI 和列名之类的内容。现在我希望 URI 的“权限”根据使用库的应用程序进行更改。想到的一种解决方案是将权限存储为字符串资源,并在运行时将该字符串加载到静态最终字符串变量中。但是,我不确定如何执行此操作,因为合同类有一个私有构造函数并且没有 Context 对象来加载字符串资源。还有哪些其他选项可以解决我的问题?
3 回答
对于那些使用较新版本的构建工具的人来说,这是一个更好的解决方案:使权限相对于您的应用程序 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
and com.example.app.free.provider
。
要在代码中引用提供者权限,请使用BuildConfig.APPLICATION_ID + ".provider"
.
如果用户尝试安装这两个版本,则对免费和付费版本使用不同的权限是有意义的。我正在为清单中的两个版本定义不同的权限,如下所示:
<provider
android:name="MyApp.MyProvider"
android:authorities="MyApp.MyProvider.free"
android:grantUriPermissions="true"/>
然后我在一个xml文件中配置provider(我使用了一个特殊的config.xml文件,因为我有更多的provider权限之类的配置数据,不过你当然可以使用strings.xml):
<string name="my_provider_authority">MyApp.MyProvider.free</string>
该代码检索提供者权限作为任何其他字符串资源。要在没有上下文的情况下访问字符串资源,请使用应用程序上下文。我正在使用应用程序类从我的应用程序中的任何位置访问应用程序上下文(但有两个例外):
public class MyApplication extends Application {
private static Context sContext;
@Override
public void onCreate() {
super.onCreate();
sContext = this;
}
public static Context getContext() {
return sContext;
}
}
当然,您需要在清单中定义 MyApplication。这允许您从应用程序中的任何位置访问字符串和其他资源。不过有两个例外:
- 内容提供者。ContentProviders 可以在应用程序启动之前启动,因此您将没有可用的应用程序上下文。不过这没问题,因为 ContentProviders 通过 getContext() 获取自己的上下文。
- 静态代码:上下文可能在 Android 组件(活动、片段、广播接收器、服务等)的生命周期之外不可用。因此,依赖于应用程序上下文的静态初始化器不是一个好主意。但这也不是一个真正的问题,因为无论如何都不允许在 Android 组件的生命周期之外使用上下文,并且总是会在该生命周期内调用访问上下文的静态方法。例如,如果一个 Activity 需要知道 ContentProvider 的权限,它会在你的合约类中调用一个静态方法,并且该调用将来自 Activity 的 onXYZ() 方法之一,如 onCreate() 或 onStart() ,这将确保上下文是初始化。因此,您需要做的就是延迟初始化合约类中的变量,并确保调用者只有在明确之前调用过 Application.onCreate() 时才检索变量。当然,您可以从活动中直接检索字符串资源。当您需要其他类/对象中的资源时,我的方法的真正优势将变得显而易见。这些对象仍将与某些 Android 组件的生命周期相关联,但您不必将上下文传递给所有这些对象,这 1)非常麻烦,2)在泄漏上下文时非常容易出错可能导致内存使用问题(Android 应用程序最常见的问题之一)。当然,您可以从活动中直接检索字符串资源。当您需要其他类/对象中的资源时,我的方法的真正优势将变得显而易见。这些对象仍将与某些 Android 组件的生命周期相关联,但您不必将上下文传递给所有这些对象,这 1)非常麻烦,2)在泄漏上下文时非常容易出错可能导致内存使用问题(Android 应用程序最常见的问题之一)。当然,您可以从活动中直接检索字符串资源。当您需要其他类/对象中的资源时,我的方法的真正优势将变得显而易见。这些对象仍将与某些 Android 组件的生命周期相关联,但您不必将上下文传递给所有这些对象,这 1)非常麻烦,2)在泄漏上下文时非常容易出错可能导致内存使用问题(Android 应用程序最常见的问题之一)。
为什么要改变权威?您不需要导出提供程序,这意味着除了解构应用程序之外,没有人可以看到授权名称。即使那样,他们也无法访问该提供商。
如果是为了您自己的内部方便,那么我会使用相同的权限,但在 URI 上设置不同的安全性。
简而言之,你的想法很有趣,但我不会那样做。太乱了