绑定方式的Service使用
在实现绑定服务时,最重要的是定义onBind()回调方法返回的接口,有三种方式:
1. 继承Binder类
2. 使用Messenger
3. 使用AIDL
这里对1,2方式进行分析。
1.继承Binder类
如果你的服务是你的应用程序的私有服务,并且跟客户端运行在同一个进程中,那么就应该通过继承Binder类来创建你的接口,并且佛从onBind()方法中返回这个接口的一个实例。客户端接收这个Binder对象,并且能够使用这个对象直接访问Binder类中实现的或Service中的公共方法。
使用官方SDK文档中的例子:
ServiceShow.java
package com.luoye.servicelearn; import java.util.Random; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class ServiceShow extends Service{ private final IBinder binder = new LocalBinder();//创建Service的内部IBinder对象 public class LocalBinder extends Binder { ServiceShow getService() //实现Binder自己的方法,这里返回Service对象的引用 { return ServiceShow.this; } } public int getRandomNumber() { return (new Random()).nextInt(100); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub //返回一个IBinder对象,即Service的内部IBinder对象,作为ServiceConnection中onServiceConnected方法的IBinder传入 return binder; } }
MainActivity.java
package com.luoye.servicelearn; import com.luoye.servicelearn.ServiceShow.LocalBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { ServiceShow localService; boolean bound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void buttonOnClickListener(View v) { switch(v.getId()) { case R.id.start_service1: Intent intent_start = new Intent(this, ServiceShow.class); //绑定Service 第二个参数为ServiceConnection对象,由于bindService是异步的, //bindService()方法立即返回并且不返回IBinder对象,所以需要在ServiceConnection的方法中去处理 //BIND_AUTO_CREATE表示if Service不存在,即onCreate() bindService(intent_start, connection, Context.BIND_AUTO_CREATE); break; case R.id.stop_service1: if(bound) { unbindService(connection); bound = false; }//解绑Service break; case R.id.show_random: if(bound == true) { Toast.makeText(this, "number is :"+localService.getRandomNumber(), Toast.LENGTH_SHORT).show(); } break; } } private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub LocalBinder binder = (LocalBinder)service; //得到service的IBinder对象 localService = binder.getService();//得到Service的引用,后续即可使用Service的方法 bound = true; } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub bound = false; } }; }
2. 使用Messenger
如果需要服务跟远程进程通信,那么就可以使用Messenger对象来给服务提供接口。
以下是信使(Messenger)对象的使用概要:
1. 服务端实现的一个处理器(Handler接口),这个处理器针对每次来自客户端的调用接收一次回调;
2. 这个处理器被用于创建一个信使对象(Messager)(这个信使对象要引用这个处理器);
3. 信使对象创建一个创建一个服务端从onBind()方法中返回给客户端的IBinder对象;
4. 客户端使用这个IBinder对象来实例化这个信使对象(信使引用了服务端的处理器),客户端使用这个信使给服务端发送Message对象;
5. 服务端在它的处理器(Handler)的handleMessage()方法中依次接收每个Message对象
在这种方法中,没有给客户端提供服务端的方法调用,相反,客户端会给发送服务端消息(Message)对象,服务端会在它的处理器中接受这些消息对象。
代码:
ServiceShow.java
package com.luoye.servicelearn; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.widget.Toast; public class ServiceShow extends Service{ static final int MSG_CODE = 0x10;//message的消息类型定义 class IncomingHandler extends Handler //message处理器,应与信使绑定 { public void handleMessage(Message msg) { switch(msg.what) { case MSG_CODE: Toast.makeText(ServiceShow.this, "Hello world", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } //创建一个信使,该信使使用Handler对象作为msg的处理器 final Messenger messenger = new Messenger(new IncomingHandler()); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Toast.makeText(ServiceShow.this, "Binding", Toast.LENGTH_SHORT).show(); return messenger.getBinder();//返回对应信使的Binder,返回给client使用 } }
MainActivity.java
package com.luoye.servicelearn; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { Messenger messenger; boolean bound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void buttonOnClickListener(View v) { switch(v.getId()) { case R.id.start_service1: Intent intent_start = new Intent(this, ServiceShow.class); //绑定Service 第二个参数为ServiceConnection对象,由于bindService是异步的, //bindService()方法立即返回并且不返回IBinder对象,所以需要在ServiceConnection的方法中去处理 //BIND_AUTO_CREATE表示if Service不存在,即onCreate() bindService(intent_start, connection, Context.BIND_AUTO_CREATE); if(bound) { //产生message对象 Message msg = Message.obtain(null, ServiceShow.MSG_CODE, 0, 0); try { //使用client端的信使发送message,该消息会通过Binder对应的信使递交到Service端的 //信使,并由该端信使的消息处理器Handler进行处理 messenger.send(msg); } catch (Exception e) { e.printStackTrace(); } } break; case R.id.stop_service1: if(bound) { unbindService(connection);//解绑Service bound = false; } break; } } private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub messenger = new Messenger(service); //利用Service返回的信使的对应的IBinder来创建client端的信使对象 bound = true; } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub messenger = null; bound = false; } }; }