将 PreferenceScreen 与 applicationIdSuffix 一起使用
Using PreferenceScreen with applicationIdSuffix
我在 PreferenceScreen
和 applicationIdSuffix
协同工作时遇到了一些问题。
假设我的应用程序包/applicationId
在Gradle和AndroidManifest.xml中是com.myapp
,并且applicationIdSuffix
定义为:
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
这是有道理的,因为我正在尝试从不同的应用程序启动 activity。问题是我找不到 Android 启动正确 activity.
的方法
如果我将 targetClass
更改为“.activities.AboutActivity”,它仍然找不到 activity
ActivityNotFoundException: Unable to find explicit activity class {com.myapp.dev/.activities.AboutActivity}
我什至尝试用正确的包为每个版本定义一个值:
android:targetClass="@string/classname"
android:targetPackage="@string/packagename"
但是找不到合适的activity:
ActivityNotFoundException: Unable to find explicit activity class
{com.myapp.dev/com.myapp.dev.activities.AboutActivity};
have you declared this activity in your AndroidManifest.xml?
那么我怎样才能使它起作用呢?
您的困惑来自以下事实:applicationIdSuffix
仅更改应用程序的包名称(其唯一 ID),但不会更改您的 类 的 java 包名称在应用程序内部,包括您的 Activity.
这意味着您应该在您的偏好中声明:
android:targetClass="com.myapp.activities.AboutActivity"
android:targetPackage="@string/packagename"
其中 targetClass
始终相同,而 targetPackage
取决于您的构建类型,可以是 com.myapp
或 com.myapp.dev
。
我在我的应用程序中所做的是将 onPreferenceClickListener
附加到其宿主 activity 中的首选项,并在该侦听器的 onPreferenceClick
方法中构建意图。通过从代码生成意图,您直接引用目标 class 并且包的问题永远不会出现。
目前没有直接的方法将有效的 applicationId
包含到其他 XML 文件中,而不是 AndroidManifest(它以 ${applicationId}
的形式提供),因此您需要创建一个字符串 属性 为它。
因为gradleapplicationId
的值是根据风味变化的,不能直接用它来定义字符串属性。相反,您需要在 build.gradle
中创建一个 afterEvaluate
规则来为所有变体生成它:
afterEvaluate {
android.applicationVariants.all { variant ->
variant.resValue 'string', 'application_id', variant.applicationId
}
}
这将创建一个 @string/application_id
(或 R.string.application_id
),您可以在任何需要的地方使用它,例如在您的布局/首选项中 XML(不需要更改 class 名称,因为它基于对所有口味都相同的 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,后者还提供了提供程序 属性。
我在 PreferenceScreen
和 applicationIdSuffix
协同工作时遇到了一些问题。
假设我的应用程序包/applicationId
在Gradle和AndroidManifest.xml中是com.myapp
,并且applicationIdSuffix
定义为:
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
这是有道理的,因为我正在尝试从不同的应用程序启动 activity。问题是我找不到 Android 启动正确 activity.
的方法如果我将 targetClass
更改为“.activities.AboutActivity”,它仍然找不到 activity
ActivityNotFoundException: Unable to find explicit activity class {com.myapp.dev/.activities.AboutActivity}
我什至尝试用正确的包为每个版本定义一个值:
android:targetClass="@string/classname"
android:targetPackage="@string/packagename"
但是找不到合适的activity:
ActivityNotFoundException: Unable to find explicit activity class
{com.myapp.dev/com.myapp.dev.activities.AboutActivity};
have you declared this activity in your AndroidManifest.xml?
那么我怎样才能使它起作用呢?
您的困惑来自以下事实:applicationIdSuffix
仅更改应用程序的包名称(其唯一 ID),但不会更改您的 类 的 java 包名称在应用程序内部,包括您的 Activity.
这意味着您应该在您的偏好中声明:
android:targetClass="com.myapp.activities.AboutActivity"
android:targetPackage="@string/packagename"
其中 targetClass
始终相同,而 targetPackage
取决于您的构建类型,可以是 com.myapp
或 com.myapp.dev
。
我在我的应用程序中所做的是将 onPreferenceClickListener
附加到其宿主 activity 中的首选项,并在该侦听器的 onPreferenceClick
方法中构建意图。通过从代码生成意图,您直接引用目标 class 并且包的问题永远不会出现。
目前没有直接的方法将有效的 applicationId
包含到其他 XML 文件中,而不是 AndroidManifest(它以 ${applicationId}
的形式提供),因此您需要创建一个字符串 属性 为它。
因为gradleapplicationId
的值是根据风味变化的,不能直接用它来定义字符串属性。相反,您需要在 build.gradle
中创建一个 afterEvaluate
规则来为所有变体生成它:
afterEvaluate {
android.applicationVariants.all { variant ->
variant.resValue 'string', 'application_id', variant.applicationId
}
}
这将创建一个 @string/application_id
(或 R.string.application_id
),您可以在任何需要的地方使用它,例如在您的布局/首选项中 XML(不需要更改 class 名称,因为它基于对所有口味都相同的 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,后者还提供了提供程序 属性。