遠程Servicejava
在清單文件中給Service添加屬性process 爲:remoteandroid
<service android:name="com.example.servicetest.MyService" android:process=":remote" > </service>
使用遠程Service,MyService將在另外一個進程中運行,只會阻塞所在進程中的主線程,不會當前應用程序。ide
遠程Service會在應用包名加上:remote;spa
遠程Service的弊端:線程
開啓多進程時 Application會運行兩次 (初始化數據時不穩當 : 須要判斷進程名與當前應用的的進程名)
code
使用bind方式與Activity創建鏈接時 程序會崩潰。
對象
由於Service與Activity 運行在兩個不一樣的進程中 ,不能使用傳統的創建鏈接方式,須要引入AIDL;blog
Activity與遠程Service 創建關聯, 使用AIDL 進行跨進程通訊(IPC)接口
AIDL(Android Interface Definition Languge) android接口定義語言 進程
AIDL的做用: 用於Service與多個應用程序組件之間進行跨進程通訊 ,實現多個應用程序共享一個Service的功能
使用跨進程通訊的步驟
1. 首先新建一個AIDL文件 進行文件MyAIDLService.aidl文件
package com.example.service.remote; interface MyAIDLService { int plus(int a, int b); String toUpperCase(String str); }
//保存後,gen目錄下會生產一個對應的java文件 ;
//編寫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,不能爲其它標記。
二、而後修改MyService中的代碼 實現剛定義好的MyAIDLService接口 而且在onBInd中返回對象
@Override public IBinder onBind(Intent intent) { return mBinder; } MyAIDLService.Stub mBinder = new Stub() { @Override public String toUpperCase(String str) throws RemoteException { if (str != null) { return str.toUpperCase(); } return null; } @Override public int plus(int a, int b) throws RemoteException { return a + b; } };
// Stub是Binderd的子類
三、在MainActivity中寫實現代碼
private MyAIDLService myAIDLService;
//建立 ServiceConnection對象 並實現MyAIDLeService中的方法 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) {
// 獲取MyAIDLService對象 myAIDLService = MyAIDLService.Stub.asInterface(service); try { int result = myAIDLService.plus(3, 5); String upperStr = myAIDLService.toUpperCase("hello world"); Log.d("TAG", "result is " + result); Log.d("TAG", "upperStr is " + upperStr); } catch (RemoteException e) { e.printStackTrace(); } } };
4.在其餘應用程序中調用MyService的方法
4.一、在清單文件中給MyService 添加隱式Intent; 用於其餘應用程序調用
<service android:name="com.example.service.remote.MyService" android:process=":remote" > <intent-filter> <action android:name="com.example.service.remote.MyService.MyAIDLService"></action> </intent-filter> </service>
//MyService能夠響應這個action的Intent
4.2.而後在一個新的項目中,把MyAIDLService.aidl文件拷貝過來(要將原有的包路徑一塊兒拷貝過來)
4.3 而後在MainActivity中 加入MyService創建關聯的代碼
private MyAIDLService myAIDLService; //建立 ServiceConnection對象 並實現MyAIDLeService中的方法 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { // 獲取MyAIDLService對象 myAIDLService = MyAIDLService.Stub.asInterface(service); try { int result = myAIDLService.plus(3, 5); String upperStr = myAIDLService.toUpperCase("hello world"); Log.d("TAG", "result is " + result); Log.d("TAG", "upperStr is " + upperStr); } catch (RemoteException e) { e.printStackTrace(); } } };
4.4 bindService 經過隱式意圖
case R.id.btn_bind: Intent intent1 = new Intent("com.example.service.remote.MyService.MyAIDLService"); bindService(intent1, conn , BIND_AUTO_CREATE); break;
實現不一樣應用程序跨進程通訊功能。