Подтвердить что ты не робот

Как вызвать метод в действии с помощью службы

Существует служба, которая слушает какой-то голос. Если голос соответствует строке, в объекте службы вызывается определенный метод.

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

     //...
}

Вот как я запускаю службу в своей деятельности:

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

Из этого метода службы, как я могу вызвать метод, который находится в объекте активности? Я не хочу, чтобы доступ от активности к сервису, но от службы к активности. Я уже читал о обработчиках и вещателях, но не смог найти/понять какой-либо пример. Любые идеи?

4b9b3361

Ответ 1

Я зарегистрировал BroadcastReceiver в Управлении и передал бы ему намерение из службы. См. Этот учебник: http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html Это может выглядеть немного долго, но вы захотите узнать, как их использовать;)

Ответ 2

Предполагая, что ваша служба и активность находятся в одном пакете (т.е. в одном приложении), вы можете использовать LocalBroadcastManager следующим образом:

В вашем сервисе:

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

В вашей деятельности:

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

Из раздела 7.3 ссылки @Ascorbin: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

Ответ 3

Существует много разных способов достижения этого. Один из них использует классы Handler и Messanger. Идея метода состоит в том, чтобы передать объект Handler с Activity на Service. Каждый раз, когда Service хочет вызвать некоторый метод Activity, он просто отправляет Message и Activity как-то его обрабатывает.

Активность:

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

Услуги:

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

Ответ 4

После некоторого исследования я нашел следующие тайминги в моем случае для отправки и получения трансляции. У меня есть сервис в том же процессе.

sendBroadcast (Не рекомендуется, если оба компонента находятся в одном процессе) 34 с

LocalBroadcastManager.getInstance(это).sendBroadcast(намерение); около 30 секунд

Реализация с использованием AIDL и RemoteCallbackList Будет работать для одного процесса или другого процесса.

В вашем сервисе

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

Когда вам нужны методы вызова в приложении /Acitvity из службы

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

В вашем классе расширяется приложение или активность.

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

Вызов этого метода почти мгновенен из трансляции и приема из того же процесса