Android - Service de démarrage au moment du démarrage


109

J'ai besoin de démarrer un service au démarrage. J'ai beaucoup cherché. Ils parlent de Broadcastreceiver. Comme je suis nouveau dans le développement Android, je n'ai pas eu une image claire des services sur Android. Veuillez fournir du code source.


25
@ user244540: Veuillez ne pas "démarrer un service au moment du démarrage" avec l'intention de le faire fonctionner indéfiniment, à moins qu'il ne fournisse continuellement de la valeur (par exemple, un client VOIP). Dans ces cas, utilisez startForeground()dans votre service. Sinon, Android et ses utilisateurs tueront votre service comme un gaspillage d'espace et vous obtiendrez des commentaires désagréables sur l'Android Market. La plupart des situations où vous pensez que vous souhaitez qu'un service démarre au moment du démarrage, il est préférable de l'utiliser AlarmManagerpour que votre service puisse s'exécuter périodiquement plutôt qu'en continu .
CommonsWare

2
@CommonsWare: Bon point. Cependant, notez que pour démarrer les exécutions périodiques AlarmManageraprès le redémarrage, vous devez suivre des étapes très similaires (la différence étant dans le contenu de la onReceiveméthode)
stanwise

1
@CommonsWare: Très bon commentaire, je suis tombé sur cette question et votre indice correspond exactement à ma situation. Si c'était une réponse, je l'aurais votée :-)
chiccodoro

Réponses:


95

Créez un BroadcastReceiveret enregistrez-le pour recevoir ACTION_BOOT_COMPLETED . Vous avez également besoin de l' autorisation RECEIVE_BOOT_COMPLETED .

Lire: Écouter et diffuser des messages globaux et définir des alarmes


2
qu'en est-il du réveil? pendant le démarrage du service, l'appareil peut décider de s'endormir ...
Marian Paździoch

Dois-je démarrer mon mobile au moins une fois pour démarrer un service?
pathe.kiran

@ MarianPaździoch a raison; vous avez besoin d'un verrou de réveil. Voir ma réponse ci-dessous: stackoverflow.com/a/30970167/473201
phreakhead


Votre dernière URL est obsolète
Prizoff

192

Votre récepteur:

public class MyReceiver extends BroadcastReceiver {   

    @Override
    public void onReceive(Context context, Intent intent) {

     Intent myIntent = new Intent(context, YourService.class);
     context.startService(myIntent);

    }
}

Votre AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.broadcast.receiver.example"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">

        <activity android:name=".BR_Example"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    <!-- Declaring broadcast receiver for BOOT_COMPLETED event. -->
        <receiver android:name=".MyReceiver" android:enabled="true" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

    </application>

    <!-- Adding the permission -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

</manifest>

5
Le lien vers l'article est mort mais l'exemple de code est tout ce dont vous avez besoin de toute façon, donc +1 :)
Alex

3
En fait, il a besoin de peu d'amélioration, vous devez utiliser wakelock dans le récepteur, sinon il y a peu de chance que votre service ne démarre pas.
Vladimir Ivanov

Dois-je démarrer mon mobile au moins une fois pour que cela fonctionne?
pathe.kiran

1
Non, mais vous devez exécuter l'application au moins une depuis Android 3.0
Vladimir Ivanov

Cela fonctionne-t-il si l'application est fermée de force à partir des paramètres? L'application se réveillera-t-elle toujours?
Srihari Karanth

32

Il est possible d'enregistrer votre propre service d'application pour démarrer automatiquement lorsque l'appareil a été démarré. Vous en avez besoin, par exemple, lorsque vous souhaitez recevoir des événements push d'un serveur http et que vous souhaitez informer l'utilisateur dès qu'un nouvel événement se produit. L'utilisateur n'a pas besoin de démarrer l'activité manuellement avant que le service ne démarre ...

C'est assez simple. Donnez d'abord à votre application l'autorisation RECEIVE_BOOT_COMPLETED. Ensuite, vous devez enregistrer un BroadcastReveiver. Nous l'appelons BootCompletedIntentReceiver.

Votre Manifest.xml devrait maintenant ressembler à ceci:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.jjoe64">
 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 <application>
  <receiver android:name=".BootCompletedIntentReceiver">
   <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
   </intent-filter>
  </receiver>
  <service android:name=".BackgroundService"/>
 </application>
</manifest>

Comme dernière étape, vous devez implémenter le récepteur. Ce récepteur démarre simplement votre service d'arrière-plan.

package com.jjoe64;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.jjoe64.BackgroundService;

public class BootCompletedIntentReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(Context context, Intent intent) {
  if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
   Intent pushIntent = new Intent(context, BackgroundService.class);
   context.startService(pushIntent);
  }
 }
}

De http://www.jjoe64.com/2011/06/autostart-service-on-device-boot.html


3
Identique à ce qui précède mais vraiment simple et rapide, utilisez celui-ci si vous venez par ce post.
dbkoren

La seule différence est que cela déclare le service sur le manifeste, ce qui est correct.
Joaquin Iurchuk

Il n'est pas seulement correct de déclarer votre service dans le manifeste, c'est obligatoire. Idem pour les activités
Tim

Où est l'activité principale !? Il n'est pas correct de créer une application sans activités ou android.intent.category.LAUNCHER!
nick

@ L'Esperanza c'est sûr, vous pouvez avoir des applications qui n'ont aucune activité visible!
appsthatmatter

15

La plupart des solutions publiées ici manquent un élément important: le faire sans verrou de réveil risque de voir votre service être tué avant la fin du traitement. J'ai vu cette solution dans un autre fil, en répondant ici également.

Étant donné que WakefulBroadcastReceiver est obsolète dans l'api 26, il est recommandé pour les niveaux d'API inférieurs à 26

Vous devez obtenir un verrou de réveil. Heureusement, la bibliothèque de support nous donne une classe pour faire ceci:

public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // This is the Intent to deliver to our service.
        Intent service = new Intent(context, SimpleWakefulService.class);

        // Start the service, keeping the device awake while it is launching.
        Log.i("SimpleWakefulReceiver", "Starting service @ " + SystemClock.elapsedRealtime());
        startWakefulService(context, service);
    }
}

puis, dans votre service, assurez-vous de libérer le verrou de réveil:

    @Override
    protected void onHandleIntent(Intent intent) {
        // At this point SimpleWakefulReceiver is still holding a wake lock
        // for us.  We can do whatever we need to here and then tell it that
        // it can release the wakelock.

...
        Log.i("SimpleWakefulReceiver", "Completed service @ " + SystemClock.elapsedRealtime());
        SimpleWakefulReceiver.completeWakefulIntent(intent);
    }

N'oubliez pas d'ajouter l'autorisation WAKE_LOCK et d'enregistrer votre récepteur dans le manifeste:

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

...

<service android:name=".SimpleWakefulReceiver">
    <intent-filter>
        <action android:name="com.example.SimpleWakefulReceiver"/>
    </intent-filter>
</service>

1
Dans le fichier manifeste, SimpleWakefulReceiver n'est pas un service.
Desmond Lua

1
WakefulBroadcastReceiver est obsolète
Amin Pinjari

5

vous devez vous inscrire à BOOT_COMPLETE ainsi qu'à REBOOT

<receiver android:name=".Services.BootComplete">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.REBOOT"/>
        </intent-filter>
    </receiver> 

2
La littérature dit que «android.intent.action.REBOOT» ne peut être utilisé que par une application / un code privilégié. Quel avantage est-ce autrement?
XMAN

1

Enregistrez également votre service créé dans le manifeste et utilise-permission comme

<application ...>
   <service android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="com.example.MyBroadcastReciver"/>
        </intent-filter>
   </service>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

puis en braod cast Reciever appelez votre service

public class MyBroadcastReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent myIntent = new Intent(context, MyService.class);
        context.startService(myIntent);
    }
}

Pourquoi le filtre d'intention dans le service?
Joaquin Iurchuk

car lorsque le démarrage est terminé, le MyService sera appelé
SoftEye

Dans ce cas, votre classe de service étendra le service et le récepteur de diffusion. Ai-je raison?
Joaquin Iurchuk

La classe étendra la classe de service.
SoftEye

2
Il y a quelque chose qui ne va pas ici. Le service est censé être appelé depuis le récepteur de diffusion. Mais vous dites que votre service est le récepteur de diffusion et après cela, vous me dites que la classe de service n'étend pas Broadcast Receiver. Ainsi, il ne recevra pas la diffusion de démarrage terminée. Que remplacez-vous lorsque vous déclarez la méthode onReceive?
Joaquin Iurchuk

0

Enregistrez d'abord un récepteur dans votre fichier manifest.xml:

    <receiver android:name="com.mileagelog.service.Broadcast_PowerUp" >
        <intent-filter>
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

puis écrivez une émission pour ce récepteur comme:

public class Broadcast_PowerUp extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
        Toast.makeText(context, "Service_PowerUp Started",
                Toast.LENGTH_LONG).show();


    } else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {



        Toast.makeText(context, "Service_PowerUp Stoped", Toast.LENGTH_LONG)
        .show();
    }
  }
}

0

Pour redémarrer le service dans Android Oou plus ie OS> 28 Utilisez ce code VERSION KOTLIN 1) Ajouter l'autorisation dans le manifeste

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

2) Créez un Classet étendez-le avecBroadcastReceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.content.ContextCompat



class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, arg1: Intent?) {
        Log.d("BootCompletedReceiver", "starting service...")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, Intent(context, YourServiceClass::class.java))
        } else {
            context.startService(Intent(context, YourServiceClass::class.java))
        }
    }
}

3) Déclarez dans le fichier manifeste comme celui-ci sous la balise d'application

<receiver android:name=".utils.BootCompletedReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

-1

Veuillez vérifier JobScheduler pour les API ci-dessus 26

WakeLock était la meilleure option pour cela, mais il est obsolète au niveau de l'API 26.Veuillez vérifier ce lien si vous considérez les niveaux d'API supérieurs à 26
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html# startWakefulService (android.content.Context,% 20android.content.Intent)

Ça dit

À partir d'Android O, les restrictions de vérification des antécédents rendent cette classe généralement inutile. (Il n'est généralement pas sûr de démarrer un service à partir de la réception d'une diffusion, car vous n'avez aucune garantie que votre application est au premier plan à ce stade et donc autorisée à le faire.) Au lieu de cela, les développeurs devraient utiliser Android. app.job.JobScheduler pour planifier un travail, et cela ne nécessite pas que l'application maintienne un verrou de réveil pendant cette opération (le système se chargera de maintenir un verrou de réveil pour le travail).

comme il est dit cosider JobScheduler
https://developer.android.com/reference/android/app/job/JobScheduler

si c'est pour faire quelque chose que pour commencer et pour le garder vous pouvez recevoir l'émission ACTION_BOOT_COMPLETED

S'il ne s'agit pas de pls de premier plan, vérifiez si un service d'accessibilité pourrait le faire

une autre option consiste à démarrer une activité à partir du récepteur de diffusion et à la terminer après le démarrage du service dans onCreate (), car les versions plus récentes d'Android ne permettent pas de démarrer les services à partir des récepteurs

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.