android service 的简单实例 binder service

时间:2021-10-14 16:30:50

Service 这个一搜一大把详细的介绍,这里就不多说了。 实质就是一种不用和用户交互,在后台运行的一种 服务。

Service 分为 绑定的 和  不绑定的。

不绑定的:简单说:就是当你启动service后,不去主动的 StopService() 它 或者 不在service中调用  stopSelf() 是不会停止的。

绑定的:简单说:当你的绑定组件 启动service后,组件解除 绑定,那么service就会销毁,当然允许多个组件绑定,直到没有组件绑定到service的时候,它就会销毁了。

下来看例子。不绑定的 我注释的代码写的很清楚,那个很简单。主要说下 绑定的service,界面就是由2个按钮  1个是绑定,1个是解除绑定。

android  service 的简单实例 binder service

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


Service.java

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 oncreate 并且进入回调方法):

android  service 的简单实例 binder service

当点击activity中的解除绑定按钮时(进入到了service  desroty 方法),

android  service 的简单实例 binder service

二,现在要实现 activity 和service间的相互通信

android  service 的简单实例 binder service


(xml 太过简单就不贴了,代码自己考过去画几个button 就可以测了呢 )当我点击 通信按钮。

android  service 的简单实例 binder service           android  service 的简单实例 binder service


上面第一张是,我点击通讯按钮后,进入到了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;
}
}
}

HandlerService.java

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的通信下个说 = =,