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.
- Permiso revocado android.permission.CALL_PHONE
- El número de llamada desde el teclado de marcación devuelve la advertencia: "Llamada requiere permiso que puede ser rechazado por el usuario"
- La acción de llamada de intención no funciona en Marshmallow
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.