binder机制是贯穿整个android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的。

service 你可以理解成没有的界面的activity,它是跑在后台的程序,所谓后台是相对于可以被看得到的程序的,后台程序是不能直接交互的程序。

binder主要是用来进程间通信的,但也可用在和本地service通信。

1. 我们先来看一个与本地service通信的例子。

  1. package com.ckt.wangxin;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.Binder;
  5. import android.os.IBinder;
  6. import android.widget.Toast;
  7. /**
  8. * This is a service stub for both LocalBinderClient
  9. * and RemoteBinderClient
  10. * @author Wang Xin
  11. * @email springnap@163.com
  12. *
  13. */
  14. public class LocalService extends Service {
  15. @Override
  16. public IBinder onBind(Intent intent) {
  17. return new LocalBinder();
  18. }
  19. public void sayHelloWorld(){
  20. Toast.makeText(this.getApplicationContext(), "Hello World Local Service!", Toast.LENGTH_SHORT).show();
  21. }
  22. public class LocalBinder extends Binder {
  23. LocalService getService() {
  24. // Return this instance of LocalService so clients can call public methods
  25. return LocalService.this;
  26. }
  27. }
  28. }
package com.ckt.wangxin;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
/**
* This is a service stub for both LocalBinderClient
* and RemoteBinderClient
* @author Wang Xin
* @email springnap@163.com
*
*/
public class LocalService extends Service { @Override
public IBinder onBind(Intent intent) {
return new LocalBinder();
} public void sayHelloWorld(){
Toast.makeText(this.getApplicationContext(), "Hello World Local Service!", Toast.LENGTH_SHORT).show();
} public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
}

local servcie 的代码如上,在onBinder方法中返回binder,binder包含了service的句柄,客户端得到句柄以后就可以调用servcie的公共方法了,这种调用方式是最常见的。

客户端代码

  1. package com.ckt.wangxin;
  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.IBinder;
  9. import android.util.Log;
  10. import com.ckt.wangxin.LocalService.LocalBinder;
  11. public class LocalServiceTestActivity extends Activity {
  12. static final String TAG = "LocalBinderTestActivity";
  13. ServiceConnection mSc;
  14. /** Called when the activity is first created. */
  15. @Override
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.main);
  19. mSc = new ServiceConnection(){
  20. @Override
  21. public void onServiceConnected(ComponentName name, IBinder service) {
  22. Log.d(TAG, "service connected");
  23. LocalService ss = ((LocalBinder)service).getService();
  24. ss.sayHelloWorld();
  25. }
  26. @Override
  27. public void onServiceDisconnected(ComponentName name) {
  28. Log.d(TAG, "service disconnected");
  29. }
  30. };
  31. }
  32. @Override
  33. protected void onStart() {
  34. super.onStart();
  35. Log.d(TAG, this.getApplicationContext().getPackageCodePath());
  36. Intent service = new Intent(this.getApplicationContext(),LocalService.class);
  37. this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
  38. }
  39. @Override
  40. protected void onStop() {
  41. super.onStop();
  42. //must unbind the service otherwise the ServiceConnection will be leaked.
  43. <span style="color: rgb(255, 0, 0); ">this.unbindService(mSc);</span>
  44. }
  45. }
package com.ckt.wangxin;

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.util.Log; import com.ckt.wangxin.LocalService.LocalBinder; public class LocalServiceTestActivity extends Activity {
static final String TAG = "LocalBinderTestActivity";
ServiceConnection mSc; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); mSc = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "service connected");
LocalService ss = ((LocalBinder)service).getService();
ss.sayHelloWorld();
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "service disconnected");
}
};
} @Override
protected void onStart() {
super.onStart();
Log.d(TAG, this.getApplicationContext().getPackageCodePath());
Intent service = new Intent(this.getApplicationContext(),LocalService.class);
this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
} @Override
protected void onStop() {
super.onStop();
//must unbind the service otherwise the ServiceConnection will be leaked.
<span style="color: rgb(255, 0, 0); ">this.unbindService(mSc);</span>
}
}

需要注意的是在onStop中要解绑定service, 否则会造成内存泄露的问题。

2. 我们再看一下与另外一个进程中的service进行通信的问题(跨进程通信!)。

如何将servcie运行在另外一个进程呢?在manifest 里面配置个属性就行了。

android:process=":remote" , 代表这个service运行在同一个应用程序的不同进程中。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.ckt.wangxin"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6. <uses-sdk android:minSdkVersion="15" />
  7. <application
  8. android:icon="@drawable/ic_launcher"
  9. android:label="@string/app_name" >
  10. <activity
  11. android:name=".LocalServiceTestActivity"
  12. android:label="@string/app_name" >
  13. <!--  <intent-filter>
  14. <action android:name="android.intent.action.MAIN" />
  15. <category android:name="android.intent.category.LAUNCHER" />
  16. </intent-filter> -->
  17. </activity>
  18. <service android:name=".LocalService"></service>
  19. <!-- android:process=":remote" specify this service run in
  20. another process in the same application. -->
  21. <service android:name=".RemoteService" android:process=":remote"></service>
  22. <activity android:name="RemoteServiceTestActivity">
  23. <intent-filter>
  24. <action android:name="android.intent.action.MAIN" />
  25. <category android:name="android.intent.category.LAUNCHER" />
  26. </intent-filter>
  27. </activity>
  28. </application>
  29. </manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ckt.wangxin"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" /> <application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".LocalServiceTestActivity"
android:label="@string/app_name" >
<!-- <intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> -->
</activity>
<service android:name=".LocalService"></service>
<!-- android:process=":remote" specify this service run in
another process in the same application. -->
<service android:name=".RemoteService" android:process=":remote"></service>
<activity android:name="RemoteServiceTestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </activity>
</application> </manifest>

客户端可以使用Messenger发送消息到service。

客户端代码:

  1. package com.ckt.wangxin;
  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.os.IBinder;
  10. import android.os.Message;
  11. import android.os.Messenger;
  12. import android.os.RemoteException;
  13. import android.util.Log;
  14. import android.widget.Toast;
  15. public class RemoteServiceTestActivity extends Activity {
  16. static final String TAG = "RemoteServiceTestActivity";
  17. ServiceConnection mSc;
  18. public static final int SAY_HELLO_TO_CLIENT = 0;
  19. /**
  20. * Handler of incoming messages from service.
  21. */
  22. class IncomingHandler extends Handler {
  23. @Override
  24. public void handleMessage(Message msg) {
  25. switch (msg.what) {
  26. case SAY_HELLO_TO_CLIENT:
  27. Toast.makeText(RemoteServiceTestActivity.this.getApplicationContext(), "Hello World Remote Client!",
  28. Toast.LENGTH_SHORT).show();
  29. break;
  30. default:
  31. super.handleMessage(msg);
  32. }
  33. }
  34. }
  35. Messenger messenger_reciever = new Messenger(new IncomingHandler());
  36. /** Called when the activity is first created. */
  37. @Override
  38. public void onCreate(Bundle savedInstanceState) {
  39. super.onCreate(savedInstanceState);
  40. setContentView(R.layout.main);
  41. mSc = new ServiceConnection(){
  42. @Override
  43. public void onServiceConnected(ComponentName name, IBinder service) {
  44. Log.d(TAG, "service connected");
  45. <span style="color: rgb(204, 0, 0); ">Messenger messenger = new Messenger(service);
  46. Message msg = new Message();
  47. msg.what = RemoteService.MSG_SAY_HELLO;</span>
  48. msg.replyTo = messenger_reciever;
  49. try {
  50. <span style="color: rgb(255, 0, 0); ">messenger.send(msg);</span>
  51. } catch (RemoteException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. @Override
  56. public void onServiceDisconnected(ComponentName name) {
  57. Log.d(TAG, "service disconnected");
  58. }
  59. };
  60. }
  61. @Override
  62. protected void onStart() {
  63. super.onStart();
  64. Log.d(TAG, this.getApplicationContext().getPackageCodePath());
  65. Intent service = new Intent(this.getApplicationContext(),RemoteService.class);
  66. this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
  67. }
  68. @Override
  69. protected void onStop() {
  70. super.onStop();
  71. //must unbind the service otherwise the ServiceConnection will be leaked.
  72. this.unbindService(mSc);
  73. }
  74. }
package com.ckt.wangxin;

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.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast; public class RemoteServiceTestActivity extends Activity {
static final String TAG = "RemoteServiceTestActivity";
ServiceConnection mSc;
public static final int SAY_HELLO_TO_CLIENT = 0;
/**
* Handler of incoming messages from service.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SAY_HELLO_TO_CLIENT:
Toast.makeText(RemoteServiceTestActivity.this.getApplicationContext(), "Hello World Remote Client!",
Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
} Messenger messenger_reciever = new Messenger(new IncomingHandler()); /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); mSc = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "service connected");
<span style="color: rgb(204, 0, 0); ">Messenger messenger = new Messenger(service);
Message msg = new Message();
msg.what = RemoteService.MSG_SAY_HELLO;</span>
msg.replyTo = messenger_reciever;
try {
<span style="color: rgb(255, 0, 0); ">messenger.send(msg);</span>
} catch (RemoteException e) {
e.printStackTrace();
}
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "service disconnected");
}
};
} @Override
protected void onStart() {
super.onStart();
Log.d(TAG, this.getApplicationContext().getPackageCodePath());
Intent service = new Intent(this.getApplicationContext(),RemoteService.class);
this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
} @Override
protected void onStop() {
super.onStop();
//must unbind the service otherwise the ServiceConnection will be leaked.
this.unbindService(mSc);
}
}

获得service端传来的binder,用来构建一个Messenger向service发送消息。

service端代码:

  1. package com.ckt.wangxin;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.Handler;
  5. import android.os.IBinder;
  6. import android.os.Message;
  7. import android.os.Messenger;
  8. import android.os.RemoteException;
  9. import android.widget.Toast;
  10. public class RemoteService extends Service {
  11. public static final int MSG_SAY_HELLO = 0;
  12. @Override
  13. public IBinder onBind(Intent intent) {
  14. <span style="color: rgb(204, 0, 0); ">  return messager.getBinder();</span>
  15. }
  16. Handler IncomingHandler = new Handler() {
  17. @Override
  18. public void handleMessage(Message msg) {
  19. if(msg.replyTo != null){
  20. Message msg_client = this.obtainMessage();
  21. msg_client.what = RemoteServiceTestActivity.SAY_HELLO_TO_CLIENT;
  22. try {
  23. ((Messenger)msg.replyTo).send(msg_client);
  24. } catch (RemoteException e) {
  25. // TODO Auto-generated catch block
  26. e.printStackTrace();
  27. }
  28. }
  29. switch (msg.what) {
  30. case MSG_SAY_HELLO:
  31. Toast.makeText(RemoteService.this.getApplicationContext(), "Hello World Remote Service!",
  32. Toast.LENGTH_SHORT).show();
  33. break;
  34. default:
  35. super.handleMessage(msg);
  36. }
  37. }
  38. };
  39. Messenger  messager = new Messenger (IncomingHandler);
  40. }
package com.ckt.wangxin;

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.os.RemoteException;
import android.widget.Toast; public class RemoteService extends Service { public static final int MSG_SAY_HELLO = 0; @Override
public IBinder onBind(Intent intent) {
<span style="color: rgb(204, 0, 0); "> return messager.getBinder();</span>
} Handler IncomingHandler = new Handler() { @Override
public void handleMessage(Message msg) {
if(msg.replyTo != null){
Message msg_client = this.obtainMessage();
msg_client.what = RemoteServiceTestActivity.SAY_HELLO_TO_CLIENT;
try {
((Messenger)msg.replyTo).send(msg_client);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(RemoteService.this.getApplicationContext(), "Hello World Remote Service!",
Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
} }; Messenger messager = new Messenger (IncomingHandler);
}

构建一个Messenger,包含一个handler,然后将messenger的binder传给客户端,客户端可以通过handler再构造一个messenger与service通信,消息在handler里面被处理。

现在是service端单向响应客户端的消息,同理可以做成双向发送消息,实现双向通信。

Android使用binder访问service的方式(一)的更多相关文章

  1. Android 使用binder访问service的方式

    binder机制是贯穿整个Android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的. service 你可以理解成没 ...

  2. android 多进程 Binder AIDL Service

    本文參考http://blog.csdn.net/saintswordsman/article/details/5130947 android的多进程是通过Binder来实现的,一个类,继承了Bind ...

  3. 图解Android - Binder 和 Service

    在 Zygote启动过程 一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了 ...

  4. Android 核心分析 之六 IPC框架分析 Binder,Service,Service manager

    IPC框架分析 Binder,Service,Service manager 我首先从宏观的角度观察Binder,Service,Service Manager,并阐述各自的概念.从Linux的概念空 ...

  5. android学习笔记56——Service

    Service四大组件之一,需要在AndroidMainfest.xml中添加相关配置,运行于后台,不与用户进行交换,没有UI... 配置时可通过<intent-filter.../>元素 ...

  6. Android四大组件之Service

    Android四大组件之Service Android支持服务的概念,服务是在后台运行的组件,没有用户界面,Android服务可用有与活动独立的生命周期.Android支持两种类型的服务: 本地服务: ...

  7. Android面试,与Service交互方式

    五种交互方式,分别是:通过广播交互.通过共享文件交互.通过Messenger(信使)交互.通过自定义接口交互.通过AIDL交互.(可能更多) Service与Thread的区别 Thread:Thre ...

  8. Android四大组件之一 -- Service详解

    相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...

  9. 如何快速学会android的四大基础----Service篇

    很多人都以为,只要学过一点java就可以马上写android应用了,这种想法的产生非常自然,因为现在网上有那么多的android开源实例,只要跟着来,也能够自己写一个播放器.但是,只有去写一个真正投入 ...

随机推荐

  1. 设置mysql group_concat长度

    #在MySQL配置文件(my.ini)中默认无该配置项,使用默认值时,值为1024,可在客户端执行下列语句修改: #SET GLOBAL group_concat_max_len = 1024; #该 ...

  2. ubuntu下安装迅雷thunder

    迅雷是windows xp下必装的下载工具,作为一款跨协议的下载软件,迅雷的下载速度极其强悍. 那么在ubuntu下能否安装迅雷呢? 到ubuntu中文论坛逛了一圈,发现有现成的wine-thunde ...

  3. LUA pcall 多个返回值

    You call lua_pcall with the number of arguments you are passing and the number of results you want. ...

  4. JavaScript escape() unescape() decodeURI()函数对字符串进行编码解码

    定义和用法 escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串. 语法 escape(string) 参数 描述 string 必需.要被转义或编码的字符串. 返回值 已 ...

  5. 关于去哪儿网的UI自动化测试脚本

    UI自动化测试Qunar机票搜索场景访问Qunar机票首页http://flight.qunar.com,选择“单程”,输入出发.到达城市,选择today+7日后的日期,点“搜索”,跳转到机票单程搜索 ...

  6. Fedora下使用minicom及USB串口线

    一.minicom Fedora不像以前的RedHat,不能直接输入minicom回车,因为在目录/dev/下面没有modem这个子目录,而minicom的运行默认是有这个目录的,所以直接敲是不行的. ...

  7. 【转】细说UI线程和Windows消息队列

    在Windows应用程序中,窗体是由一种称为“UI线程(User Interface Thread)”的特殊类型的线程创建的. 首先,UI线程是一种“线程”,所以它具有一个线程应该具有的所有特征,比如 ...

  8. CentOS 7 systemd的坑

    一.概述 在从 CentOS 6 迁移到 CentOS 7 的过程中,可能有一些地方需要调整,最显著的地方莫过于 systemd 带来的改变,不同的管理服务的方式,不同的日志方式,设置时区,时间等等. ...

  9. easyui-linkbutton 设置和获取text文本

    <a id="butTransagt"  href="#" class="easyui-linkbutton"  icon=" ...

  10. Oracle 12C -- 手动创建CDB

    1.指定oracle_sid $ export ORACLE_SID=db12 2.指定环境变量 比如ORACLE_BASE.ORACLE_HOME.PATH(要包含$ORACLE_HOME/bin) ...