web-dev-qa-db-fra.com

Android - implémentation de startForeground pour un service?

Donc, je ne sais pas où/comment implémenter cette méthode pour que mon service s'exécute au premier plan. Actuellement, je commence mon service par les éléments suivants dans une autre activité: 

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

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

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

Alors oui, je suis un peu perdu et incertain de la façon de mettre en œuvre cela.

98
JDS

Je commencerais par remplir complètement la Notification. Voici un exemple de projet démontrant l'utilisation de startForeground().

119
CommonsWare

Depuis votre activité principale, démarrez le service avec le code suivant:

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

Ensuite, dans votre service pour onCreate(), vous construirez votre notification et la définirez au premier plan, comme ceci:

Intent notificationIntent = new Intent(this, MainActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.app_icon)
                .setContentTitle("My Awesome App")
                .setContentText("Doing some work...")
                .setContentIntent(pendingIntent).build();

startForeground(1337, notification);
59
mikebertiean

Ceci est mon code pour définir le service au premier plan:

private void runAsForeground(){
    Intent notificationIntent = new Intent(this, RecorderMainActivity.class);
    PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
            notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK);

    Notification notification=new NotificationCompat.Builder(this)
                                .setSmallIcon(R.drawable.ic_launcher)
                                .setContentText(getString(R.string.isRecording))
                                .setContentIntent(pendingIntent).build();

    startForeground(NOTIFICATION_ID, notification);

}

Je dois créer une notification à l'aide de PendingIntent, afin de pouvoir démarrer mon activité principale à partir de la notification.

Pour supprimer la notification, appelez simplement stopForeground (true);

Il est appelé dans onStartCommand (). S'il vous plaît se référer à mon code à: https://github.com/bearstand/greyparrot/blob/master/src/com/xiong/richard/greyparrot/Mp3Recorder.Java

26
Richard

Solution pour Oreo 8.1

J'ai rencontré des problèmes tels que RemoteServiceException en raison d'un identifiant de canal non valide avec les versions les plus récentes d'Android. Voici comment je l'ai résolu: 

Activité :

override fun onCreate(savedInstanceState: Bundle?) {
    val intent = Intent(this, BackgroundService::class.Java)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(intent)
    } else {
        startService(intent)
    }
}

BackgroundService:

override fun onCreate() {
    super.onCreate()
    startForeground()
}

private fun startForeground() {

    val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channelId =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel()
            } else {
                // If earlier version channel ID is not used
                // https://developer.Android.com/reference/Android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(Android.content.Context)
                ""
            }

    val notificationBuilder = NotificationCompat.Builder(this, channelId )
    val notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(PRIORITY_MIN)
            .setCategory(Notification.CATEGORY_SERVICE)
            .build()
    startForeground(101, notification)
}


@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String{
    val channelId = "my_service"
    val channelName = "My Background Service"
    val chan = NotificationChannel(channelId,
            channelName, NotificationManager.IMPORTANCE_HIGH)
    chan.lightColor = Color.BLUE
    chan.importance = NotificationManager.IMPORTANCE_NONE
    chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
    val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    service.createNotificationChannel(chan)
    return channelId
}

Java EQUIVALENT

public class YourService extends Service {

    // Constants
    private static final int ID_SERVICE = 101;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

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

        // do stuff like register for BroadcastReceiver, etc.

        // Create the Foreground Service
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel(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(ID_SERVICE, notification);
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private String createNotificationChannel(NotificationManager notificationManager){
        String channelId = "my_service_channelid";
        String channelName = "My Foreground Service";
        NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        // omitted the LED color
        channel.setImportance(NotificationManager.IMPORTANCE_NONE);
        channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        notificationManager.createNotificationChannel(channel);
        return channelId;
    }
}
14
Rawa

En plus deRAWAanswer, cette paix de code: 

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent)
} else {
    startService(intent)
}

Vous pouvez changer pour:

ContextCompat.startForegroundService(context, yourIntent);

Si vous regardez à l'intérieur de cette méthode, vous constaterez que cette méthode effectue tout le travail de vérification pour vous.

8
Edgar Khimich

Si vous souhaitez faire d’IntentService un service de premier plan

alors vous devriez remplacer onHandleIntent()like 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 la méthode getNotification()

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();
}

Compréhension plus profonde

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

Ça arrive

 enter image description here

Qu'est-ce qu'un service de premier plan?

Un service de premier plan, 

  • s'assure que l'utilisateur est activement conscient du fait 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

Implémentation de la fonctionnalité de téléchargement de morceau dans une application musicale

6
Rohit Singh

Ajouter un code donné à la classe de service pour "OS> = Build.VERSION_CODES.O" in 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" />
1
Kush

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

Voici les étapes que j'ai utilisées pour résoudre ce problème de service de premier 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 lancer ce service, j’ai déclenché en dessous de cmd -


adb -s "+ ID_serveur +" Shell à commencer par le service principal -n com.test.socket.sample/.SocketService


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

0
Arpana

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

Si une application doit créer un service de premier plan, elle doit appeler startForegroundService(). Cette méthode crée un service en arrière-plan, mais la méthode indique au système que le service se présentera au premier plan. 

Une fois le service créé, le service doit appeler sa startForeground() method within five seconds.