service bound(二)
service 绑定有三种实现方式:
1. 直接继承Binder类实现。
条件: 同一应用,同一进程
2. 使用Messenger实现。
条件:要在不同的进程间通信,这种方式不用考虑线程安全性。(单线程操作时使用)
3. 使用AIDL实现。
条件:要在不同的进程间通信,并且需要多线程处理。要考虑线程之间的安全性。
通过Messenger实现bound service。
实现步骤:
- service 要实现Handler,service通过Handler可以得到客户端的调用请求。
- Handler用于创建Messenger对象。
- Messenger创建一个IBinder,client调用onBind()时,IBinder返回给client的
- Clients 通过IBinder实例化Messenger
- service 通过Handler收到每一个Message, 在
handleMessage()
方法明确的处理.
---service 要实现Handler,service通过Handler可以得到客户端的调用请求。
class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REGISTER:
if(msg.replyTo != null && !messengerList.contains(msg.replyTo)){
messengerList.add(msg.replyTo) ;
}
Toast.makeText(getApplicationContext(), "bound", Toast.LENGTH_SHORT).show();
break;
case UNREGISTER:
if(msg.replyTo != null && messengerList.contains(msg.replyTo)){
messengerList.remove(msg.replyTo) ;
}
Toast.makeText(getApplicationContext(), "unbound", Toast.LENGTH_SHORT).show();
break;
case REPLYTO:
Message message = Message.obtain(null, 1, 0, 0);
Bundle data = new Bundle() ;
data.putString("REPLYTO", "reply from service") ;
message.setData(data) ;
try {
msg.replyTo.send(message) ;
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
default:
super.handleMessage(msg);
break;
}
}
}
private Messenger messenger = new Messenger(new MessengerHandler()) ;
---Messenger创建一个IBinder,client调用onBind()时,IBinder返回给client的
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
---Clients 通过IBinder实例化Messenger
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service); //通过IBinder 实例化Messenger
mBound = true ;
registerService();
}
---S ervice 通过Handler收到每一个Message, 在
handleMessage()
方法明确的处理.
try {
Message msg = Message.obtain(null , MessengerService.REGISTER,0,0) ;
msg.replyTo = mMessenger ;
mService.send(msg) ;
} catch (RemoteException e) {
e.printStackTrace();
}
Service的所有code:
package com.hualu.serviceexample.messenger;
import java.util.ArrayList;
import java.util.List;
import android.app.Service;
import android.content.Intent;
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.widget.Toast;
/**
* 测试不在同一个进程中, 不需要考虑线程安全性
* @author Administrator
*
*/
public class MessengerService extends Service {
final static int REGISTER = 1;
final static int UNREGISTER = 2;
final static int REPLYTO = 3;
private Messenger messenger = new Messenger(new MessengerHandler()) ;
private List<Messenger> messengerList = new ArrayList<Messenger>() ;
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REGISTER:
if(msg.replyTo != null && !messengerList.contains(msg.replyTo)){
messengerList.add(msg.replyTo) ;
}
Toast.makeText(getApplicationContext(), "bound", Toast.LENGTH_SHORT).show();
break;
case UNREGISTER:
if(msg.replyTo != null && messengerList.contains(msg.replyTo)){
messengerList.remove(msg.replyTo) ;
}
Toast.makeText(getApplicationContext(), "unbound", Toast.LENGTH_SHORT).show();
break;
case REPLYTO:
Message message = Message.obtain(null, 1, 0, 0);
Bundle data = new Bundle() ;
data.putString("REPLYTO", "reply from service") ;
message.setData(data) ;
try {
msg.replyTo.send(message) ;
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
default:
super.handleMessage(msg);
break;
}
}
}
}
Activity 中所有的Code:
package com.hualu.serviceexample.messenger;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.hualu.serviceexample.R;
public class MessengerActivity extends Activity implements OnClickListener{
private Messenger mService ;
private boolean mBound ;
private Button messenger, unBound, replyFromService ;
private TextView text ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_binder_messenger) ;
text = (TextView)this.findViewById(R.id.textView1) ;
messenger = (Button)this.findViewById(R.id.messenger) ;
unBound = (Button)this.findViewById(R.id.unbound) ;
replyFromService = (Button)this.findViewById(R.id.reply_from_service) ;
messenger.setOnClickListener(this) ;
unBound.setOnClickListener(this) ;
replyFromService.setOnClickListener(this) ;
}
private ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service); ;
mBound = true ;
registerService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false ;
}
} ;
@Override
protected void onStart() {
super.onStart() ;
boundService() ;
};
@Override
protected void onStop() {
super.onStop() ;
if(mBound){
unbindService(conn);
mMessenger = null;
mBound = false;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.messenger:
boundService();
break;
case R.id.unbound:
unBoundService() ;
break ;
case R.id.reply_from_service:
replyFromService() ;
break;
}
}
private void boundService() {
bindService(new Intent("com.hualu.serviceexample.BIND_MESSENGER_SERVICE"), conn, Context.BIND_AUTO_CREATE) ;
text.setText("bound") ;
}
private void registerService(){
try {
Message msg = Message.obtain(null , MessengerService.REGISTER,0,0) ;
msg.replyTo = mMessenger ;
mService.send(msg) ;
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void replyFromService() {
if(mService != null){
try {
Message msg = Message.obtain(null , MessengerService.REPLYTO,0,0) ;
msg.replyTo = mMessenger ;
mService.send(msg) ;
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
private void unBoundService() {
if (mBound) {
if(mService != null){
Message msg = Message.obtain(null , MessengerService.UNREGISTER,0,0) ;
msg.replyTo = mMessenger ;
try {
mService.send(msg) ;
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(conn) ;
mBound =false;
mService = null;
text.setText("unbound") ;
}
};
private Messenger mMessenger = new Messenger(new MessengerActivityHandler()) ;
class MessengerActivityHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Bundle data = msg.getData() ;
String str = data.getString("REPLYTO");
text.setText(str) ;
break;
default:
super.handleMessage(msg);
break;
}
}
}
}
在activity和service中,实现了双向通道,既可以从activity中发送消息给service,也可以从service中发送消息给activity。都是通过Messenger实现的。
activity中的registerService()和unBoundService()方法,发送消息到service中;
replyFromService()是既发送消息到service中,又收到service返回的消息。
与上面说的对应的是在service里面的Handler的handleMessage()里面
Layout文件的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:orientation="vertical" >
<Button
android:id="@+id/messenger"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/messenger" />
<Button
android:id="@+id/unbound"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/unbound_messenger" />
<Button
android:id="@+id/reply_from_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/reply_from_service" />
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
Manifest中相关的code:
<activity android:name=".messenger.MessengerActivity">
<intent-filter>
<action android:name="com.hualu.serviceexample.BIND_MESSENGER_ACTIVITY"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
<service android:name=".messenger.MessengerService">
<intent-filter>
<action android:name="com.hualu.serviceexample.BIND_MESSENGER_SERVICE"></action>
</intent-filter>
</service>