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