Service作为Android四大组件之一,承载着重要的作用,同时,熟悉Service也会为理解Binder打下重要的基础,这里是我初学Android时做的关于Service的笔记,现在总结到这篇文章中。
概述
创建服务步骤
public class MyService extends Service {
//必须实现方法,方法返回IBinder对象,应用程序可通过该对象与Service组件通信
public IBinder onBind(Intent intent) {
Log.i("Other", "MyService.onBind");
return null;
}
//生命周期方法,当Service第一次创建后将立即回调该方法
public void onCreate() {
super.onCreate();
Log.i("Other", "MyService.onCreate");
}
//当Service被关闭之前将回调该方法
public void onDestroy() {
super.onDestroy();
Log.i("Other", "MyService.onDestroy");
}
//每次客户端调用startService(Intent)方法启动该Service时都会回调该方法
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Other", "MyService.onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//当该Service上绑定的所有客户端都断开连接时将回调该方法
public boolean onUnbind(Intent intent) {
Log.i("Other", "MyService.onUnbind");
return super.onUnbind(intent);
}
在配置清单中注册该service
<!-- 注册服务 -->
<service android:name=".MyService">
<intent-filter>
<action android:name="cn.itcast.service.myservice.action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
启动服务
绑定本地Service并与之通信(进程内部绑定服务)
- service:该参数通过Intent指定要启动的Service
- conn:连接,该参数用于接收绑定服务后接收服务传递过来Binder,数据封装在IBinder类中,一般会根据service业务继承ServiceConnection类编写Connection代码,在本例中
/**
* 服务连接对象,是调用者和服务联系的核心
*/
class CustomerServiceConnection implements ServiceConnection{
/**
* 服务连接上之后会回调该方法,服务传回来的数据在binder中
*/
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.i("Other","service connected");
ics = (ICustomerSerice) binder;
}
/**
* 服务连接断开之后会回调该方法.注意,当调用者主动通过unbindService()方法断开Service的连接时,
* onServiceConnected()方法不会被调用。只有Service所在宿主进程由 于异常或其他原因终止,才会调用到该方法
*/
public void onServiceDisconnected(ComponentName name) {
}
}
/**
* 进程内部通信,使用bind方法开启服务.调用者和服务通过
*IBinder对象联系在一 起.
*/
public class CustomerService extends Service {
//访问者绑定服务,服务调用该方法
public IBinder onBind(Intent intent) {
Log.i("Other", "CustomerService.onBind");
//返回自己编写的业务Binder,该类实现IBinder接口,访问者在ServiceConnection的onServiceConnected方法中接收到该Binder对象
return new CustomerServiceBinder();
}
public void onCreate() {
super.onCreate();
Log.i("Other", "CustomerService.onCreate,tid=" + Thread.currentThread().getId());
}
public void onDestroy() {
super.onDestroy();
Log.i("Other", "CustomerService.onDestroy");
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Other", "CustomerService.onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
public boolean onUnbind(Intent intent) {
Log.i("Other", "CustomerService.onUnbind");
return super.onUnbind(intent);
}
/**
* 组合体,既继承了Binder(IBinder的实现类),同时实现自定义业务接口.
*/
class CustomerServiceBinder extends Binder implements ICustomerSerice{
//业务方法
public String sayHello(String name) {
Log.i("Other","CustomerServiceBinder.sayHello("+name+")");
return "hello "+ name ;
}
//业务方法
public Customer findCustomerByName(String name) {
Customer c = new Customer();
c.id = 1000;
c.name = name ;
c.age = 33;
return c;
}
}
}
图示如下:
进程间绑定服务——使用AIDL
进程间服务绑定步骤
服务端
package cn.itcast.service3;
//符合要求4>
import cn.itcast.service3.Person;
interface IPersonService {
String sayHello(in String name);
Person findPersonByName(in String name);
}
IPersionService{
abstarct class Stub extends Binder implements IPersionService{
class proxy{...}
}
}
package cn.itcast.service3;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Javabean
*/
public class Person implements Parcelable {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
/**
* 将javabean信息写入邮包,等价于序列化过程,顺序很关键(反序列化时和序列化顺序相一致)
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeInt(age);
}
/**
* 静态成员,必须是CREATOR,该对象实现Parcelable.Createor接口,用于反 * 序列化
*/
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
//从邮包中得到对象,反序列化过程
public Person createFromParcel(Parcel source) {
Person p = new Person();
p.setId(source.readInt());
p.setName(source.readString());
p.setAge(source.readInt());
return p ;
}
public Person[] newArray(int size) {
return new Person[size];
}
};
}
package cn.itcast.service3;
parcelable Person;
public IBinder onBind(Intent intent) {
Log.i("Other", "PersonService.onBind");
//AIDL接口文件中定义的业务方法
return new IPersonService.Stub() {
public String sayHello(String name) throws RemoteException {
Log.i("Other","PersonService.sayHello()=" + name);
return "hello " + name;
}
//AIDL接口文件中定义的业务方法
public Person findPersonByName(String name) throws RemoteException {
Person p = new Person();
p.setId(2000);
p.setName(name);
p.setAge(23);
return p;
}
};
}
客户端部分
/**
* 服务连接对象
*/
//服务端的业务接口
private IPersonService ips;
class PersonConnection implements ServiceConnection{
//通过生成的类调用其方法,返回业务实现对象,代理对象(封装了进行间的通信细节)
public void onServiceConnected(ComponentName name, IBinder service) {
ips = IPersonService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
}
}
这里调用asInterface()方法其实返回的是stub内部类Proxy,客户端通过该代理可以返回到服务端提供的业务方法。
//绑定远程服务的隐式意图
Intent i = new Intent();
i.setAction("cn.itcast.service.personservice.action");
this.bindService(i, conn, Context.BIND_AUTO_CREATE);
Toast.makeText(this, "远程绑定ok", 1).show();
4、调用业务方法
try {
Toast.makeText(this, ips.sayHello("kkk"),1).show();
} catch (RemoteException e) {
e.printStackTrace();
}
try {
Person p = ips.findPersonByName("jerry");
Toast.makeText(this,p.toString(),1).show();
} catch (RemoteException e) {
e.printStackTrace();
}