android service詳解
服務--Service
Android中的服務和windows中的服務是類似的東西,服務一般沒有使用者操作介面,它執行於系統中不容易被使用者發覺,可以使用它開發如監控之類的程式。服務的開發比較簡單,如下:
第一步:繼承Service類
public class SMSService extends Service { }
第二步:在AndroidManifest.xml檔案中的<application>節點裡對服務進行配置:
<service android:name=".SMSService" />
服務不能自己執行,需要通過呼叫Context.startService()或Context.bindService()方法啟動服務。這兩個方法都可以啟動Service,但是它們的使用場合有所不同。使用startService()方法啟用服務,訪問者與服務之間沒有關連,即使訪問者退出了,服務仍然執行。使用bindService()方法啟用服務,訪問者與服務繫結在了一起,訪問者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
採用Context.startService()方法啟動服務,只能呼叫Context.stopService()方法結束服務,服務結束時會呼叫onDestroy()方法。
兩種方式啟動服務的區別:
通過startService()和stopService()啟動關閉服務。適用於服務和訪問者之間沒有互動的情況。如果服務和訪問者之間需要方法呼叫或者傳遞引數,側需要使用bindService()和unbindService()方法啟動關閉服務。
採用Context.bindService()方法啟動服務,在服務未被建立時,系統會先呼叫服務的onCreate()方法,接著呼叫onBind()方法,這個時候訪問者和服務繫結在一起。 如果訪問者要與服務進行通訊,那麼,onBind()方法必須返回Ibinder物件。如果訪問者退出了,系統就會先呼叫服務的onUnbind()方法,接著呼叫onDestroy()方法。如果呼叫bindService()方法前服務已經被繫結,多次呼叫bindService()方法並不會導致多次建立服務及繫結(也就是說onCreate()和onBind()方法並不會被多次呼叫)。如果訪問者希望與正在繫結的服務解除繫結,可以呼叫unbindService()方法,呼叫該方法也會導致系統呼叫服務的onUnbind()-->onDestroy()方法。
服務的生命週期回撥方法:
服務的生命週期跟啟動服務的方法有關:
當採用Context.startService()方法啟動服務,與之有關的生命週期方法
onCreate()--> onStart()--> onDestroy()
onCreate()該方法在服務被建立時呼叫,該方法只會被呼叫一次,無論呼叫多少次startService()或bindService()方法,服務也只被建立一次。
onStart() 只有採用Context.startService()方法啟動服務時才會回撥該方法。該方法在服務開始執行時被呼叫。多次呼叫startService()方法儘管不會多次建立服務,但onStart() 方法會被多次呼叫。
onDestroy()該方法在服務被終止時呼叫。
當採用Context.bindService()方法啟動服務,與之有關的生命週期方法
onCreate()--> onBind() --> onUnbind() --> onDestroy()
onBind()只有採用Context.bindService()方法啟動服務時才會回撥該方法。該方法在呼叫者與服務繫結時被呼叫,當呼叫者與服務已經繫結,多次呼叫Context.bindService()方法並不會導致該方法被多次呼叫。
onUnbind()只有採用Context.bindService()方法啟動服務時才會回撥該方法。該方法在呼叫者與服務解除繫結時被呼叫。
如果先採用startService()方法啟動服務,然後呼叫bindService()方法繫結到服務,再呼叫unbindService()方法解除繫結,最後呼叫bindService()方法再次繫結到服務,觸發的生命週期方法如下:
onCreate()-->onStart()-->onBind()-->onUnbind()[過載後的方法需返回true-->onRebind()
使用AIDL和遠端服務實現程式通訊
在Android中, 每個應用程式都有自己的程式,當需要在不同的程式之間傳遞物件時,該如何實現呢? 顯然, Java中是不支援跨程式記憶體共享的。因此要傳遞物件, 需要把物件解析成作業系統能夠理解的資料格式, 以達到跨界物件訪問的目的。在JavaEE中,採用RMI通過序列化傳遞物件。在Android中, 則採用AIDL(Android Interface Definition Language:介面定義語言)方式實現。
AIDL是一種介面定義語言,用於約束兩個程式間的通訊規則,供編譯器生成程式碼,實現Android裝置上的兩個程式間通訊(IPC)。AIDL的IPC機制和EJB所採用的CORBA很類似,程式之間的通訊資訊,首先會被轉換成AIDL協議訊息,然後傳送給對方,對方收到AIDL協議訊息後再轉換成相應的物件。由於程式之間的通訊資訊需要雙向轉換,所以android採用代理類在背後實現了資訊的雙向轉換,代理類由android編譯器生成,對開發人員來說是透明的。
實現程式通訊,一般需要下面四個步驟:
假設A應用需要與B應用進行通訊,呼叫B應用中的download(String path)方法,B應用以Service方式向A應用提供服務。需要下面四個步驟:
1> 在B應用中建立*.aidl檔案,aidl檔案的定義和介面的定義很相類,如:在cn.itcast.aidl包下建立IDownloadService.aidl檔案,內容如下:
package cn.itcast.aidl;
interface IDownloadService {
void download(String path);
}
當完成aidl檔案建立後,eclipse會自動在專案的gen目錄中同步生成IDownloadService.java介面檔案。介面檔案中生成一個Stub的抽象類,裡面包括aidl定義的方法,還包括一些其它輔助方法。值得關注的是asInterface(IBinder iBinder),它返回介面型別的例項,對於遠端服務呼叫,遠端服務返回給客戶端的物件為代理物件,客戶端在onServiceConnected(ComponentName name, IBinder service)方法引用該物件時不能直接強轉成介面型別的例項,而應該使用asInterface(IBinder
iBinder)進行型別轉換。
編寫Aidl檔案時,需要注意下面幾點:
1.介面名和aidl檔名相同。
2.介面和方法前不用加訪問許可權修飾符public,private,protected等,也不能用final,static。
3.Aidl預設支援的型別包話java基本型別(int、long、boolean等)和(String、List、Map、CharSequence),使用這些型別時不需要import宣告。對於List和Map中的元素型別必須是Aidl支援的型別。如果使用自定義型別作為引數或返回值,自定義型別必須實現Parcelable介面。
4.自定義型別和AIDL生成的其它介面型別在aidl描述檔案中,應該顯式import,即便在該類和定義的包在同一個包中。
5.在aidl檔案中所有非Java基本型別引數必須加上in、out、inout標記,以指明引數是輸入引數、輸出引數還是輸入輸出引數。
6.Java原始型別預設的標記為in,不能為其它標記。
2> 在B應用中實現aidl檔案生成的介面(本例是IDownloadService),但並非直接實現介面,而是通過繼承介面的Stub來實現(Stub抽象類內部實現了aidl介面),並且實現介面方法的程式碼。內容如下:
public class ServiceBinder extends IDownloadService.Stub {
@Override
public void download(String path) throws RemoteException {
Log.i("DownloadService", path);
}
}
3> 在B應用中建立一個Service(服務),在服務的onBind(Intent intent)方法中返回實現了aidl介面的物件(本例是ServiceBinder)。內容如下:
public class DownloadService extends Service {
private ServiceBinder serviceBinder = new ServiceBinder();
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
public class ServiceBinder extends IDownloadService.Stub {
@Override
public void download(String path) throws RemoteException {
Log.i("DownloadService", path);
}
}
}
其他應用可以通過隱式意圖訪問服務,意圖的動作可以自定義,AndroidManifest.xml配置程式碼如下:
<service android:name=".DownloadService" >
<intent-filter>
<action android:name="cn.itcast.process.aidl.DownloadService" />
</intent-filter>
</service>
4> 把B應用中aidl檔案所在package連同aidl檔案一起拷貝到客戶端A應用,eclipse會自動在A應用的gen目錄中為aidl檔案同步生成IDownloadService.java介面檔案,接下來就可以在A應用中實現與B應用通訊,程式碼如下:
public class ClientActivity extends Activity {
private IDownloadService downloadService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.bindService(new Intent("cn.itcast.process.aidl.DownloadService"), this.serviceConnection, BIND_AUTO_CREATE);//繫結到服務
}
@Override
protected void onDestroy() {
super.onDestroy();
this.unbindService(serviceConnection);//解除服務
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadService = IDownloadService.Stub.asInterface(service);
try {
downloadService.download("http://www.itcast.cn");
} catch (RemoteException e) {
Log.e("ClientActivity", e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
downloadService = null;
}
};
}
程式間傳遞自定義型別引數
要傳遞自定義型別,首先要讓自定義型別支援parcelable協議,實現步驟如下:
1>自定義型別必須實現Parcelable介面,並且實現Parcelable介面的public void writeToParcel(Parcel dest, int flags)方法 。
2>自定義型別中必須含有一個名稱為CREATOR的靜態成員,該成員物件要求實現Parcelable.Creator介面及其方法。
3> 建立一個aidl檔案宣告你的自定義型別。
Parcelable介面的作用:實現了Parcelable介面的例項可以將自身的狀態資訊(狀態資訊通常指的是各成員變數的值)寫入Parcel,也可以從Parcel中恢復其狀態。 Parcel用來完成資料的序列化傳遞。
Parcelable介面與Serailzable介面區別:
Serailzable介面為 jdk中定義,Parcelable介面為GOOGLE在android sdk中定義
都是用來實現資料的可序列化
序列化的方式不同
相關文章
- Android Service詳解(一)Android
- Android Service詳解(二)Android
- Android-Service詳解Android
- Android Service生命週期 Service裡面的onStartCommand()方法詳解Android
- Service詳解
- Angular service 詳解Angular
- k8s之Service詳解-Service使用K8S
- Service Mesh技術詳解
- Android ServiceAndroid
- konga新增service和rouce詳解
- Android Service和IntentService知識點詳細總結AndroidIntent
- Android Intent ServiceAndroidIntent
- Android Service SecurityAndroid
- Android AsyncTask 詳解Android
- Android拖拽詳解Android
- Android Service完全解析Android
- Android工程gradle詳解AndroidGradle
- Android元件詳解—TextViewAndroid元件TextView
- Android AIDL使用詳解AndroidAI
- Android-Application詳解AndroidAPP
- Android混淆(Proguard)詳解Android
- Android SecureRandom漏洞詳解Androidrandom
- Android 向量圖詳解Android
- Android BroadcastReceiver使用詳解AndroidAST
- Android:動畫詳解Android動畫
- Android Gson使用詳解Android
- Android總結篇系列:Android ServiceAndroid
- kubernetes實踐之四十三: Service詳解
- Android中Service總結Android
- Android中的Web ServiceAndroidWeb
- Android 之Service使用攻略Android
- Android之Service設定android:process作用Android
- Android 訊息機制詳解(Android P)Android
- Android FlexboxLayout 佈局詳解AndroidFlex
- Android輸入事件詳解Android事件
- Android-SharedPreferences 使用詳解Android
- Android Bluetooth HCI log 詳解Android
- [轉]Android 通知Notification 詳解Android
- Android 加密知識詳解Android加密