service组件二之创建绑定service(Bound Service)

  Bound Service顾名思义,绑定服务。将service与其他组件更有甚于其他appication绑定,并且在service服务的过程中,进行交互。相比于简单的service,增加了交互功能。

  简单来说,实现boundService,在service端,需要实现onBind()方法,同时在内部继承Binder类,只需要实现getService()方法即可。在客户端调用的时候,需要在其内部实现ServiceConnection接口,并且调用bindService()与service进行绑定。交互的数据封装在IBinder里面。

  具体有三类,常用的是:

  1.基于同进程的Extending the Binder class

  2.使用Messenger(多进程间通信IPC)

具体步骤如下:

第一种方式:

  1.创建TestBoundService

    构造内部类继承Binder,重写其getService(),返回当前service对象;重写service 的onBind(),返回内部类对象;具体来说就是service封装进了binder

  

package com.nankang.example.ad.apis;

import java.util.Random;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class TestBoundService extends Service{

private final IBinder ibinder = new TestBoundBinder();
private final Random ran = new Random();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return ibinder;
}

public class TestBoundBinder extends Binder{
TestBoundService getService(){
return TestBoundService.this;
}
}

public int getRandomNum(){
return ran.nextInt(100);
}
}

  2.创建BoundServiceActivity

    a).构造内部类,实现ServiceConnection接口,重写onServiceConnected和onServiceDisconnected,主要是至标志位以及获取service对象;

    b).重写onStart(),onStop()方法,主要是绑定service以及解除绑定(bindService()和unbindService())。在这之前需要初始化内部类的实例。

    c).通过service对象调用service中public的方法。

   

package com.nankang.example.ad.apis;

import com.nankang.example.ad.apis.TestBoundService.TestBoundBinder;

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.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class BoundServiceActivity extends Activity{

private TestBoundService testBoundService;
private boolean flag = false;
private TestConnection conn = new TestConnection();
private Button bt1 ;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.boundservice);
bt1 = (Button)findViewById(R.id.bound_bt1);
init();
}

/**
* 初始化button事件
*/
public void init(){
bt1.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
if(flag){
int num = testBoundService.getRandomNum();
Toast.makeText(BoundServiceActivity.this, "随机数是:"+num, Toast.LENGTH_LONG).show();
}

}
});
}


@Override
protected void onStart(){
super.onStart();
Intent service = new Intent(BoundServiceActivity.this,TestBoundService.class);

bindService(service, conn, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop(){
super.onStop();
if(flag){
unbindService(conn);
flag = false ;
}
}

public class TestConnection implements ServiceConnection{

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
TestBoundBinder tb = (TestBoundBinder)service;
testBoundService = tb.getService();
flag = true ;
}

@Override
public void onServiceDisconnected(ComponentName name) {
flag = false;

}
}
}

 

    需要注意的是:这种方式并未涉及到进程通信。实现ServiceConnection接口,实际上是解锁操作,包括获取Ibinder对象,进而获取当前bound的service。

第二种方式(使用Messenger):

  1.创建TestMessengerService

    主要用到的类有:Messenger,Binder,Handler。三者之间的关系:handler通过Messenger的构造方法封装进了Messenger对象,然后是service和client之间通过binder来通信

    a).创建handler的继承类,用来处理业务逻辑

    b).实例化messenger,封装handler

    c).在onBind方法中返回messenger的binder

package com.nankang.example.ad.apis;

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.Process;
import android.util.Log;
import android.widget.Toast;

public class TestMessengerService extends Service implements FinaleFields{
final Messenger mMessenger = new Messenger(new MsgHandler());
class MsgHandler extends Handler{

@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case msg_ok:
//Log.e("service 线程:", String.valueOf(Thread.currentThread().getId()));
Toast.makeText(getApplicationContext(), msg.getData().getString("info"), Toast.LENGTH_LONG).show();
break;
case msg_exit:
Toast.makeText(getApplicationContext(), "it' over!", Toast.LENGTH_LONG).show();
break;
default:
Toast.makeText(getApplicationContext(), "nothing ", Toast.LENGTH_LONG).show();
break;
}
}
}

@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "prograss:"+Process.myPid(), Toast.LENGTH_LONG).show();
return mMessenger.getBinder();
}

}

  2.创建BoundServiceAcitvity

    a).构造内部类,实现ServiceConnection接口,获取service闯过来的messenger对象

    b).重写onStart(),onStop()方法。

 

    c).调用service具体的过程是,将信息封装进Message,然后通过messenger对象的send方法发送该Message对象到service,由service中的handleMessage方法处理。

package com.nankang.example.ad.apis;

import com.nankang.example.ad.apis.TestBoundService.TestBoundBinder;

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.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class BoundServiceActivity extends Activity implements FinaleFields{

private TestBoundService testBoundService;
private boolean flag = false;
private TestConnection conn = new TestConnection();
private Button bt1 ;
private Messenger mMessenger;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.boundservice);
bt1 = (Button)findViewById(R.id.bound_bt1);
init();
}

/**
* 初始化button事件
*/
public void init(){
bt1.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
// if(flag){
// Log.e("activity 线程:", String.valueOf(Thread.currentThread().getId()));
// int num = testBoundService.getRandomNum();
// Toast.makeText(BoundServiceActivity.this, "随机数是:"+num, Toast.LENGTH_LONG).show();
// }
if(flag){
Log.e("activity线程:", String.valueOf(Thread.currentThread().getId()));
Toast.makeText(getApplicationContext(), "activity prograss:"+Process.myPid(), Toast.LENGTH_LONG).show();
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("info","I'm coming from activity..");
msg.setData(bundle);
msg.what=msg_ok;
try {
mMessenger.send(msg);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
});
}


@Override
protected void onStart(){
super.onStart();
//Intent service = new Intent(BoundServiceActivity.this,TestBoundService.class);
Intent service = new Intent(BoundServiceActivity.this,TestMessengerService.class);
bindService(service, conn, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop(){
super.onStop();
if(flag){
unbindService(conn);
flag = false ;
}
}

public class TestConnection implements ServiceConnection{

// @Override
// public void onServiceConnected(ComponentName name, IBinder service) {
// TestBoundBinder tb = (TestBoundBinder)service;
// testBoundService = tb.getService();
// flag = true ;
// }

public void onServiceConnected(ComponentName name, IBinder service){
mMessenger = new Messenger(service);
flag = true ;
}

@Override
public void onServiceDisconnected(ComponentName name) {
flag = false;

}
}
}


  上面只是单方面的client向service发送消息,若是要client接收service发送的消息,同样可以在client初始化handler以及messenger对象,然后client向service发送消息的时候将messenger对象通过msg.replyTo封装进message对象中.

总结:

  绑定到service需要经过以下几个步骤:

  1.实现ServiceConnection接口

  2.调用bindService方法

  3.初始化service对象

  4.释放service,调用unbindService().

  

  


  

posted @ 2011-11-04 16:07  我要当地主  阅读(475)  评论(0)    收藏  举报