最近在研究Android写一个学习笔记:
一个BoundService 相当于C/S模式下的服务器,可以接受其他组件(如Activity)的连接,然后可以发请求,接受回复
创建一个BoundService,首先需要提供一个IBinder来实现C/S的通信,有三种方式来实现一个IBinder:
界面文件
一个BoundService 相当于C/S模式下的服务器,可以接受其他组件(如Activity)的连接,然后可以发请求,接受回复
创建一个BoundService,首先需要提供一个IBinder来实现C/S的通信,有三种方式来实现一个IBinder:
-
继承Binder类
-
使用Messager
-
使用AIDL(Android Interface Definition Language)
在Service里创建一个Binder的对象,该对象内容必须包含以下三点:
1.该对象包含可以被客户端调用的公共方法;
2.该对象要返回一个当前service的实例,以便客户端可以调用上面的方法;
3.在onBinder()方法里返回Binder对象
在客户端的onServiceConnected()方法里,客户通过对上面第二步返回的Service里方法的调用,实现通信。
Activity代码需要通过ServiceConnection(接口)的内部类实现来连接Service和Activity。
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。
Context.BIND_AUTO_CREATE:常量的作用,只要binding存在,就自动建立服务
使用使用bindService()启动Service会经历:
bindService()--onCreate() -- onBind() -- Service running-- onUnbind() -- onDestroy()
onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。把调用者(Context,例如Activity)和Service绑定在一起,Context退出了,Service就会调用onUnbind -- onDestroy相应退出,所以调用bindService的生命周期为:
onCreate() -- onBind(只一次,不可多次绑定) -- onUnbind() -- onDestory()
本地服务和Activity交互的示例:
如果activity和service之间需要传递参数或者方法调用,需要使用bind和unbind方法,这时activity和service是绑定在一起的。
以下是效果图,后台服务开启一个线程,每秒不断加一计数,前台Activity点第一个按钮绑定Service:

package org.newboy.activity;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
/*
* 计数的服务
*/
public class CountService extends Service {
private int count = 0; //从0开始
private boolean threadDisabled = false; //判断线程是否可用
@Override
public IBinder onBind(Intent intent) {
Log.i("tag", "onBind方法");
//3.在onBinder()方法里返回Binder对象
return new CountBinder();
}
//继承于Binder类
public class CountBinder extends Binder {
//1. 包含可供客户端调用的公共方法
public CountService getCountService() {
//2.返回当前Service的实例
return CountService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i("tag", "运行onCreate");
new Thread(new Runnable() {
@Override
public void run() {
while (!threadDisabled) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
Log.i("tag", "count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisabled = true;
Log.i("tag", "onDestroy");
}
/**
* 外面的应用得到此count的值
* @return
*/
public int getCount() {
return count;
}
}
package org.newboy.activity;
import org.newboy.activity.CountService.CountBinder;
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.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/*
* 本地绑定的服务实例
*/
public class MainActivity extends Activity {
private TextView txtShow; //显示信息文本框
private Button buttonStart; //服务开始按钮
private Button buttonShow; //显示后台服务的值
private Button buttonStop; //服务停止
private CountService countService; // 服务对象
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtShow = (TextView) findViewById(R.id.txtShow);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonShow = (Button) findViewById(R.id.buttonShow);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(listener);
buttonShow.setOnClickListener(listener);
buttonStop.setOnClickListener(listener);
}
// 服务连接以后的事件
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
//服务停止的事件
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// IBinder服务对象
CountBinder binder = (CountBinder) service;
countService = binder.getCountService();
}
};
private View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonStart:
// 开始后台的服务
Intent service = new Intent(MainActivity.this, CountService.class);
// 建立服务
bindService(service, conn, Context.BIND_AUTO_CREATE);
Toast.makeText(MainActivity.this, "服务连接", Toast.LENGTH_SHORT).show();
break;
case R.id.buttonShow:
// 调用后台服务的方法
int count = countService.getCount();
txtShow.setText("当前的计数是:" + count);
break;
case R.id.buttonStop:
// 停止服务
unbindService(conn);
Toast.makeText(MainActivity.this, "服务断开", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
}
以下是配置文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.newboy.activity" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="后台服务绑定演示">
<activity android:name="org.newboy.activity.MainActivity"
android:label="后台服务绑定演示">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 后台服务类 -->
<service android:name="org.newboy.activity.CountService" />
</application>
</manifest>
界面文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent" android:id="@+id/txtShow"
android:gravity="center_horizontal" android:textSize="22sp"
android:layout_height="wrap_content" android:text="得到服务的值"
android:layout_marginTop="5dip" android:layout_marginBottom="5dip" />
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<Button android:text="开始" android:id="@+id/buttonStart"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
<Button android:text="显示" android:id="@+id/buttonShow"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
<Button android:text="停止" android:id="@+id/buttonStop"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
</LinearLayout>
</LinearLayout>