快速入門android AIDL(開啟多程式並進行通訊)
為何要開啟多程式?主要有兩種情況:
一、一個應用由於自身需要採用多程式模式來實現。比如播放器之類,如果僅僅在service中執行會影響主執行緒的響應速度,很可能會造成ANR,一般情況下不會這麼寫;如果僅僅在子執行緒中執行,一旦開啟該執行緒的Activity被殺死後,執行緒也被殺死,無法實現後臺執行效果,更加不合理。而如果在另外一個程式中使用service後臺執行,就顯得十分恰當了。
二、由於android對單個應用所使用的最大記憶體做了限制,為了加大一個應用可使用的記憶體,所以通過多程式來獲取多份記憶體空間。
本篇文章demo重點:(demo原始碼在文章結尾)
1、開啟多程式
2、兩個程式之間使用AIDL進行通訊
開啟多程式:
在Android中常用的使用多程式只有一種辦法,那就是在AndroidManifest中為四大元件(Activity、Service、Broadcast Receiver、ContentProvier)指定android:process屬性。筆者demo中的遠端service如下圖:
最終繫結該service後在DDMS中程式的顯示情況如下圖:
可以看到最後的兩個程式都是同一個包名,只是第二個是“:remote”。這樣就非常簡單的開啟了多程式。
講到此處,很多好奇的讀者定然有疑問了,“android:process”中的引數到底代表了什麼?簡單來講就是代表了新開的這個程式的id。如果兩個應用要共享同一個程式就需要用到這個了。
那麼筆者此處寫的“:remote”又是什麼意思呢?“remote”不是關鍵,這個完全可以自己隨意取名字,“:”冒號才是關鍵。
程式名以“:”開頭的程式屬於當前應用的私有程式,其他應用的元件不可以和它跑在同一個程式中。而程式名不以“:”開頭的程式屬於全域性程式,其他應用可以通過某些方式和它跑在同一個程式中。
兩個程式之間使用AIDL進行通訊:
筆者此篇文章實現的主要效果:
能夠在當前程式中MainActivity,執行另一個程式中開啟的Service中實現的方法testMethod(),方法與最終效果如下:
介面上主要有兩個按鈕,第一個是開啟遠端程式中的Service,另一個為執行該方法。
主要實現步驟:(主要有三條,分別為AIDL、Service、和呼叫處(demo中為MainActivity))
1、建立一個AIDL介面,並寫入自己要在程式間通訊用的抽象方法。
myAIDL.aidl:
package com.example.double2.myaidltest;
interface myAIDL {
void testMethod();
}
建立AIDL檔案與建立java檔案等類似,直接右擊建立即可。android studio中就十分方便,會自動在main檔案下建立一個aidl資料夾,並在該資料夾建立於你專案名相同的包名。
可能遇到的小問題:
筆者第一次建立AIDL,在Service中發現找不到該AIDL的包。遇到相同問題的讀者可以在建立AIDL並寫完抽象方法之後使用build->make project重新構建一下專案。
2、建立一個遠端Service,在Service中建立一個類繼承AIDL介面中的Stub類並實現Stub中的抽象方法,最後不要忘記在onBind中返回這個類的物件。
public class AIDLRemoteService extends Service {
private static final String TAG = "AIDLRemoteService";
private final myAIDL.Stub mBinder=new myAIDL.Stub(){
@Override
public void testMethod() throws RemoteException {
Log.d(TAG, "testMethod: "+"this is myAIDLTest");
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
3、在要呼叫的地方(筆者demo中就為MainActivity中)繫結該Service,將Service返回的Binder物件轉換成AIDL介面所屬的型別,接著直接呼叫AIDL的方法。
在成功連線之後,將Service返回的Binder物件轉換成AIDL介面所屬的型別:
private myAIDL mMyAIDL;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected");
mMyAIDL = myAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected");
mMyAIDL = null;
}
};
在呼叫處直接使用:
btnStartMethod.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mMyAIDL.testMethod();
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "服務被異常殺死,請重新開啟。", Toast.LENGTH_SHORT).show();
}
}
});
demo專案結構:
myAIDL.aidl:
package com.example.double2.myaidltest;
interface myAIDL {
void testMethod();
}
package com.example.double2.myaidltest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
/**
* 專案名稱:MyAIDLTest
* 建立人:Double2號
* 建立時間:2016/6/10 8:13
* 修改備註:
*/
public class AIDLRemoteService extends Service {
private static final String TAG = "AIDLRemoteService";
private final myAIDL.Stub mBinder=new myAIDL.Stub(){
@Override
public void testMethod() throws RemoteException {
Log.d(TAG, "testMethod: "+"this is myAIDLTest");
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
package com.example.double2.myaidltest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Button btnBindService;
private Button btnStartMethod;
private myAIDL mMyAIDL;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected");
mMyAIDL = myAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected");
mMyAIDL = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
btnBindService = (Button) findViewById(R.id.btn_bind_service);
btnStartMethod = (Button) findViewById(R.id.btn_start_method);
btnBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AIDLRemoteService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
btnStartMethod.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mMyAIDL.testMethod();
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "服務被異常殺死,請重新開啟。", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:id="@+id/btn_bind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="bindService"/>
<Button
android:id="@+id/btn_start_method"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="startMethod"/>
</LinearLayout>
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.double2.myaidltest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".AIDLRemoteService"
android:process=":remote"/>
</application>
</manifest>
demo原始碼地址:http://download.csdn.net/detail/double2hao/9545551
相關文章
- Android程式間通訊之AIDLAndroidAI
- Android程式間通訊,AIDL工作原理AndroidAI
- Android 程式通訊機制之 AIDLAndroidAI
- Android 程式間通訊 AIDL詳解AndroidAI
- 從AIDL看Android跨程式通訊AIAndroid
- Android跨程式通訊之非AIDL(二)AndroidAI
- 從AIDL開始談Android程式間Binder通訊機制AIAndroid
- Webview獨立程式並通過AIDL實現資料通訊WebViewAI
- Android開啟多程式及程式間通訊的幾種方式Android
- Android探索之AIDL實現程式間通訊AndroidAI
- Android 多程式通訊Android
- electron開發入門(二)程式通訊
- [Android]你不知道的Android程式化(4)--程式通訊AIDL框架AndroidAI框架
- Android AIDL SERVICE 雙向通訊 詳解AndroidAI
- Android IPC程式間通訊之AIDL和Messenger的使用AndroidC程式AIMessenger
- Android中AIDL實現程式通訊(附原始碼下載)AndroidAI原始碼
- Android Studio 建立aidl檔案,用於程式間通訊AndroidAI
- vue3 快速入門系列 —— 元件通訊Vue元件
- 4-AIII–Service跨程式通訊:aidlAI
- Aidl程式間通訊詳細介紹AI
- 使用AIDL實現程式間的通訊AI
- Android 元件化之通訊(多模組,多程式)Android元件化
- Android入門教程 | Fragment (載入方法與通訊)AndroidFragment
- Android程式間通訊——多程式共用SharedPreferencesAndroid
- Java 高階 --- 多執行緒快速入門Java執行緒
- 定位模組LuatOS快速入門:源UART串列埠通訊串列埠
- 簡單設計並開發一個行動通訊程式
- Android入門教程 | 多執行緒Android執行緒
- 快速Android開發系列通訊篇之EventBusAndroid
- android AIDL程式間通訊(只介紹了簡單資料型別)AndroidAI資料型別
- android-IPC/Binder/D-BUS(Binder/Messager/AIDL)程式間通訊(訊息機制)AndroidAI
- 通過API開啟PDF檔案,並進行指定文字的搜尋API
- Android Socket連線,使用Socket進行通訊(Android)Android
- 阿里Android開發規範:程式、執行緒與訊息通訊阿里Android執行緒
- Android 活動(activity)和服務(service)進行通訊Android
- Android中使用HTTP和HttpClient進行通訊AndroidHTTPclient
- 序列通訊與並行通訊的區別並行
- 入門python多執行緒/多程式Python執行緒