简体   繁体   English

如何从服务中调用活动中的方法

[英]How to call a method in activity from a service

There is a service that listens for some voice. 有一种服务可以听取一些声音。 If voice matches a string a certain method is invoked in the service object. 如果语音匹配字符串,则在服务对象中调用某个方法。

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

     //...
}

This is how I start the service in my activity: 这就是我在我的活动中启动服务的方式:

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

From this service method, how can I invoke a method that resides in the activity object? 从这个服务方法,我如何调用驻留在activity对象中的方法? I don't want access from activity to service, but from service to activity. 我不希望从活动到服务的访问,而是从服务到活动。 I already read about handlers and broadcasters but could not find/understand any example. 我已经阅读过有关处理程序和广播公司的内容,但无法找到/理解任何示例。 Any ideas? 有任何想法吗?

Assuming your Service and Activity are in the same package (ie the same app), you can use LocalBroadcastManager as follows: 假设您的服务和活动位于同一个包中(即相同的应用程序),您可以使用LocalBroadcastManager,如下所示:

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

In your Activity: 在您的活动中:

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

From section 7.3 of @Ascorbin's link: http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager 来自@ Ascorbin链接的第7.3节: http ://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html#ownreceiver_localbroadcastmanager

I would register a BroadcastReceiver in the Activity and send an Intent to it from the service. 我会在Activity中注册一个BroadcastReceiver并从服务中向它发送一个Intent。 See this tutorial: http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html It might look a bit long but you'll want to learn how to use those anyway ;) 请参阅本教程: http//www.vogella.com/articles/AndroidBroadcastReceiver/article.html它可能看起来有点长,但无论如何你都想学习如何使用它们;)

There are many different ways to achive this. 有许多不同的方法来实现这一点。 One of them to use Handler and Messanger classes. 其中一个使用HandlerMessanger类。 The idea of the method is to pass Handler object from Activity to Service . 该方法的想法是将Handler对象从Activity传递给Service Every time Service wants to call some method of the Activity it just sends a Message and Activity handles it somehow. 每次Service想要调用Activity某个方法时,它只会发送一个MessageActivity会以某种方式处理它。

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

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

After some research I found the following timings in my case for sending and receiving the broadcast. 经过一些研究,我发现在我的情况下发送和接收广播的时间如下。 I have service in the same process. 我在同一个过程中服务。

sendBroadcast (Not recommended if both components are in same process) 34 sec sendBroadcast(如果两个组件在同一个进程中,则不推荐)34秒

LocalBroadcastManager.getInstance(this).sendBroadcast(intent); LocalBroadcastManager.getInstance(本).sendBroadcast(意向); close to 30 sec 接近30秒

Implementing using AIDL and RemoteCallbackList Will work for same process or different process 使用AIDL和RemoteCallbackList实现将适用于相同的进程或不同的进程

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

When you need call methods in Application/Acitvity from service 当您需要来自服务的Application / 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();
}

In your class extending Application or Activity. 在您的类中扩展应用程序或活动。

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

Calling this way is almost instantaneous from broadcasting and receiving from the same process 通过这种方式呼叫几乎是从广播和从同一过程接收的瞬间

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM