web-dev-qa-db-fra.com

Comment appeler une méthode en activité à partir d'un service

Il existe un service qui écoute une voix. Si la voix correspond à une chaîne, une certaine méthode est invoquée dans l'objet de service.

public class SpeechActivationService extends Service {

     public static Intent makeStartServiceIntent(Context pContext){    

         return new Intent(pContext, SpeechActivationService.class);
     }

     //...

     public void onMatch(){
         Log.d(TAG, "voice matches Word");
     }

     //...
}

Voici comment je démarre le service dans mon activité:

Intent i = SpeechActivationService.makeStartServiceIntent(this);
startService(i);

À partir de cette méthode de service, comment puis-je appeler une méthode qui réside dans l'objet d'activité? Je ne veux pas l'accès de l'activité au service, mais du service à l'activité. J'ai déjà lu des informations sur les gestionnaires et les diffuseurs, mais je n'ai pu trouver/comprendre aucun exemple. Des idées?

28
Upvote

Je voudrais enregistrer un BroadcastReceiver dans l'activité et lui envoyer une intention à partir du service. Voir ce tutoriel: http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html Cela peut sembler un peu long mais vous voudrez quand même apprendre à les utiliser;)

11
asco

En supposant que votre service et votre activité sont dans le même package (c'est-à-dire la même application), vous pouvez utiliser LocalBroadcastManager comme suit:

À votre service:

// Send an Intent with an action named "my-event". 
private void sendMessage() {
  Intent intent = new Intent("my-event");
  // add data
  intent.putExtra("message", "data");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Dans votre activité:

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

  // Register mMessageReceiver to receive messages.
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("my-event"));
}

// handler for received Intents for the "my-event" event 
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Extract data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onPause() {
  // Unregister since the activity is not visible
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onPause();
}

De la section 7.3 du lien @ Ascorbin: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

59
Tony Wickham

Il existe de nombreuses façons d'y parvenir. L'un d'eux pour utiliser les classes Handler et Messanger. L'idée de la méthode est de passer l'objet Handler de Activity à Service. Chaque fois que Service veut appeler une méthode de Activity, il envoie simplement un Message et Activity le gère d'une manière ou d'une autre.

Activité:

public class MyActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                showToast(msg.what);
            }
        };

        final Intent intent = new Intent(this, MyService.class);
        final Messenger messenger = new Messenger(handler);

        intent.putExtra("messenger", messenger);
        startService(intent);
    }

    private void showToast(int messageId) {
        Toast.makeText(this, "Message  " + messageId, Toast.LENGTH_SHORT).show();
    }
}

Un service:

public class MyService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            final Messenger messenger = (Messenger) intent.getParcelableExtra("messenger");
            final Message message = Message.obtain(null, 1234);

            try {
                messenger.send(message);
            } catch (RemoteException exception) {
                exception.printStackTrace();
            }
        }

        return START_NOT_STICKY;
    }

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

Après quelques recherches, j'ai trouvé les horaires suivants dans mon cas pour l'envoi et la réception de l'émission. J'ai un service dans le même processus.

sendBroadcast (Non recommandé si les deux composants sont dans le même processus) 34 sec

LocalBroadcastManager.getInstance (this) .sendBroadcast (intention); près de 30 sec

Implémentation en utilisant AIDL et RemoteCallbackList fonctionnera pour le même processus ou un processus différent

A votre service

public final RemoteCallbackList<ICallBackAidl> mDMCallbacks = new RemoteCallbackList<ICallBackAidl>();

public void registerDMCallback(ICallBackAidl cb) {
    Logger.d(LOG_TAG, "registerDMCallback " + cb);
    if (cb != null)
        mDMCallbacks.register(cb);
}

Lorsque vous avez besoin de méthodes d'appel dans Application/Acitvity from service

public void callMehodsInApplication() {
    final int N = mDMCallbacks.beginBroadcast();
    for (int i = 0; i < N; i++) {
        try {
            mDMCallbacks.getBroadcastItem(i).method1();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    mDMCallbacks.finishBroadcast();
}

Dans votre classe, étendre l'application ou l'activité.

private ISyncmlServiceDMCallback mCallback = new ISyncmlServiceDMCallback.Stub() {
 // Implement callback methods here
  public void method1() {
       // Service can call this method
  }
}

 public void onServiceConnected(ComponentName name, IBinder service) {   
        svc.LocalBinder binder = (svc.LocalBinder) service;
        mSvc = binder.getService();
        mSvc.registerDMCallback(mCallback);
 }

Appeler de cette façon est presque instantané de la diffusion et de la réception du même processus

0
Deepu