¿Cómo iniciarForeground () sin mostrar notificación?

Quiero crear un servicio y hacerlo funcionar en primer plano.

La mayoría de los códigos de ejemplo tienen notificaciones. Pero no quiero mostrar ninguna notificación. ¿Es eso posible?

¿Me puede dar algunos ejemplos? ¿Hay alguna alternativa?

Mi servicio de aplicación está haciendo mediaplayer. Cómo hacer que el sistema no mate mi servicio, excepto que la aplicación lo mate solo (como pausar o detener la música con el botón).

    Como característica de seguridad de la plataforma Android, no puede , bajo ninguna circunstancia, tener un servicio prioritario sin tener una notificación. Esto se debe a que un servicio foregrounded consume una mayor cantidad de recursos y está sujeto a diferentes restricciones de progtwigción (es decir, no se elimina tan rápido) que los servicios en segundo plano, y el usuario necesita saber qué es lo que posiblemente se está comiendo la batería. Entonces, no hagas esto.

    Sin embargo, es posible tener una notificación “falsa”, es decir, puede crear un icono de notificación transparente (iirc). Esto es extremadamente falso para sus usuarios, y no tiene ninguna razón para hacerlo, aparte de matar su batería y crear malware.

    Actualización: esto fue “arreglado” en Android 7.1. https://code.google.com/p/android/issues/detail?id=213309

    Desde la actualización 4.3, es básicamente imposible iniciar un servicio con startForeground() sin mostrar una notificación.

    Sin embargo, puede ocultar el icono con las API oficiales … no es necesario un ícono transparente: (Use NotificationCompat para admitir versiones anteriores)

     NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setPriority(Notification.PRIORITY_MIN); 

    He hecho las paces con el hecho de que la notificación en sí misma todavía necesita estar allí, pero para quienes quieran ocultarla, es posible que haya encontrado una solución alternativa para eso también:

    1. Inicie un servicio falso con startForeground() con la notificación y todo.
    2. Inicie el servicio real que desea ejecutar, también con startForeground() (mismo ID de notificación)
    3. Detenga el primer servicio (falso) (puede llamar a stopSelf() y en ontroy call stopForeground(true) ).

    Voilà! Sin notificación alguna y su segundo servicio sigue en funcionamiento.

    Aquí está mi implementación de la técnica en la respuesta de Lior Iluz .

    Tenga en cuenta que esto ya no funciona en Android 7.1. También tenga en cuenta que esta técnica podría interpretarse como una violación de las políticas de desarrollador de Google Play ( Apps that introduce or exploit security vulnerabilities. ).

    Código

    ForegroundService.java

     public class ForegroundService extends Service { static ForegroundService instance; @Override public void onCreate() { super.onCreate(); instance = this; if (startService(new Intent(this, ForegroundEnablingService.class)) == null) throw new RuntimeException("Couldn't find " + ForegroundEnablingService.class.getSimpleName()); } @Override public void onDestroy() { super.onDestroy(); instance = null; } @Override public IBinder onBind(Intent intent) { return null; } } 

    ForegroundEnablingService.java

     public class ForegroundEnablingService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (ForegroundService.instance == null) throw new RuntimeException(ForegroundService.class.getSimpleName() + " not running"); //Set both services to foreground using the same notification id, resulting in just one notification startForeground(ForegroundService.instance); startForeground(this); //Cancel this service's notification, resulting in zero notifications stopForeground(true); //Stop this service so we don't waste RAM. //Must only be called *after* doing the work or the notification won't be hidden. stopSelf(); return START_NOT_STICKY; } private static final int NOTIFICATION_ID = 10; private static void startForeground(Service service) { Notification notification = new Notification.Builder(service).getNotification(); service.startForeground(NOTIFICATION_ID, notification); } @Override public IBinder onBind(Intent intent) { return null; } } 

    AndroidManifest.xml

       

    Compatibilidad

    Probado y trabajando en:

    • Emulador oficial
      • 4.0.2
      • 4.1.2
      • 4.2.2
      • 4.3.1
      • 4.4.2
      • 5.0.2
      • 5.1.1
      • 6.0
      • 7.0
    • Sony Xperia M
      • 4.1.2
      • 4.3
    • Samsung galaxia ?
      • 4.4.2
      • 5.X
    • Genymotion
      • 5.0
      • 6.0
    • CyanogenMod
      • 5.1.1

    Ya no funciona a partir de Android 7.1.

    Puedes usar esto:

      Notification note = new Notification( 0, null, System.currentTimeMillis() ); note.flags |= Notification.FLAG_NO_CLEAR; startForeground( 42, note ); 

    como lo sugirió @Kristopher Micinski

    —–ACTUALIZAR

    Tenga en cuenta que esto ya no está permitido con las versiones de Android KitKat +. Y tenga en cuenta que esto es más o menos violatorio del principio de diseño en Android que hace que las operaciones en segundo plano sean visibles para los usuarios como lo menciona @Kristopher Micinski

    Simplemente configure la ID de su notificación a cero:

     // field for notification ID private static final int NOTIF_ID = 0; ... startForeground(NOTIF_ID, mBuilder.build()); NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIF_ID); ... 

    Un beneficio que puede obtener es que un Service podrá funcionar con alta prioridad sin ser destruido por el sistema Android, a menos que tenga mucha memoria.

    EDITAR

    Para que funcione con Pre-Honeycomb y Android 4.4 y versiones posteriores, asegúrese de utilizar NotificationCompat.Builder que proporciona la Biblioteca de soporte v7, en lugar de Notification.Builder .

    Establecí el parámetro de icono en el constructor para Notificación a cero, y luego pasé la notificación resultante a startForeground (). No hay errores en el registro y no aparece ninguna notificación. No sé, sin embargo, si el servicio fue exitosamente enfocado, ¿hay alguna manera de verificarlo?

    Editado: comprobado con dumpsys, y de hecho el servicio está en mi sistema 2.3. Aún no he verificado con otras versiones del sistema operativo.

    Hay una solución. Intente crear una notificación sin configurar el icono, y la notificación no se mostraría. No sé cómo funciona, pero sí 🙂

      Notification notification = new NotificationCompat.Builder(this) .setContentTitle("Title") .setTicker("Title") .setContentText("App running") //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification); 

    la notificación del servicio de ocultación de la versión 4.3 (18) y superior no es posible, pero puede deshabilitar el icono, la versión 4.3 (18) y abajo es posible ocultar la notificación

     Notification noti = new Notification(); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) { noti.priority = Notification.PRIORITY_MIN; } startForeground(R.string.app_name, noti); 

    Encontré en Android 8.0 que todavía es posible al no usar un canal de notificación.

     public class BootCompletedIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent notificationIntent = new Intent(context, BluetoothService.class); context.startForegroundService(notificationIntent); } else { //... } } } } 

    Y en BluetoothService.class:

      @Override public void onCreate(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent notificationIntent = new Intent(this, BluetoothService.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification notification = new Notification.Builder(this) .setContentTitle("Title") .setContentText("App is running") .setSmallIcon(R.drawable.notif) .setContentIntent(pendingIntent) .setTicker("Title") .setPriority(Notification.PRIORITY_DEFAULT) .build(); startForeground(15, notification); } } 

    No se muestra una notificación persistente, sin embargo, verá la notificación de Android ‘x aplicaciones se están ejecutando en segundo plano’.

    Bloquear la notificación del servicio en primer plano

    A partir de Android 7.1, no parece haber ningún truco / error que pueda utilizar para hacer esto. Por lo tanto, debe indicar al usuario que desactive la notificación del servicio de primer plano en la configuración de Android.

    Cómo

    Android 4.1 a 7.1 (inclusive)

    Creo que la única forma es deshabilitar todas las notificaciones de su aplicación.

    1. Use una intención para enviar al usuario a la pantalla de detalles de su aplicación:

       Uri uri = Uri.fromParts("package", getPackageName(), null); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri); startActivity(intent); 
    2. Luego, haz que el usuario bloquee las notificaciones de la aplicación desde allí.

    Tenga en cuenta que esto también bloquea los brindis de su aplicación.

    Android 8:

    Desafortunadamente, si el usuario bloquea la notificación del servicio, Android lo reemplazará con una notificación de ” {Nombre de la aplicación} se está ejecutando en el fondo “. Entonces no tiene mucho sentido esconderlo.

    Aquí hay una manera de hacer que el oom_adj de su aplicación sea 1 (Probado en el emulador ANDROID 6.0 SDK). Agregue un servicio temporal. En su servicio principal, llame a startForgroundService(NOTIFICATION_ID, notificion) . Y luego inicie la llamada de servicio temporal startForgroundService(NOTIFICATION_ID, notificion) con el mismo ID de notificación nuevamente, después de un tiempo en la llamada de servicio temporal stopForgroundService (true) para descartar la ontificación de onging.

    Desarrollé un simple jugador de medios hace unos meses. Entonces, lo que creo es si estás haciendo algo como:

     Intent i = new Intent(this, someServiceclass.class); 

    startService (i);

    Entonces, el sistema no debería poder matar su servicio.

    referencia : lea el párrafo que discute cuando el sistema detiene el servicio

    También puede declarar su aplicación como persistente.

       

    Esto esencialmente establece su aplicación en una prioridad de memoria más alta, disminuyendo la probabilidad de que sea asesinado.