Comment faire en sorte qu'Android Service communique avec Activity

251

J'écris ma première application Android et j'essaie de comprendre la communication entre les services et les activités. J'ai un service qui fonctionnera en arrière-plan et effectuera une connexion GPS et basée sur le temps. J'aurai une activité qui sera utilisée pour démarrer et arrêter le service.

Donc, tout d'abord, je dois être en mesure de déterminer si le service est en cours d'exécution au démarrage de l'activité. Il y a d'autres questions ici à ce sujet, donc je pense que je peux comprendre cela (mais n'hésitez pas à offrir des conseils).

Mon vrai problème: si l'activité est en cours d'exécution et que le service est démarré, j'ai besoin d'un moyen pour le service d'envoyer des messages à l'activité. Chaînes simples et entiers à ce stade - messages d'état principalement. Les messages ne se produiront pas régulièrement, donc je ne pense pas que l'interrogation du service soit une bonne façon de procéder s'il existe une autre solution. Je veux cette communication uniquement lorsque l'activité a été démarrée par l'utilisateur - je ne veux pas démarrer l'activité à partir du service. En d'autres termes, si vous démarrez l'activité et que le service est en cours d'exécution, vous verrez des messages d'état dans l'interface utilisateur d'activité lorsque quelque chose d'intéressant se produit. Si vous ne démarrez pas l'activité, vous ne verrez pas ces messages (ils ne sont pas si intéressants).

Il semble que je devrais être en mesure de déterminer si le service est en cours d'exécution et, dans l'affirmative, d'ajouter l'activité en tant qu'écouteur. Supprimez ensuite l'activité en tant qu'auditeur lorsque l'activité s'arrête ou s'arrête. Est-ce vraiment possible? La seule façon pour moi de le faire est de demander à Activity d'implémenter Parcelable et de créer un fichier AIDL afin que je puisse le passer via l'interface distante du Service. Cela semble cependant exagéré, et je n'ai aucune idée de la façon dont l'activité devrait implémenter writeToParcel () / readFromParcel ().

Existe-t-il un moyen plus simple ou meilleur? Merci pour toute aide.

ÉDITER:

Pour ceux qui sont intéressés par cela plus tard, il existe un exemple de code de Google pour gérer cela via AIDL dans le répertoire d'exemples: /apis/app/RemoteService.java

Scott Saunders
la source

Réponses:

94

Il existe trois façons évidentes de communiquer avec les services:

  1. Utiliser les intentions
  2. Utilisation d'AIDL
  3. Utilisation de l'objet de service lui-même (en tant que singleton)

Dans votre cas, j'irais avec l'option 3. Faites une référence statique au service lui-même et remplissez-le dans onCreate ():

void onCreate(Intent i) {
  sInstance = this;
}

Créez une fonction statique MyService getInstance(), qui renvoie la statique sInstance.

Ensuite Activity.onCreate(), lorsque vous démarrez le service, attendez de manière asynchrone que le service soit réellement démarré (vous pouvez demander à votre service d'aviser votre application qu'il est prêt en envoyant une intention à l'activité) et d'obtenir son instance. Lorsque vous avez l'instance, enregistrez votre objet d'écoute de service dans votre service et vous êtes prêt. REMARQUE: lorsque vous modifiez des vues à l'intérieur de l'activité, vous devez les modifier dans le thread d'interface utilisateur, le service exécutera probablement son propre thread, vous devez donc appeler Activity.runOnUiThread().

La dernière chose que vous devez faire est de supprimer la référence à votre objet d'écoute Activity.onPause(), sinon une instance de votre contexte d'activité fuira, ce qui n'est pas bon.

REMARQUE: cette méthode n'est utile que lorsque votre application / activité / tâche est le seul processus qui accède à votre service. Si ce n'est pas le cas, vous devez utiliser l'option 1. ou 2.

MrSnowflake
la source
2
Comment puis-je busy-waitl'activité? Pouvez-vous expliquer s'il vous plaît?
iTurki
1
Donc, après onCreate ou après onStartCommand dans votre classe de service, définissez une variable statique publique, appelez-la isConnected ou quelque chose de vrai. Ensuite, dans votre activité, procédez comme suit: Intention intention = nouvelle intention (act, YourService.class); startService (intention); while (! YourService.isConnected) {sleep (300); } Après cette boucle, votre service est en cours d'exécution et vous pouvez communiquer avec lui. D'après mon expérience, il existe certainement des limites à l'interaction avec un service comme celui-ci.
Matt Wolfe
Pourquoi ne peut-il être démarré qu'en Activity.onCreate()?
skywall
Un mot sur pourquoi vous ne voudriez pas utiliser Intentsen envoyant des données via des Parcellablemessages entre eux?
Aman Alam
2
Cela fonctionne, mais la réponse de @ MaximumGoat est beaucoup plus claire et n'implique aucune attente occupée.
Matt
262

Le demandeur est probablement passé depuis longtemps, mais au cas où quelqu'un d'autre le chercherait ...

Il y a une autre façon de gérer cela, qui je pense pourrait être la plus simple.

Ajoutez un BroadcastReceiverà votre activité. Enregistrez-le pour recevoir une intention personnalisée onResumeet annulez-le onPause. Envoyez ensuite cette intention à partir de votre service lorsque vous souhaitez envoyer vos mises à jour de statut ou ce que vous avez.

Assurez-vous que vous ne seriez pas mécontent si une autre application écoutait votre Intent(quelqu'un pourrait-il faire quelque chose de malveillant?), Mais au-delà, vous devriez être bien.

Un exemple de code a été demandé:

À mon service, j'ai ceci:

// Do stuff that alters the content of my local SQLite Database
sendBroadcast(new Intent(RefreshTask.REFRESH_DATA_INTENT));

( RefreshTask.REFRESH_DATA_INTENTest juste une chaîne constante.)

Dans mon activité d'écoute, je définis mon BroadcastReceiver:

private class DataUpdateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(RefreshTask.REFRESH_DATA_INTENT)) {
          // Do stuff - maybe update my view based on the changed DB contents
        }
    }
}

Je déclare mon récepteur en tête de la classe:

private DataUpdateReceiver dataUpdateReceiver;

Je remplace onResumepour ajouter ceci:

if (dataUpdateReceiver == null) dataUpdateReceiver = new DataUpdateReceiver();
IntentFilter intentFilter = new IntentFilter(RefreshTask.REFRESH_DATA_INTENT);
registerReceiver(dataUpdateReceiver, intentFilter);

Et je remplace onPausepour ajouter:

if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);

Maintenant, mon activité est à l'écoute de mon service pour dire "Hé, allez vous mettre à jour." Je pourrais transmettre des données au Intentlieu de mettre à jour les tables de base de données, puis revenir pour trouver les modifications dans mon activité, mais comme je veux que les modifications persistent de toute façon, il est logique de transmettre les données via DB.

MaximumGoat
la source
5
Comment? Ce que vous décrivez est exactement ce dont j'ai besoin. Mais plus que cela, j'ai besoin d'un exemple de code complet. Merci d'avance. Pour info, la dernière fois que j'ai essayé d'écrire un widget, la partie messagerie m'a pris 2 mois. Riez si vous le souhaitez, mais vous, les experts, devez publier davantage car IMHO Android est plus compliqué qu'iOS!
1
aaaaaaa, Le Guide du codeur occupé pour le développement avancé d'Android a un excellent chapitre sur les widgets. C'est la seule ressource qui m'a permis de surmonter ce gâchis. CommonsWare, l'auteur, a une réputation de 115k sur StackOverflow, et je recommande fortement le livre. commonsware.com/AdvAndroid
MaximumGoat
64
Broadcastssont fantastiques et en plus si vous ne voulez pas que votre diffusion dépasse votre propre processus alors envisagez d'utiliser un LocalBroadcast: developer.android.com/reference/android/support/v4/content/…
Cody Caughlan
2
Merci Cody, je n'avais jamais vu ça avant.
MaximumGoat
3
C'est un très bon moyen de communication. Mais que faire en cas de résultats obtenus, lorsque l'activité était en pause? Ainsi, après l'activité onResume, les résultats peuvent attendre longtemps. Et aucune donnée ne sera reçue, car des données ont été manquées.
Anton-M
39

Utilisez LocalBroadcastManagerpour enregistrer un récepteur pour écouter une émission envoyée par un service local dans votre application, la référence se trouve ici:

http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html

Jack Gao
la source
3
Oui, une très belle discussion sur la diffusion locale ici lien
SohailAziz
1
LocalBroadcastManagerest désormais déconseillé au profit d' LiveDataautres outils de modèle d'observateur: developer.android.com/reference/androidx/localbroadcastmanager/…
Ali Nem
20

Je suis surpris que personne n'ait fait référence à la bibliothèque de bus de l'événement Otto

http://square.github.io/otto/

Je l'utilise dans mes applications Android et cela fonctionne parfaitement.

Madhur Ahuja
la source
7
Alternativement, il y a la bibliothèque EventBus de greenrobot .
Jazzer
15
Mais rappelez-vous que EventBus et otto sont toujours dans un même processus. Lorsque vous utilisez un service qui est dans son propre processus (a commencé par définir le android:process=":my_service"ils ne sont pas en mesure de communiquer.
Ron
20

L'utilisation d'un Messenger est un autre moyen simple de communiquer entre un Service et une Activité.

Dans l'activité, créez un gestionnaire avec un messager correspondant. Cela gérera les messages de votre service.

class ResponseHandler extends Handler {
    @Override public void handleMessage(Message message) {
            Toast.makeText(this, "message from service",
                    Toast.LENGTH_SHORT).show();
    }
}
Messenger messenger = new Messenger(new ResponseHandler());

Le Messenger peut être transmis au service en l'attachant à un Message:

Message message = Message.obtain(null, MyService.ADD_RESPONSE_HANDLER);
message.replyTo = messenger;
try {
    myService.send(message);
catch (RemoteException e) {
    e.printStackTrace();
}

Un exemple complet peut être trouvé dans les démonstrations d'API: MessengerService et MessengerServiceActivity . Reportez-vous à l'exemple complet pour savoir comment fonctionne MyService.

Kjetil
la source
1
Très appréciée! Fonctionne parfaitement. Juste un détail dans le code: myService.send(message);devrait être à la messenger.send(message);place.
Federico Cristina
9

L'autre méthode non mentionnée dans les autres commentaires consiste à se lier au service à partir de l'activité à l'aide de bindService () et à obtenir une instance du service dans le rappel ServiceConnection. Comme décrit ici http://developer.android.com/guide/components/bound-services.html

miguel
la source
4
C'est la bonne façon d'obtenir une référence d'instance de service.
김준호
9

Vous pouvez également utiliser LiveDatacela fonctionne comme un EventBus.

class MyService : LifecycleService() {
    companion object {
        var BUS = MutableLiveData<Object>()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)

        val testItem : Object

        // expose your data
        if (BUS.hasActiveObservers()) {
            BUS.postValue(testItem)
        }

        return START_NOT_STICKY
    }
}

Ajoutez ensuite un observateur de votre Activity.

MyService.BUS.observe(this, Observer {
    it?.let {
        // Do what you need to do here
    }
})

Vous pouvez en savoir plus sur ce blog.

zeenosaure
la source
2

Une autre façon pourrait être d'utiliser des observateurs avec une fausse classe de modèle à travers l'activité et le service lui-même, en implémentant une variation de modèle MVC. Je ne sais pas si c'est la meilleure façon d'y parvenir, mais c'est la manière qui a fonctionné pour moi. Si vous avez besoin d'un exemple, demandez-le et je posterai quelque chose.

Réorienter__
la source
Je me bats avec une réflexion similaire. J'ai une activité et 2 services qui ont le même modèle. Le modèle peut être mis à jour dans l'une ou l'autre activité ou dans n'importe quel service, j'ai donc pensé à utiliser Observers d'une manière ou d'une autre, mais je ne peux pas le comprendre. Pouvez-vous poster un exemple pour montrer votre idée?
pzo
2

Ma méthode:

Classe pour gérer l'envoi et la réception de messages de / vers le service / l'activité:

import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MessageManager {

    public interface IOnHandleMessage{
        // Messages
        int MSG_HANDSHAKE = 0x1;

        void onHandleMessage(Message msg);
    }

    private static final String LOGCAT = MessageManager.class.getSimpleName();

    private Messenger mMsgSender;
    private Messenger mMsgReceiver;
    private List<Message> mMessages;

    public MessageManager(IOnHandleMessage callback, IBinder target){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_ACTIVITY));
        mMsgSender = new Messenger(target);
        mMessages = new ArrayList<>();
    }

    public MessageManager(IOnHandleMessage callback){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_SERVICE));
        mMsgSender = null;
        mMessages = new ArrayList<>();
    }

    /* START Getter & Setter Methods */
    public Messenger getMsgSender() {
        return mMsgSender;
    }

    public void setMsgSender(Messenger sender) {
        this.mMsgSender = sender;
    }

    public Messenger getMsgReceiver() {
        return mMsgReceiver;
    }

    public void setMsgReceiver(Messenger receiver) {
        this.mMsgReceiver = receiver;
    }

    public List<Message> getLastMessages() {
        return mMessages;
    }

    public void addMessage(Message message) {
        this.mMessages.add(message);
    }
    /* END Getter & Setter Methods */

    /* START Public Methods */
    public void sendMessage(int what, int arg1, int arg2, Bundle msgData){
        if(mMsgSender != null && mMsgReceiver != null) {
            try {
                Message msg = Message.obtain(null, what, arg1, arg2);
                msg.replyTo = mMsgReceiver;
                if(msgData != null){
                    msg.setData(msgData);
                }
                mMsgSender.send(msg);
            } catch (RemoteException rE) {
                onException(rE);
            }
        }
    }

    public void sendHandshake(){
        if(mMsgSender != null && mMsgReceiver != null){
            sendMessage(IOnHandleMessage.MSG_HANDSHAKE, 0, 0, null);
        }
    }
    /* END Public Methods */

    /* START Private Methods */
    private void onException(Exception e){
        Log.e(LOGCAT, e.getMessage());
        e.printStackTrace();
    }
    /* END Private Methods */

    /** START Private Classes **/
    private class MessageHandler extends Handler {

        // Types
        final static int TYPE_SERVICE = 0x1;
        final static int TYPE_ACTIVITY = 0x2;

        private IOnHandleMessage mCallback;
        private int mType;

        public MessageHandler(IOnHandleMessage callback, int type){
            mCallback = callback;
            mType = type;
        }

        @Override
        public void handleMessage(Message msg){
            addMessage(msg);
            switch(msg.what){
                case IOnHandleMessage.MSG_HANDSHAKE:
                    switch(mType){
                        case TYPE_SERVICE:
                            setMsgSender(msg.replyTo);
                            sendHandshake();
                            break;
                        case TYPE_ACTIVITY:
                            Log.v(LOGCAT, "HERE");
                            break;
                    }
                    break;
                default:
                    if(mCallback != null){
                        mCallback.onHandleMessage(msg);
                    }
                    break;
            }
        }

    }
    /** END Private Classes **/

}

Dans l'exemple d'activité:

public class activity extends AppCompatActivity
      implements     ServiceConnection,
                     MessageManager.IOnHandleMessage { 

    [....]

    private MessageManager mMessenger;

    private void initMyMessenger(IBinder iBinder){
        mMessenger = new MessageManager(this, iBinder);
        mMessenger.sendHandshake();
    }

    private void bindToService(){
        Intent intent = new Intent(this, TagScanService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        /* START THE SERVICE IF NEEDED */
    }

    private void unbindToService(){
    /* UNBIND when you want (onDestroy, after operation...)
        if(mBound) {
            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    /* START Override MessageManager.IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
        switch(msg.what){
            case Constants.MSG_SYNC_PROGRESS:
                Bundle data = msg.getData();
                String text = data.getString(Constants.KEY_MSG_TEXT);
                setMessageProgress(text);
                break;
            case Constants.MSG_START_SYNC:
                onStartSync();
                break;
            case Constants.MSG_END_SYNC:
                onEndSync(msg.arg1 == Constants.ARG1_SUCCESS);
                mBound = false;
                break;
        }
    }
    /* END Override MessageManager.IOnHandleMessage Methods */

    /** START Override ServiceConnection Methods **/
    private class BLEScanServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            initMyMessenger(iBinder);
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mMessenger = null;
            mBound = false;
        }
    }
    /** END Override ServiceConnection Methods **/

Exemple en service:

public class Blablabla extends Service
    implements     MessageManager.IOnHandleMessage {

    [...]

    private MessageManager mMessenger;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        initMessageManager();
        return mMessenger.getMsgReceiver().getBinder();
    }

    private void initMessageManager(){
        mMessenger = new MessageManager(this);
    }

    /* START Override IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
    /* Do what you want when u get a message looking the "what" attribute */
    }
    /* END Override IOnHandleMessage Methods */

Envoyer un message de l'activité / du service:

mMessenger.sendMessage(what, arg1, arg2, dataBundle);

Comment cela fonctionne:

sur l'activité que vous démarrez ou liez le service. Les méthodes de service "OnBind" renvoient le classeur à son MessageManager, puis dans l'activité via l'implémentation des méthodes d'interface "Service Connection" "OnServiceConnected", vous obtenez cet IBinder et vous initiez à MessageManager. Une fois que l'activité a initié son MessageManager, le MessageHandler envoie et Handshake au service afin qu'il puisse définir son expéditeur "MessageHandler" (le "messager privé mMsgSender;" dans MessageManager). Ce faisant, le service sait à qui envoyer ses messages.

Vous pouvez également implémenter cela en utilisant une liste / file d'attente de "l'expéditeur" Messenger dans le MessageManager afin que vous puissiez envoyer plusieurs messages à différentes activités / services ou vous pouvez utiliser une liste / file d'attente de Messenger "récepteur" dans le MessageManager afin que vous puissiez recevoir plusieurs message de différentes activités / services.

Dans l'instance "MessageManager", vous avez une liste de tous les messages reçus.

Comme vous pouvez voir que la connexion entre "Activity's Messenger" et "Service Messenger" en utilisant cette instance "MessageManager" est automatique, cela se fait par la méthode "OnServiceConnected" et par l'utilisation de "Handshake".

J'espère que cela vous sera utile :) Merci beaucoup! Au revoir: D

Z3R0
la source
2

Pour suivre la réponse @MrSnowflake avec un exemple de code. Ceci est la XABBER maintenant open source de Applicationclasse . La Applicationclasse centralise et coordonne Listenerset ManagerInterfaces et plus encore. Les gestionnaires de toutes sortes sont chargés dynamiquement. Activity´scommencé dans le Xabber indiquera dans quel type Listenerils sont. Et quand Serviceil démarre, il se présente à la Applicationclasse comme commencé. Maintenant, pour envoyer un message à Activitytout ce que vous avez à faire, c'est de Activitydevenir le listenertype dont vous avez besoin. Dans le OnStart() OnPause()registre / non enregistré. Ils Servicepeuvent Applicationsimplement demander à la classe listenerde parler et si c'est le cas, l'activité est prête à recevoir.

En parcourant la Applicationclasse, vous verrez qu'il y a plus de butin que cela.

Erik
la source
Le lien fourni donne maintenant un github 404. A-t-il bougé?
JE Carter II
Oui, semble fonctionner maintenant. Ce devait être un problème temporaire sur github.
JE Carter II
1

La liaison est une autre façon de communiquer

Créer un rappel

public interface MyCallBack{

   public void getResult(String result);

}

Côté activité:

  1. Implémenter l'interface dans l'activité

  2. Fournir l'implémentation de la méthode

  3. Lier l'activité au service

  4. Enregistrez et annulez le rappel lorsque le service est lié et non lié à l'activité.

    public class YourActivity extends AppCompatActivity implements MyCallBack{
    
          private Intent notifyMeIntent;
          private GPSService gpsService;
          private boolean bound = false;
    
          @Override
          public void onCreate(Bundle sis){
    
              // activity code ...
    
              startGPSService();
    
          }
    
          @Override
          public void getResult(String result){
           // show in textView textView.setText(result);
          }
    
          @Override
          protected void onStart()
          {
              super.onStart();
              bindService();
          }
    
          @Override
          protected void onStop() {
              super.onStop();
              unbindService();
          }
    
          private ServiceConnection serviceConnection = new ServiceConnection() {
    
                @Override
                public void onServiceConnected(ComponentName className, IBinder service) {
    
                      GPSService.GPSBinder binder = (GPSService.GPSBinder) service;
                      gpsService= binder.getService();
                      bound = true;
                      gpsService.registerCallBack(YourActivity.this); // register
    
               }
    
               @Override
               public void onServiceDisconnected(ComponentName arg0) {
                      bound = false;
               }
          };
    
          private void bindService() {
    
               bindService(notifyMeIntent, serviceConnection, Context.BIND_AUTO_CREATE);
          }
    
          private void unbindService(){
               if (bound) {
                     gpsService.registerCallBack(null); // unregister            
                     unbindService(serviceConnection);
                     bound = false;
                }
          }
    
          // Call this method somewhere to start Your GPSService
          private void startGPSService(){
               notifyMeIntent = new Intent(this, GPSService.class);
               startService(myIntent );
          }
    
     }

Côté service:

  1. Initialiser le rappel

  2. Appelez la méthode de rappel chaque fois que nécessaire

     public class GPSService extends Service{
    
         private MyCallBack myCallback;
         private IBinder serviceBinder = new GPSBinder();
    
         public void registerCallBack(MyCallBack myCallback){
              this.myCallback= myCallback;
         }
    
         public class GPSBinder extends Binder{
    
             public GPSService getService(){
                  return GPSService.this;
             }
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent){
             return serviceBinder;
        }
     }
Rohit Singh
la source
votre serviceConnectionest sorti onCreate. Veuillez l'éditer.
Adeel Zafar
Il n'est pas nécessaire qu'il soit à l'intérieur de onCreate
Rohit Singh
0

Outre LocalBroadcastManager, Event Bus et Messenger ayant déjà répondu à cette question, nous pouvons utiliser Pending Intent pour communiquer à partir du service.

Comme mentionné ici dans mon article de blog

La communication entre le service et l'activité peut être effectuée à l'aide de PendingIntent. Pour cela, nous pouvons utiliser createPendingResult () .createPendingResult () crée un nouvel objet PendingIntent que vous pouvez remettre au service à utiliser et renvoyer les données de résultat à votre activité dans onActivityResult (int, int, Intent) callback. Puisqu'un PendingIntent est Parcelable, et peut donc être mis dans un Intent extra, votre activité peut transmettre ce PendingIntent au service. Le service, à son tour, peut appeler la méthode send () sur le PendingIntent pour notifier le activité via onActivityRésultat d'un événement.

Activité

public class PendingIntentActivity extends AppCompatActivity
{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class);
intent.putExtra("pendingIntent", pendingResult);
startService(intent);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

Un service

public class PendingIntentService extends Service {

    private static final String[] items= { "lorem", "ipsum", "dolor",
            "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
            "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
            "vel", "erat", "placerat", "ante", "porttitor", "sodales",
            "pellentesque", "augue", "purus" };
    private PendingIntent data;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        data = intent.getParcelableExtra("pendingIntent");

        new LoadWordsThread().start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class LoadWordsThread extends Thread {
        @Override
        public void run() {
            for (String item : items) {
                if (!isInterrupted()) {

                    Intent result = new Intent();
                    result.putExtra("name", item);
                    try {
                        data.send(PendingIntentService.this,200,result);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    SystemClock.sleep(400);

                }
            }
        }
    }
}
Développeur Android
la source