通过自定义权限启用两个Android应用之间的通信

caw*_*caw 4 android android-intent android-permissions

我的一个Android应用程序需要一些在权限方面"危险"的功能.它们需要一些权限,例如"Internet访问",这些权限与私有数据相结合是至关重要的.

这就是为什么我要创建一个单独的"附加组件",即提供这些权限关键功能的第二个应用程序.因此,如果用户需要它们,他们可以安装附加组件,但主应用程序仍然可以在没有这些权限的情况下工作.

使用a sharedUserId显然是最简单的解决方案,但之后添加此功能,当许多用户已经使用该应用程序时,可能会导致严重的问题.这不意味着应用程序不能再访问自己的数据吗?

所以我必须选择另一种方法.ContentProviders是我试图避免的,因为在我看来,它们对于这种简单的需求来说太复杂了.

我认为自定义权限可以解决问题.他们可以吗?我已将以下权限声明添加到主应用程序以及作为manifest标记的子项的加载项AndroidManifest.xml:

<permission
    android:name="com.my.package.ADDON"
    android:label="@string/permission_title"
    android:description="@string/permission_description"
    android:permissionGroup="android.permission-group.PERSONAL_INFO"
    android:protectionLevel="signature" />
Run Code Online (Sandbox Code Playgroud)

此外,两个清单文件现在都有这个部分:

<uses-permission android:name="com.my.package.ADDON"></uses-permission>
Run Code Online (Sandbox Code Playgroud)

附加组件应用程序包含一个IntentService具有以下属性的应用程序:

android:permission="com.my.package.ADDON"
Run Code Online (Sandbox Code Playgroud)

不应该这样做,以便我可以IntentService通过此代码从我的主应用程序调用加载项?

Intent addonIntent = new Intent();
addonIntent.setClassName("com.my.package", "com.my.package.MyService");
startService(addonIntent);
Run Code Online (Sandbox Code Playgroud)

不幸的是,此调用始终失败,但出现以下异常:

E/AndroidRuntime(16721): java.lang.SecurityException: Not allowed to start service Intent { cmp=com.mypackage.addon/.MyService } without permission com.mypackage.permission.ADDON
Run Code Online (Sandbox Code Playgroud)

我做错了什么?非常感谢你提前!

添加#1 - 附加清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      android:versionCode="1"
      android:versionName="1.0"
      package="com.mypackage.addon">
    <uses-sdk android:minSdkVersion="8" />
    <permission
        android:name="com.mypackage.permission.ADDON"
        android:label="@string/permission_title"
        android:description="@string/permission_description"
        android:permissionGroup="android.permission-group.PERSONAL_INFO"
        android:protectionLevel="signature" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:permission="com.mypackage.permission.ADDON"
    android:exported="true">
    <service
        android:enabled="true"
        android:name=".MyService" />
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

添加#2 - 主应用程序清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      android:versionCode="1"
      android:versionName="1.0"
      package="com.mypackage.mainapp">
    <uses-sdk android:minSdkVersion="8" />
    <permission
        android:name="com.mypackage.permission.ADDON"
        android:label="@string/permission_title"
        android:description="@string/permission_description"
        android:permissionGroup="android.permission-group.PERSONAL_INFO"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.mypackage.permission.ADDON"></uses-permission>
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:name="MyApp">
    <activity android:name=".MainActivity" android:launchMode="singleTask" android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)

Com*_*are 5

这不意味着应用程序不能再访问自己的数据吗?

正确.

我添加了以下权限

我会抛弃permission-group,因为这不应该是必要的.

此外,两个清单文件现在已经有了这个部分

只有那个打电话给你的IntentService人才需要.

不应该这样做,以便我可以通过此代码从我的主应用程序调用加载项的IntentService?

如果IntentService没有导出则不行.确保你IntentService有一个<intent-filter>android:exported="true".我建议你去<intent-filter>路线,这样你就可以声明并使用自定义动作字符串,这样你就可以远离客户端应用中的硬编码包和类名.

这是一个使用这种基本方法的两个示例项目的目录,但在我的情况下,通信基于安全ContentProvider而非安全IntentService.但是,这个概念是相同的,所以通过这些小调整,我希望你正在做的工作得很好.