Habilitar la comunicación entre dos aplicaciones de Android mediante permisos personalizados

Una de mis aplicaciones de Android necesita algunas características que son "peligrosas" cuando se trata de permisos. Requieren algunos permisos tales como "acceso a Internet" que son críticos en combinación con datos privados.

Esta es la razón por la que quiero crear una "Add-on", es decir, una segunda aplicación que proporciona estas características críticas de permiso. Así que si los usuarios quieren, pueden instalar el complemento, pero la aplicación principal seguirá funcionando sin esos permisos.

El uso de sharedUserId obviamente sería la solución más fácil, pero al agregar esto después, cuando muchos usuarios ya utilizan la aplicación, podría causar serios problemas. ¿Esto no significa que la aplicación no puede acceder a sus propios datos por más tiempo?

Así que tengo que elegir otro enfoque. ContentProviders es algo que intento evitar, porque son demasiado complejos para esta simple necesidad en mi opinión.

Pensé que los permisos personalizados podrían resolver el problema. ¿Pueden ellos? He añadido la siguiente declaración de permiso tanto a la aplicación principal como al complemento como un niño a la etiqueta de manifest en 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" /> 

Además, ambos archivos de manifiesto tienen esta parte ahora:

 <uses-permission android:name="com.my.package.ADDON"></uses-permission> 

La aplicación add-on incluye un IntentService que tiene el siguiente atributo ahora:

 android:permission="com.my.package.ADDON" 

¿No debería hacer esto el trabajo para que yo pueda llamar a la IntentService del IntentService de mi aplicación principal a través de este código?

 Intent addonIntent = new Intent(); addonIntent.setClassName("com.my.package", "com.my.package.MyService"); startService(addonIntent); 

Lamentablemente, esta llamada siempre falla con la siguiente excepción:

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

¿Qué hice mal? ¡Muchas gracias por adelantado!

Adición # 1 – manifiesto de complemento:

 <?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> 

Adición # 2 – manifiesto principal de la aplicación:

 <?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> 

    ¿Esto no significa que la aplicación no puede acceder a sus propios datos por más tiempo?

    Correcto.

    He añadido el siguiente permiso

    Dejaría el permission-group , ya que no debería ser necesario.

    Además, ambos archivos de manifiesto tienen esta parte ahora

    Sólo el que llama a IntentService podría necesitarlo.

    ¿No debería hacer esto el trabajo para que yo pueda llamar a la IntentService del complemento de mi aplicación principal a través de este código?

    No si ese IntentService no se exporta. Asegúrese de que su IntentService tiene un <intent-filter> o android:exported="true" . Yo recomendaría ir a la ruta <intent-filter> , por lo que puede declarar y utilizar una cadena de acción personalizada, por lo que se alejan de la codificación de paquetes y nombres de clase en la aplicación cliente.

    Aquí hay un directorio con dos proyectos de ejemplo usando este enfoque básico, aunque en mi caso las comunicaciones se basan en un ContentProvider seguro en lugar de un IntentService seguro. El concepto es el mismo, sin embargo, y así con estos pequeños ajustes, esperaría lo que está haciendo para trabajar bien.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.