将PreferenceScreen与applicationIdSuffix一起使用

时间:2015-06-29 11:22:59

标签: android gradle android-manifest preferenceactivity

我在使PreferenceScreenapplicationIdSuffix一起工作时遇到了一些问题。

假设我的应用包/ applicationId在Gradle和AndroidManifest.xml中为com.myappapplicationIdSuffix定义为:

buildTypes {
    debug {
        applicationIdSuffix '.dev'
    }
}

如果我将PreferenceScreen定义为以下

<PreferenceScreen
    android:key="key_about" android:summary="something" android:title="About">
    <intent
        android:targetClass="com.myapp.activities.AboutActivity"
        android:targetPackage="com.myapp" />
</PreferenceScreen>

启动应用程序的调试版本时出现异常

java.lang.SecurityException: Permission Denial: starting Intent { (...) } from ProcessRecord{(...)} (pid=13658, uid=10105) not exported from uid 10067

这是有道理的,因为我正在尝试从其他应用程序启动一个活动。问题是我无法找到Android启动正确活动的方法。

如果我将targetClass更改为“.activities.AboutActivity”,它仍然无法找到活动

ActivityNotFoundException: Unable to find explicit activity class {com.myapp.dev/.activities.AboutActivity}

我甚至尝试使用正确的包为每个版本定义一个值:

android:targetClass="@string/classname"
android:targetPackage="@string/packagename"

但找不到合适的活动:

ActivityNotFoundException: Unable to find explicit activity class
    {com.myapp.dev/com.myapp.dev.activities.AboutActivity};
have you declared this activity in your AndroidManifest.xml?

那么我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:5)

您的困惑来自于applicationIdSuffix仅更改应用程序的包名称(其唯一ID),但不会更改应用程序内类的java包名称,包括您的活动。

这意味着您应该在您的偏好中声明:

android:targetClass="com.myapp.activities.AboutActivity"
android:targetPackage="@string/packagename"

targetClass始终相同,而targetPackage取决于您的构建类型,可以是com.myappcom.myapp.dev

答案 1 :(得分:0)

我在我的应用程序中执行的操作是在其主机活动中将onPreferenceClickListener附加到首选项,并在该侦听器的onPreferenceClick方法中构建intent。通过从代码生成意图,您可以直接引用目标类,并且不会出现包的问题。

答案 2 :(得分:0)

除了AndroidManifest(在applicationId中可用)之外,目前没有直接方法将有效的${applicationId}包含在其他XML文件中,因此您需要为其创建一个字符串属性。 / p>

由于gradle applicationId的值根据风味而变化,因此不能直接使用它来定义string属性。相反,您需要在afterEvaluate中创建一个build.gradle规则以为所有变体生成它:

afterEvaluate {
    android.applicationVariants.all { variant ->
        variant.resValue 'string', 'application_id', variant.applicationId
    }
}

这将创建一个@string/application_id(或R.string.application_id),您可以在需要的地方使用它,例如在您的布局/首选项XML中(类名称无需更改,因为它基于所有口味都相同的java包):

<PreferenceScreen
    android:key="key_about" android:summary="something" android:title="About">
    <intent
        android:targetClass="com.myapp.activities.AboutActivity"
        android:targetPackage="@string/application_id" />
</PreferenceScreen>

此解决方案基于https://gist.github.com/Takhion/74b67cb518e90faf2708,该解决方案还提供了提供者属性。