Scenario(方案) 1: Broadcast receiver另有:android.support.v4.content.LocalBroadcastManagerjava
https://androidexperinz.wordpress.com/2012/02/14/communication-between-service-and-activity-part-1/ android
To communicate between activity ad services there two major ways 1. Broadcast receiver 2. Aidl – Android Interface Definition Language 3. Messenger In this post, we will just go through Broadcast receivers, 1. Create a service and activity. 2. Create a broadcast receiver for both service and activity. 3. Register the receiver in the activity and service. Scenario: 1. Service starts on launching the application. 2. Onclick of a button, activity sends broadcast to service 3. service in turn sends broadcast to the activity. SERVICE public class MyService extends Service { //Strings to register to create intent filter for registering the recivers private static final String ACTION_STRING_SERVICE = "ToService"; private static final String ACTION_STRING_ACTIVITY = "ToActivity"; //STEP1: Create a broadcast receiver private BroadcastReceiver serviceReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(getApplicationContext(), "received message in service..!", Toast.LENGTH_SHORT).show(); Log.d("Service", "Sending broadcast to activity"); sendBroadcast(); } }; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { super.onCreate(); Log.d("Service", "onCreate"); //STEP2: register the receiver if (serviceReceiver != null) { //Create an intent filter to listen to the broadcast sent with the action "ACTION_STRING_SERVICE" IntentFilter intentFilter = new IntentFilter(ACTION_STRING_SERVICE); //Map the intent filter to the receiver registerReceiver(serviceReceiver, intentFilter); } } @Override public void onDestroy() { super.onDestroy(); Log.d("Service", "onDestroy"); //STEP3: Unregister the receiver unregisterReceiver(serviceReceiver); } //send broadcast from activity to all receivers listening to the action "ACTION_STRING_ACTIVITY" private void sendBroadcast() { Intent new_intent = new Intent(); new_intent.setAction(ACTION_STRING_ACTIVITY); sendBroadcast(new_intent); } } ACTIVITY public class sample extends Activity { //Strings to register to create intent filter for registering the recivers private static final String ACTION_STRING_SERVICE = "ToService"; private static final String ACTION_STRING_ACTIVITY = "ToActivity"; //STEP1: Create a broadcast receiver private BroadcastReceiver activityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(getApplicationContext(), "received message in activity..!", Toast.LENGTH_SHORT).show(); } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //STEP2: register the receiver if (activityReceiver != null) { //Create an intent filter to listen to the broadcast sent with the action "ACTION_STRING_ACTIVITY" IntentFilter intentFilter = new IntentFilter(ACTION_STRING_ACTIVITY); //Map the intent filter to the receiver registerReceiver(activityReceiver, intentFilter); } //Start the service on launching the application startService(new Intent(this,MyService.class)); findViewById(R.id.button).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.d("SampleActivity", "Sending broadcast to service"); sendBroadcast(); } }); } @Override public void onDestroy() { super.onDestroy(); Log.d("Service", "onDestroy"); //STEP3: Unregister the receiver unregisterReceiver(activityReceiver); } //send broadcast from activity to all receivers listening to the action "ACTION_STRING_SERVICE" private void sendBroadcast() { Intent new_intent = new Intent(); new_intent.setAction(ACTION_STRING_SERVICE); sendBroadcast(new_intent); } } Conclusion: This seemed a simple solution but this was a chaotic one. So had to move into second approach.
Scenario(方案) 2: AIDLapp
https://androidexperinz.wordpress.com/2012/02/21/communication-between-service-and-activity-part-2/ide
Aidl though simple seems to be tough in the beginning, not sure why but hope this post will help to make it simple. Scenario:(we will have 2 aidl, 2 activity, 1 sevice) IService.aidl – to bind the activity and service (to process messages from activity) IServiceCallback.aidl – to return messages to the activity from service sample2.java – to start the service (not required for time-being let the flow be like this) sample.java – activity bounded to the service MsgService.java – service IService.aidl: package com.sample.aidl; import com.sample.aidl.IServiceCallBack; interface IService { void fromActivity(); // function called from activity void registerCallBack(IServiceCallBack cb); } IServiceCallBack.aidl: package com.sample.aidl; interface IServiceCallBack { void fromService(); } Sample2.java: Create a button and on click of it start the service as below: startService(new Intent(sample2.this,MsgService.class)); MsgService.java: Step1: Create a callback list, which gets populated when registerCallback is called from the activity final RemoteCallbackList<IServiceCallBack> mCallbacks = new RemoteCallbackList<IServiceCallBack>(); Step2: Implement the IService.aidl private final IService.Stub mBinder = new IService.Stub() { @Override public void fromActivity() throws RemoteException { Log.d("AIDL service", "fromActivity method called from Activity"); fromActivityProcess(); } @Override public void registerCallBack(IServiceCallBack cb) throws RemoteException { if(cb!=null){ Log.d("AIDL service", "registerCallBack registering"); mCallbacks.register(cb); } } }; Step3:Return the binder(IService type) in onBind function @Override public IBinder onBind(Intent arg0) { return mBinder; // null; } Step4:startActivity(sample.java) in onCreate function @Override public void onCreate() { super.onCreate(); Log.d("AIDL service", "Oncreate"); startActivity(); } public void startActivity(){ Log.d("AIDL service", "startActivity"); Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName("com.sample.aidl", "com.sample.aidl.sample"); startActivity(intent); } Step5:Implement fromActivityProcess function – to send callback to the activity public void fromActivityProcess(){ Log.d("AIDL service", "fromActivity1"); Log.d("AIDL service", "Now to call someMethodInActivity"); try { // this is very important - if u miss it u ll end in exception int N = mCallbacks.beginBroadcast(); Log.d("AIDL service", "mCallBacks N value = " + N); // now for time being we will consider only one activity is bound to the service, so hardcode 0 mCallbacks.getBroadcastItem(0).fromService(); mCallbacks.finishBroadcast(); } catch (RemoteException e) { e.printStackTrace(); } } Sample.java: Step1: Implement IServiceCallback stub private IServiceCallBack mCallback = new IServiceCallBack.Stub() { @Override public void fromService() throws RemoteException { Log.d("Sample Activity", "Callback from Service"); someMethodInActivity(); } }; public void someMethodInActivity(){ Log.d("Sample Activity", "someMethodInActivity"); } Step2: Create a class which implements serviceConnection class MyConnection implements ServiceConnection { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("Sample Activity", "Inside OnServiceConnected callback"); remoteService = IService.Stub.asInterface(service); try { remoteService.registerCallBack(mCallback); } catch (RemoteException e1) { e1.printStackTrace(); } try { Log.d("Sample Activity", "Before calling fromActivity in Activity"); remoteService.fromActivity(); } catch (RemoteException e) { e.printStackTrace(); } } } Step3: Bind the service and activity on click of a button or on onCreate function boolean ret = getApplicationContext().bindService(new Intent(sample.this,MsgService.class), mConnection, Context.BIND_AUTO_CREATE); Log.d("Sample Activity", "After bind call " + ret); Step4: unbind the service onDestroy function unbindFromService();
Scenario(方案) 3: Messengerwordpress
https://androidexperinz.wordpress.com/2012/12/14/communication-between-service-and-activity-part-3/post
After a long time, I found out that Messenger can also be used to communicate between Activity and Services. What does this Messenger mean? It is a Parcelable type, which carries messages from service to activity and vise vera. It is similar to aidl, which can work between two different processes. Quick example how to implement them. Create a service on launching the activity. On clicking the button in the Activity: 1. It will have an handler which is responsible for handling all the messages from the service private class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { String str = (String)msg.obj; Toast.makeText(getApplicationContext(), "From Service -> " + str, Toast.LENGTH_LONG).show(); } } 2. Create a class implementing ServiceConnection Interface class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { mServiceMessenger = new Messenger(service); // where mServiceMessenger is used to send messages to Service // service is the binder returned from onBind method in the Service } @Override public void onServiceDisconnected(ComponentName name) { mServiceMessenger = null; unbindService(mCon); } } 3. Create a Messenger Object in OnCreate method with the object of IncomingHandler class Messenger mActivityMessenger; mActivityMessenger = new Messenger(new IncomingHandler()); 4. Start the service in the onCreate method Intent lIntent = new Intent(MainActivity.this, MainService.class); lIntent.putExtra("Messenger", mActivityMessenger); startService(lIntent); 5. Bind to a service in OnResume method @Override protected void onResume() { super.onResume(); Intent lIntent = new Intent(MainActivity.this, MainService.class); bindService(lIntent, mCon, 0); // mCon is an object of MyServiceConnection Class } 6. Unbind the service in OnPause method to avoid Service leakage @Override protected void onPause() { super.onPause(); unbindService(mCon); } 7. Add a onClickListener to the button and send message to service on onClick event. ((Button)findViewById(R.id.button1)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.d(TAG, "onClick"); Message msg = new Message(); msg.obj = "Hi service.."; try { mServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } }); NOTE: 1. Currently string is sent in the message as obj but when the activity and the service are in different process we need to send the string as bundle. 2. If there are more than one activity bound to the service then the service should have a arraylist of client registered and replyTo variable in Message should be set to that activity’s messenger. Service: 1. It will have an handler which is responsible for handling all the messages from the Activity private class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { String str = (String)msg.obj; Toast.makeText(getApplicationContext(), "From Activity -> " + str, Toast.LENGTH_LONG).show(); Message lMsg = new Message(); lMsg.obj="Hello Activity"; try { mActivityMessenger.send(lMsg); } catch (RemoteException e) { e.printStackTrace(); } } } 3. Create a Messenger Object in OnCreate method with the object of IncomingHandler class Messenger mServiceMessenger; mServiceMessenger = new Messenger(new IncomingHandler()); 4. Get the extras from the messenger and save it in the local variable @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand"); mActivityMessenger = intent.getParcelableExtra("Messenger"); return super.onStartCommand(intent, flags, startId); } 5. OnBind return the service messenger’s binder to the activity. @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return mServiceMessenger.getBinder(); }
以上三種方案思路太清晰了!震撼!ui
Scenario(方案) 4:第三方之EventBusthis