Android之Activity与Service通信
一、当Acitivity和Service处于同一个Application和进程时,通过继承Binder类来实现。
二..使用Messenger
三.通过broadcast(广播)的形式.当我们的进度发生变化的时候我们发送一条广播,然后在Activity的注册广播接收器,接收到广播之后更新ProgressBar,
四.使用AIDL的方法.点击我看AIDL的详情
当一个Activity绑定到一个Service上时,它负责维护Service实例的引用,允许你对正在运行的Service进行一些方法调用。比如你后台有一个播放背景音乐的Service,这时就可以用这种方式来进行通信。
代码如下:
/*************************Service代码****************************************/ public class LocalService extends Service { private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { LocalService getService() { return LocalService.this; } } public IBinder onBind(Intent intent) { return binder; } } /*****************************Activity代码*************************************/ public class BindingActivity extends Activity { LocalService localService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className,IBinder localBinder) { localService = (LocalBinder) localBinder.getService(); } public void onServiceDisconnected(ComponentName arg0) { localService = null; } }; protected void onStart() { super.onStart(); Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } protected void onStop() { super.onStop(); unbindService(mConnection); } public void printRandomNumber{ int num = localService.getRandomNumber(); System.out.println(num); } }
代码解释:
使用使用context.bindService()启动Service会经历:
context.bindService()->onCreate()->onBind()->Service running
onUnbind() -> onDestroy() ->Service stop
Activity能进行绑定得益于Service的接口onBind()。Service和Activity的连接可以用ServiceConnection来实现,需要实现一个新的ServiceConnection,重写onServiceConnected和onServiceDisconnected方法。执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显式或隐式)和一个你实现了的ServiceConnection实例。一旦连接建立,你就能通Service的接口onBind()得到serviceBinder实例进而得到Service的实例引用。一旦Service对象找到,就能得到它的公共方法和属性。但这种方式,一定要在同一个进程和同一个Application里。
使用Messenger
上面的方法只能在同一个进程里才能用,如果要与另外一个进程的Service进行通信,则可以用Messenger。
其实实现IPC的方式,还有AIDL,但推荐使用Messenger,有两点好处:
1. 使用Messenger方式比使用AIDL的方式,实现起来要简单很多
2. 使用Messenger时,所有从Activity传过来的消息都会排在一个队列里,不会同时请求Service,所以是线程安全的。如果你的程序就是要多线程去访问Service,就可以用AIDL,不然最好使用Messenger的方式。
不过,其实Messenger底层用的就是AIDL实现的,看一下实现方式,先看Service的代码:
- public class MessengerService extends Service {
- /** 用于Handler里的消息类型 */
- static final int MSG_SAY_HELLO = 1;
- /**
- * 在Service处理Activity传过来消息的Handler
- */
- class IncomingHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SAY_HELLO:
- Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
- break;
- default:
- super.handleMessage(msg);
- }
- }
- }
- /**
- * 这个Messenger可以关联到Service里的Handler,Activity用这个对象发送Message给Service,Service通过Handler进行处理。
- */
- final Messenger mMessenger = new Messenger(new IncomingHandler());
- /**
- * 当Activity绑定Service的时候,通过这个方法返回一个IBinder,Activity用这个IBinder创建出的Messenger,就可以与Service的Handler进行通信了
- */
- @Override
- public IBinder onBind(Intent intent) {
- Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
- return mMessenger.getBinder();
- }
- }
再看一下Activity的代码:
- public class ActivityMessenger extends Activity {
- /** 向Service发送Message的Messenger对象 */
- Messenger mService = null;
- /** 判断有没有绑定Service */
- boolean mBound;
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // Activity已经绑定了Service
- // 通过参数service来创建Messenger对象,这个对象可以向Service发送Message,与Service进行通信
- mService = new Messenger(service);
- mBound = true;
- }
- public void onServiceDisconnected(ComponentName className) {
- mService = null;
- mBound = false;
- }
- };
- public void sayHello(View v) {
- if (!mBound) return;
- // 向Service发送一个Message
- Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
- try {
- mService.send(msg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- @Override
- protected void onStart() {
- super.onStart();
- // 绑定Service
- bindService(new Intent(this, MessengerService.class), mConnection,
- Context.BIND_AUTO_CREATE);
- }
- @Override
- protected void onStop() {
- super.onStop();
- // 解绑
- if (mBound) {
- unbindService(mConnection);
- mBound = false;
- }
- }
- }
注意:以上写的代码只能实现从Activity向Service发送消息,如果想从Service向Activity发送消息,只要把代码反过来写就可以了。
3..使用AIDL
如果知道上面两种方法,这个方法基本很少会用到。
详情请看这篇文章.http://blog.csdn.net/sanjay_f/article/details/38493257
4...broadcast(广播)的形式
当我们的进度发生变化的时候我们发送一条广播,然后在Activity的注册广播接收器,接收到广播之后更新ProgressBar,代码如下
- package com.example.communication;
- <span style="font-family:System;">
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ProgressBar;
- public class MainActivity extends Activity {
- private ProgressBar mProgressBar;
- private Intent mIntent;
- private MsgReceiver msgReceiver;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //动态注册广播接收器
- msgReceiver = new MsgReceiver();
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction("com.example.communication.RECEIVER");
- registerReceiver(msgReceiver, intentFilter);
- mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
- Button mButton = (Button) findViewById(R.id.button1);
- mButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- //启动服务
- mIntent = new Intent("com.example.communication.MSG_ACTION");
- startService(mIntent);
- }
- });
- }
- @Override
- protected void onDestroy() {
- //停止服务
- stopService(mIntent);
- //注销广播
- unregisterReceiver(msgReceiver);
- super.onDestroy();
- }
- /**
- * 广播接收器
- * @author len
- *
- */
- public class MsgReceiver extends BroadcastReceiver{
- @Override
- public void onReceive(Context context, Intent intent) {
- //拿到进度,更新UI
- int progress = intent.getIntExtra("progress", 0);
- mProgressBar.setProgress(progress);
- }
- }
- }
- </span>
- <span style="font-family:System;">package com.example.communication;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- public class MsgService extends Service {
- /**
- * 进度条的最大值
- */
- public static final int MAX_PROGRESS = 100;
- /**
- * 进度条的进度值
- */
- private int progress = 0;
- private Intent intent = new Intent("com.example.communication.RECEIVER");
- /**
- * 模拟下载任务,每秒钟更新一次
- */
- public void startDownLoad(){
- new Thread(new Runnable() {
- @Override
- public void run() {
- while(progress < MAX_PROGRESS){
- progress += 5;
- //发送Action为com.example.communication.RECEIVER的广播
- intent.putExtra("progress", progress);
- sendBroadcast(intent);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- startDownLoad();
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
- }</span>