138 votes

Android - mise en œuvre de startForeground pour un service ?

Je ne suis donc pas sûr de savoir où/comment mettre en œuvre cette méthode pour faire fonctionner mon service en avant-plan. Actuellement, je démarre mon service par ce qui suit dans une autre activité :

Intent i = new Intent(context, myService.class); 
context.startService(i);

Et ensuite, dans le onCreate() de myServices, j'essaie le startForeground()... ?

Notification notification = new Notification();
startForeground(1, notification);

Donc oui, je suis un peu perdu et incertain de la façon de mettre en œuvre cette solution.

0 votes

Cela ne fonctionne pas, du moins pour autant que je puisse dire, mon service fonctionne toujours comme un service d'arrière-plan et est tué.

0 votes

14voto

Rohit Singh Points 1934

Si vous voulez faire de IntentService un service d'avant-plan

alors vous devez remplacer onHandleIntent() comme ceci

Override
protected void onHandleIntent(@Nullable Intent intent) {

    startForeground(FOREGROUND_ID,getNotification());     //<-- Makes Foreground

   // Do something

    stopForeground(true);                                // <-- Makes it again a normal Service                         

}

Comment faire une notification ?

simple. Voici le getNotification() Méthode

public Notification getNotification()
{

    Intent intent = new Intent(this, SecondActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);

    NotificationCompat.Builder foregroundNotification = new NotificationCompat.Builder(this);
    foregroundNotification.setOngoing(true);

    foregroundNotification.setContentTitle("MY Foreground Notification")
            .setContentText("This is the first foreground notification Peace")
            .setSmallIcon(android.R.drawable.ic_btn_speak_now)
            .setContentIntent(pendingIntent);

    return foregroundNotification.build();
}

Une compréhension plus approfondie

Que se passe-t-il lorsqu'un service devient un service de premier plan ?

Cela arrive

enter image description here

Qu'est-ce qu'un service d'avant-plan ?

Un service de premier plan,

  • s'assure que l'utilisateur est activement conscient que quelque chose se passe en arrière-plan. en fournissant la notification.

  • (le plus important) n'est pas tué par le système lorsqu'il manque de mémoire.

Un cas d'utilisation du service de premier plan

Mise en œuvre de la fonctionnalité de téléchargement de chansons dans une application musicale

9voto

Kush Points 695

Ajoutez le code suivant Classe de service pour "OS >= Build.VERSION_CODES.O". dans onCreate()

@Override
public void onCreate(){
    super.onCreate();

     .................................
     .................................

    //For creating the Foreground Service
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? getNotificationChannel(notificationManager) : "";
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
    Notification notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
           // .setPriority(PRIORITY_MIN)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .build();

    startForeground(110, notification);
}

@RequiresApi(Build.VERSION_CODES.O)
private String getNotificationChannel(NotificationManager notificationManager){
    String channelId = "channelid";
    String channelName = getResources().getString(R.string.app_name);
    NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
    channel.setImportance(NotificationManager.IMPORTANCE_NONE);
    channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    notificationManager.createNotificationChannel(channel);
    return channelId;
}

Ajouter cette permission dans le fichier manifeste :

 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

1voto

Ranvijay Points 538

Manipuler l'intention de startCommand de service en utilisant.

 stopForeground(true)

Cet appel retirer le service de l'état de premier plan ce qui permet de le tuer si l'on a besoin de plus de mémoire. Cela n'arrête pas le service de l'exécution. Pour cela, vous devez appeler stopSelf() ou des méthodes connexes.

Valeur de passage vrai o faux a indiqué si vous souhaitez supprimer la notification ou non.

val ACTION_STOP_SERVICE = "stop_service"
val NOTIFICATION_ID_SERVICE = 1
...  
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    super.onStartCommand(intent, flags, startId)
    if (ACTION_STOP_SERVICE == intent.action) {
        stopForeground(true)
        stopSelf()
    } else {
        //Start your task

        //Send forground notification that a service will run in background.
        sendServiceNotification(this)
    }
    return Service.START_NOT_STICKY
}

Gérer votre tâche lorsque on destroy est appelé par stopSelf() .

override fun onDestroy() {
    super.onDestroy()
    //Stop whatever you started
}

Créez une notification pour que le service continue à fonctionner en avant-plan.

//This is from Util class so as not to cloud your service
fun sendServiceNotification(myService: Service) {
    val notificationTitle = "Service running"
    val notificationContent = "<My app> is using <service name> "
    val actionButtonText = "Stop"
    //Check android version and create channel for Android O and above
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        //You can do this on your own
        //createNotificationChannel(CHANNEL_ID_SERVICE)
    }
    //Build notification
    val notificationBuilder = NotificationCompat.Builder(applicationContext, CHANNEL_ID_SERVICE)
    notificationBuilder.setAutoCancel(true)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_location)
            .setContentTitle(notificationTitle)
            .setContentText(notificationContent)
            .setVibrate(null)
    //Add stop button on notification
    val pStopSelf = createStopButtonIntent(myService)
    notificationBuilder.addAction(R.drawable.ic_location, actionButtonText, pStopSelf)
    //Build notification
    val notificationManagerCompact = NotificationManagerCompat.from(applicationContext)
    notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notificationBuilder.build())
    val notification = notificationBuilder.build()
    //Start notification in foreground to let user know which service is running.
    myService.startForeground(NOTIFICATION_ID_SERVICE, notification)
    //Send notification
    notificationManagerCompact.notify(NOTIFICATION_ID_SERVICE, notification)
}

Fournir un bouton d'arrêt sur la notification pour arrêter le service quand l'utilisateur en a besoin.

/**
 * Function to create stop button intent to stop the service.
 */
private fun createStopButtonIntent(myService: Service): PendingIntent? {
    val stopSelf = Intent(applicationContext, MyService::class.java)
    stopSelf.action = ACTION_STOP_SERVICE
    return PendingIntent.getService(myService, 0,
            stopSelf, PendingIntent.FLAG_CANCEL_CURRENT)
}

1voto

Remarque : si votre application vise le niveau 26 de l'API ou un niveau supérieur, le système impose des restrictions quant à l'utilisation ou à la création de services d'arrière-plan, sauf si l'application elle-même est au premier plan.

Si une application doit créer un service d'avant-plan, elle doit appeler startForegroundService() . Cette méthode crée un service d'arrière-plan, mais elle signale au système que le service va passer au premier plan.

Une fois que le service a été créé, il doit appeler sa fonction startForeground() method within five seconds.

0voto

Gunjan Points 139

Dans mon cas, c'était totalement différent puisque je n'avais pas d'activité pour lancer le service dans Oreo.

Voici les étapes que j'ai suivies pour résoudre ce problème de service en avant-plan.

public class SocketService extends Service {
    private String TAG = this.getClass().getSimpleName();

    @Override
    public void onCreate() {
        Log.d(TAG, "Inside onCreate() API");
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
            mBuilder.setSmallIcon(R.drawable.ic_launcher);
            mBuilder.setContentTitle("Notification Alert, Click Me!");
            mBuilder.setContentText("Hi, This is Android Notification Detail!");
            NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            // notificationID allows you to update the notification later on.
            mNotificationManager.notify(100, mBuilder.build());
            startForeground(100, mBuilder.mNotification);
        }
        Toast.makeText(getApplicationContext(), "inside onCreate()", Toast.LENGTH_LONG).show();
    }

    @Override
    public int onStartCommand(Intent resultIntent, int resultCode, int startId) {
        Log.d(TAG, "inside onStartCommand() API");

        return startId;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "inside onDestroy() API");

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

Et après cela, pour initier ce service, j'ai déclenché la commande cmd - ci-dessous.


adb -s " + serial_id + " shell am startforegroundservice -n com.test.socket.sample/.SocketService


Cela m'aide donc à démarrer le service sans activité sur les appareils Oreo :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X