之前寫過一篇關於綁定前臺Service實現APP安裝包下載的文章
http://blog.csdn.net/androidmsky/article/details/53407925
今天自己也是溫習了一下,確實普通應用開發Service用的比較少,不過他又是四大組件中僅次於Activity的傢伙,所以決定再探Service。
設想場景,我們可以在一個獨立進程的Service中進行復雜的計算,或者多媒體音樂的播放等。開啓一個獨立進程的優勢主要就是系統會給我開啓獨立的內存空間從而突破一個程序(準確說是一個進程)的最大內存限制。當然對於多進程又有很多弊端,最大的弊端想必就是原來很方便的事變得複雜,原本同一進程的綁定方法的Binder將不可用。那麼我們就可以通過AIDL來輔助進行綁定,從而實現Activity跨進程操作Service也就是本文的目標。
開發
1.先把Service放到另一個進程中:
<service android:name=".MyService1"
android:process=":message"
>
</service>
好如果我們用普通的綁定方法,來綁定這個Service是可以成功綁定並啓動的,但是
@Override
public void onServiceConnected(ComponentName arg0, IBinder service)
中的Service並不能強制轉換成Service中的binder程序會報錯,所以我們必須藉助AIDL
2.創建一個AIDL文件並寫隨意兩個方法
// IMyAidlService.aidl
package com.air.service;
// Declare any non-default types here with import statements
interface IMyAidlService {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void play(int i);
int add(int i);
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
寫完之後rebulid一下項目,Android Studio 會幫我們自動生成相關的Java文件。
3.在Service中引用並實現相關方法。
private MyBinder mBinder = new MyBinder();
class MyBinder extends IMyAidlService.Stub {
@Override
public void play(int i) throws RemoteException {
}
@Override
public int add(int i) throws RemoteException {
return ++i;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
4.在Activity中綁定:
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
Log.d("MyService123", "Service Connection Success");
mMyBinder = IMyAidlService.Stub.asInterface(service);
try {
Log.d("MyService123", "" + mMyBinder.add(10));
} catch (RemoteException e) {
e.printStackTrace();
}
//同一進程的獲取方法
//mMyBinder = (MyService1.MyBinder) service;
}
5.提供停止,解綁,開啓,綁定四個方法
public void stop(View v) {
Intent stopIntent = new Intent(this, MyService1.class);
stopService(stopIntent);
}
//解綁
public void stop2(View v) {
unbindService(myServiceConnection);
}
public void start(View v) {
Intent startIntent = new Intent(this, MyService1.class);
startService(startIntent
}
public void bind(View v) {
Intent intent = new Intent(this, MyService1.class);
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
}
6.我們自定一個Application來看它的創建情況
public class A extends Application {
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService123","create");
}
}
測試
好我們點擊綁定按鈕:
主進程輸出日誌:
06-27 15:26:33.367 26110-26110/com.air.service D/MyService123: create
06-27 15:26:35.458 26110-26110/com.air.service D/MyService123: Service Connection Success
06-27 15:26:35.460 26110-26110/com.air.service D/MyService123: 11
message進程輸出日誌:
06-27 15:35:53.947 32013-32013/com.air.service:message D/MyService123: create
06-27 15:35:53.949 32013-32013/com.air.service:message D/MyService123: onCreate() executed
可見我們成功使用了Service的add方法,得出數值11,Application也被兩個進程分別創建了一次。
我們點擊解除綁定按鈕:
06-27 15:37:25.885 32013-32013/com.air.service:message D/MyService123: onDestroy() executed
Service成功被銷燬。
如果我們先startService再綁定,再解綁會怎樣?
我們會發現Service沒有被銷燬,如果再點擊stop來停止Service,
06-27 15:39:39.156 32013-32013/com.air.service:message D/MyService123: onDestroy() executed
Service被成功銷燬。
如果我們先startService再綁定,再停止Service會怎樣?
其實是一樣的Service沒有被銷燬,如果再點擊stopService成功銷燬。
總結
1.如果Service跨進程我們可以輕鬆的調起Service
2.如果Service跨進程我們可以綁定但不能通過原來的方法獲取Binder實例
3.通過AIDL可以解決獲取Binder實例的問題
4.如果Service即被綁定,又被開啓,解綁和停止必須都執行才能正確的殺死Service。
5.Service放在獨立進程中Application會被重複創建
本文代碼鏈接:
https://github.com/AndroidMsky/AIDLBindService
哪裏可以找到我:
我的Github: https://github.com/AndroidMsky
我的博客主頁: http://blog.csdn.net/androidmsky
歡迎加作者自營安卓開發交流羣: 308372687