代码改变世界

service bound(二)

2013-04-06 16:32  java20130722  阅读(194)  评论(0编辑  收藏  举报

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;
			}
			
		}
	}



---Handler用于创建Messenger对象。

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();
		}

---Service 通过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>