android - disable - NotificationListenerService con RemoteController.OnClientUpdateListener se bloquea en API18(4.3)
hide notification apk (2)
El problema
Quiero implementar la nueva API RemoteController , que se ha introducido con API19 (Kitkat, 4.4) . La API requiere que implemente una clase que se extiende desde NotificationListenerService (introducido con API18) e implementa la interfaz RemoteController.OnClientUpdateListener . (Puede encontrar más información sobre cómo implementar todo esto aquí y puede encontrar un ejemplo de proyecto muy útil aquí )
Todo funciona como debería en mi dispositivo API19 (Kitkat, 4.4) y en cualquier otro dispositivo API <18. Sin embargo, el problema es que la aplicación se bloquea de inmediato en API18 (Jelly Bean, 4.3), porque se está enviando el "android.service.notification.NotificationListenerService" y se inicia RemoteService, que luego bloquea la aplicación al instante con la siguiente Stacktrace:
05-24 09:32:48.945 893-893/com.example E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to instantiate service com.example.RemoteService: java.lang.ClassNotFoundException: Didn''t find class "com.example.RemoteService" on path: DexPathList[[zip file "/data/app/com.example-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.example-1, /system/lib]]
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2561)
at android.app.ActivityThread.access$1600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1338)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn''t find class "com.example.RemoteService" on path: DexPathList[[zip file "/data/app/com.example-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.example-1, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2558)
at android.app.ActivityThread.access$1600(ActivityThread.java:141
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1338)
...
Esto se debe al simple hecho de que RemoteController y, por lo tanto, la interfaz implementada RemoteController.OnClientUpdateListener no está disponible en API18, pero NotificationListenerService sí lo está. La intención no se envía en todos los dispositivos
Lo que he intentado hasta ahora
- Ponga otra capa de abstracción y cree una simple comprobación "if (API> = 19)". Intenté hacer esto usando un segundo NotificationListenerService vacío que funcionaría como un tipo de servicio de llamada directa. Pondría ese segundo servicio en mi AndroidManifest, para que reciba el intento en su lugar, y luego pondría la marca "if (API> = 19)" en su onCreate y comenzaría mi RemoteService real desde allí. El resultado es que mi aplicación no se cuelga más (yay). Desafortunadamente, tampoco funciona en API19 Kitkat :(. Creo que es porque tengo que registrar mi RemoteService como un oyente en mi AndroidManifest directamente, o de lo contrario no recibirá nada.
Fragmentos de código
RemoteService.java:
public class RemoteService extends NotificationListenerService
implements RemoteController.OnClientUpdateListener {
...
}
AndroidManifest.xml:
<manifest ...>
<application ...>
<service android:name="com.example.RemoteService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
Simplemente deshabilite el servicio con android: enabled = "false", luego en Application.onCreate habilítelo si el dispositivo ejecuta KitKat o una versión más reciente.
La solución
Coloque un bool en un archivo xml en valores y valores-v19. Establézcalo en false en values y en true en values-v19. Ahora configure la etiqueta "android: enabled" de NotificationListenerService en este bool.
./values/bool_switches.xml:
<resources>
<bool name="remotecontrollerservice_enabled">false</bool>
</resources>
./values-v19/bool_switches.xml:
<resources>
<bool name="remotecontrollerservice_enabled">true</bool>
</resources>
./AndroidManifest.xml:
...
<service android:name=".services.RemoteControllerService"
android:label="@string/scrobblingservice_string"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:enabled="@bool/remotecontrollerservice_enabled">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService"/>
</intent-filter>
</service>
...