Service 这个一搜一大把详细的介绍,这里就不多说了。 实质就是一种不用和用户交互,在后台运行的一种 服务。
Service 分为 绑定的 和 不绑定的。
不绑定的:简单说:就是当你启动service后,不去主动的 StopService() 它 或者 不在service中调用 stopSelf() 是不会停止的。
绑定的:简单说:当你的绑定组件 启动service后,组件解除 绑定,那么service就会销毁,当然允许多个组件绑定,直到没有组件绑定到service的时候,它就会销毁了。
下来看例子。不绑定的 我注释的代码写的很清楚,那个很简单。主要说下 绑定的service,界面就是由2个按钮 1个是绑定,1个是解除绑定。
MainActivity.java 界面
public class MainActivity extends Activity { //用来绑定链接的 private ServiceConnection conn; //判断是否已绑定 public boolean isBind = false; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //当 service启动后,再次启动 service,不会调用oncreate方法了,而是直接调用onStartCommand 方法 /** * 1. * 平常简单的启动service的方法 startService * 停止serviced的方法 stopService * 这个的特点就是 没有绑定service,当启动service的这个activity消失后,service仍然存在, * 想要停止 service 必须手动 stop * * //startService(new Intent()) * //stopService(name) */ /** * 2. 绑定的(同一进程中) */ conn = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { // 当绑定时 会从这个回调接口得到 binder对象 通过binder对象绑定的 MainBinService.BinServiceBind sBinder = (MainBinService.BinServiceBind)service; // 然后使用 binder对象的方法 System.out.println( "11 + 11 = " + sBinder.add(11,11)); System.out.println("sBinder.getService().toString()"+ sBinder.getBinServiceBind().toString()); } @Override public void onServiceDisconnected(ComponentName name) { } }; //启动绑定button ((Button)this.findViewById(R.id.button1)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //BIND_DEBUG_UNBIND 这个flag 用于调试 BIND_AUTO_CREATE 默认使用的 MainActivity.this.bindService(new Intent(MainActivity.this, MainBinService.class), conn, Context.BIND_AUTO_CREATE);//这个flag 默认使用 isBind = true; } }); //解除绑定 button ((Button)this.findViewById(R.id.button2)).setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(isBind){ // 多次调用 unbindService 会抛出异常 MainActivity.this.unbindService(conn); } } }); }
public class MainBinService extends Service{ /** * android:process ---------- 表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字 * android:enabled ---------- 如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false * android:exported --------- 表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false */ private BinServiceBind myBind; //bind public class BinServiceBind extends Binder{ public MainBinService getBinServiceBind(){ return MainBinService.this; } public int add(int a,int b){ return a+b; } } // 返回binder 对象 @Override public IBinder onBind(Intent arg0) { return myBind; } @Override public void onCreate() { super.onCreate(); System.out.println(" SERVCEI oncreate = "); myBind = new BinServiceBind(); } @Override public boolean onUnbind(Intent intent) { // 所有的客户端使用unbindService()解除了绑定 return false; } @Override public void onRebind(Intent intent) { // 一个客户端在调用onUnbind()之后,正使用bindService()绑定到service } @Override public void onDestroy() { System.out.println(" service destory"); super.onDestroy(); } /** * 注意方法onStartCommand()必须返回一个整数.这个整数描述了在系统杀死它的事件中系统如何继续这个服务 * onStartCommand()返回值必须是下面常量之一: START_NOT_STICKY 如果系统在onStartCommand()返回后杀死了服务,不要重新创建这个service,除非还有挂起的intent需要被传送. 这是避免在不必要时运行你的service和当你的应用可以简单重启任何未竟的工作时的最佳选择. START_STICKY 如果系统在onStartCommand()返回后杀死了这个service,会重新创建这个service并且调用onStartCommand(),但是不再重新发送上次最后一个intent, 而是使用一个nullintent调用onStartCommand(),除非有一些挂起的intent,在此情况下,这些挂起的intent被派送.这适合于媒体播放器(or或相似也的服务), 它不执行命令,但是无限期的运行并等待一个工作. START_REDELIVER_INTENT 如果系统在onStartCommand()返回后杀死了service,重新创建这个service并且使用上次最后一个intent调用onStartCommand(). 任何挂起的intent都顺序地被派送.这适合于活跃地执行一个工作并且应被立即恢复的服务,比如下载一个文件. */ @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } }
当点击activity中的解除绑定按钮时(进入到了service desroty 方法),
二,现在要实现 activity 和service间的相互通信
(xml 太过简单就不贴了,代码自己考过去画几个button 就可以测了呢 )当我点击 通信按钮。
上面第一张是,我点击通讯按钮后,进入到了service, 第2张是 service 处理完自己的事后(3秒后),给activity 返回的1个信息,并在activity中显示toast
要用到 Messenger(信使) 注释非常详细了,实质就是通过Messenger 对象然后进行消息的发送。
先来 HandlerActivity.java
public class HandlerActivity extends Activity { //接收service的 Messenger private Messenger serviceMessenger = null; //activity本身 的 Messenger private Messenger myMessenger =null ; boolean mBound; static final int service_back = 1; //Handler private Handler handler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what){ case service_back: //当service 完成自己的事情后 通知activity 显示 toast Toast.makeText(getApplicationContext(), "service back ==!", Toast.LENGTH_SHORT).show(); break; } }; }; /** *与service的主接口交互的类 */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // 当与service的连接已经建立时被调用,获得service 返回的 Ibinder对象 serviceMessenger = new Messenger(service); mBound = true; } public void onServiceDisconnected(ComponentName className) { // 当与service的连接意外断开时被调用-- 也就是,service的进程崩溃了 serviceMessenger = null; mBound = false; } }; public void doSomethings() { if (!mBound){ return; } myMessenger = new Messenger(handler); // 创建并发送一个消息给service Message msg = Message.obtain(null, HandlerService.Hello_Service, 0, 0); //指明此message发送到何处的可选Messenger对象。具体的使用方法由发送者和接受者决定。 msg.replyTo = myMessenger; try { //将包含本身 Messenger 的 message发送出去 serviceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //点击 activity的 button 给 service 发送消息 让其执行 ((Button)this.findViewById(R.id.button3)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //调用sen message doSomethings(); } }); } @Override protected void onStart() { super.onStart(); // 这个class 是为了测试通讯,所以启动的时候直接绑定到service bindService(new Intent(this, HandlerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mConnection); mBound = false; } } }
public class HandlerService extends Service { public static final int Hello_Service = 1; // Handler处理 private Handler handler =new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what) { case Hello_Service: //显示toast Toast.makeText(getApplicationContext(), " Hello_Service_in_handler! ", Toast.LENGTH_SHORT).show(); //得到msg 就可以用 得到的 messenger 给客户端发送数据了 replyMessenger = msg.replyTo; //执行相应的操作 th.start(); break; default: super.handleMessage(msg); } } }; //使用 信息给客户端发送消息 发送消息的的对象 private final Messenger serviceMessenger = new Messenger(handler); // 得到的客户端传递过来的 Messenger(信使) private Messenger replyMessenger ; //做了1个假的执行操作的线程 private Thread th = new Thread(){ public void run() { try { Thread.sleep(3000); //假设上面执行了自己操作3秒 //现在给客户端回应 Message msg = Message.obtain(null, HandlerActivity.service_back, 0,0); replyMessenger.send(msg); } catch (RemoteException e) { } catch (InterruptedException e) { } }; }; /** * 当绑定到service,我们返回指向我们的messenger的接口 */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return serviceMessenger.getBinder(); } /** * 当你需要执行IPC时,为你的接口使用一个Messenger比使用AIDL实现它简单, * 因为Messenger把所有对service的调用入队列,一个纯AIDL接口并行发送请求到service,这样就必须用多线程来处理了. 对于大多数应用,service不需使用多线程,所以使用一个Messenger允许service在一个时刻只处理一个请求. 如果要使用多线程,那么就要使用到AIDL */ @Override public void onCreate() { super.onCreate(); } /** Messenger:信使 官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。 该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger, 客户端持有这个Messenger就可以与服务端通信了。 * * 以前我们使用Handler+Message的方式进行通信,都是在同一个进程中,从线程持有一个主线程的Handler对象,并向主线程发送消息。 而Android既然可以使用bindler机制进行跨进行通信,所以我们当然可以将Handler与bindler结合起来进行跨进程发送消息。 查看API就可以发现,Messenger就是这种方式的实现。 */ }
好了这个有点长了 AIDL的通信下个说 = =,