AIDL基礎體驗
- 基礎理論
- 運行效果
- 核心代碼
- 完整代碼
- 注意事項
第一章 基礎理論
第01節 原理圖

第02節 簡述說明
1. 什么是 AIDL?
AIDL 是 Android Interface Definition Language, 即Android介面定義語言,
2. AIDL有什么作用?
AIDL 可以實作跨行程的服務呼叫,
也就是 行程A當中,可以訪問到行程B當中 暴露出來的內容資訊,
3. 兩個行程介紹:
A. 對外暴露資料的是 服務端行程
B. 訪問暴露時間的是 客戶端行程
4. 行程互動程序說明:
A. 服務端行程, 定義統一的介面 AIDL, 再定義 Service 在定義的 Service 當中需要系結 binder 物件,
B. 服務端行程, 需要在清單檔案當中,指定 action
C. 客戶端行程, 定義統一的介面 AIDL, 再系結 Service 在系結的程序當中,指定 Intent 的action和package,
D. 客戶端行程, 需要在系結Service 之后, 再去采用 binder的代理物件去呼叫共享的 AIDL 方法
第二章 運行效果
第01節 效果圖

第02節 簡述說明
左圖說明
概述說明:
左圖是 Server 服務端行程的代碼實作, 主要是 服務端行程的操作,提供 AIDL
主要的操作步驟:
1、需要先定義 AIDL 檔案資訊
2、編譯AIDL檔案,在選單欄當中,找到 Build 選擇 Make Project 會產生 AIDL的介面檔案
3、介面檔案所在的位置: build/generated/aidl_source_output_dir/debug/out/...
4、需要定義 Service 其中在 onBind 方法當中回傳 iBuilder 的物件
5、需要在 Service 里面, 定義方法回傳 iBuilder 的物件,主要是通過 AIDL 回傳的結果
6、不要忘記了在服務端行程的清單檔案當中, 定義 Service 的 action 以便于客戶端行程進行遠程訪問
右圖說明
概述說明:
右圖是 Client 客戶端行程的代碼實作, 主要是客戶端行程的操作,訪問服務端的 AIDL
主要的操作步驟:
1、在客戶端行程當中, 需要定義 AIDL 檔案, 注意該檔案的包路徑, 必須和服務端的 AIDL 的包路徑完全相同
2、編譯AIDL檔案,在選單欄當中,找到 Build 選擇 Make Project 會產生 AIDL的介面檔案
3、在 MainActivity 當中初始化基礎控制元件和點擊事件等, findViewById 和 setOnClickListener 操作
4、在 MainActivity 當中系結服務端的操作 ServiceConnection 需要重寫兩個方法 系結和解綁
5、在 MainActivity 當中點擊系結服務按鈕的點擊事件當中, 需要系結服務, 采用意圖 Intent 設定 action 和 bindService 方法
6、在 MainActivity 當中的 onDestroy 方法當中, 需要解綁服務, 呼叫 unbindService 方法
第三章 核心代碼
第01節 服務端行程操作
步驟01:定義AIDL檔案
位置介紹

案例代碼
在 HelloAIDL.aidl 當中的寫法
// HelloAIDL.aidl
package hello.svip.server;
// Declare any non-default types here with import statements
interface HelloAIDL {
//計算 num1+num2
int add(int num1,int num2);
}
步驟02:編譯AIDL
位置介紹

案例代碼
以下代碼是自動生成的,主要存在于 build/generated/aidl_source_output_dir/debug/out
下面是部分代碼展示:
public interface HelloAIDL extends android.os.IInterface
{
/** Default implementation for HelloAIDL. */
public static class Default implements hello.svip.server.HelloAIDL
{
//計算 num1+num2
@Override public int add(int num1, int num2) throws android.os.RemoteException
{
return 0;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements hello.svip.server.HelloAIDL
{
private static final java.lang.String DESCRIPTOR = "hello.svip.server.HelloAIDL";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
//備注:后面代碼省略,這部分內容是自動生成的代碼
步驟03:創建Service
位置介紹
在 java 代碼當中,創建一個 HelloService 的代碼實作
案例代碼
Java 代碼的寫法
package hello.svip.server;
//定義服務 Service
public class HelloService extends Service {
public static final String TAG = "chc";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
清單檔案當中,指定 Service 這里的 action 可以隨意指定,提供給客戶端行程進行訪問得到,
<!-- 系結服務 -->
<service
android:name=".HelloService">
<intent-filter>
<action android:name="this.is.server.action.for.adil" />
</intent-filter>
</service>
步驟04:修改Service
在 service 里面定義一個 獲取到 iBinder 物件的匿名內部類
/***
* 在 AndroidStudio 當中.采用的是 Builder --> Make Project
*
* 等待編譯完畢之后,會產生一個 HelloAIDL的介面檔案.
*
* 產生的檔案具體在: build/generated/aidl_source_output_dir/debug/out/...
*/
private IBinder iBinder = new HelloAIDL.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.i(TAG, "add: 收到來自于客戶端的請求:" + num1 + "+" + num2);
//具體的操作,實作兩者相加的程序,
return num1 + num2;
}
};
修改 onBind 方法的回傳值,回傳的是 iBinder 的物件
@Nullable
@Override
public IBinder onBind(Intent intent) {
//回傳的是下面產生的AIDL的實作類物件
return iBinder;
}
第02節 客戶端行程操作
步驟01:定義AIDL檔案
位置介紹

案例代碼
在 HelloAIDL.aidl 當中的寫法
// HelloAIDL.aidl
package hello.svip.server;
// Declare any non-default types here with import statements
interface HelloAIDL {
//計算 num1+num2
int add(int num1,int num2);
}
步驟02:編譯AIDL
位置介紹

案例代碼
以下代碼是自動生成的,主要存在于 build/generated/aidl_source_output_dir/debug/out
下面是部分代碼展示:
public interface HelloAIDL extends android.os.IInterface
{
/** Default implementation for HelloAIDL. */
public static class Default implements hello.svip.server.HelloAIDL
{
//計算 num1+num2
@Override public int add(int num1, int num2) throws android.os.RemoteException
{
return 0;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements hello.svip.server.HelloAIDL
{
private static final java.lang.String DESCRIPTOR = "hello.svip.server.HelloAIDL";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
//備注:后面代碼省略,這部分內容是自動生成的代碼
步驟03:創建Activity
位置介紹
在 java 代碼當中,設定布局檔案,輸入框等按鈕點擊事件等,

準備 Java 代碼的資訊
package hello.svip.client;
public class MainActivity extends AppCompatActivity {
private EditText etNum01, etNum02;
private Button btn_bind, btn_call;
private TextView tvShow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.etNum01 = this.findViewById(R.id.et_num01);
this.etNum02 = this.findViewById(R.id.et_num02);
this.btn_bind = this.findViewById(R.id.btn_bind);
this.btn_call = this.findViewById(R.id.btn_call);
this.tvShow = this.findViewById(R.id.tv_show);
//系結服務
this.btn_bind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
//點擊訪問
this.btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點擊訪問", Toast.LENGTH_LONG).show();
}
});
}
}
第04節:修改Activity
定義 AIDL的系結匿名內部類
//定義AIDL
private HelloAIDL aidl;
//客戶端的服務系結
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//系結服務
aidl = HelloAIDL.Stub.asInterface(service);
Log.i(TAG, "onServiceConnected: --aidl->" + aidl);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//解綁服務,設定為null
aidl = null;
}
};
定義系結服務操作方法
/***
* 系結服務
*/
public void bindService() {
Intent intent = new Intent();
//系結服務
intent.setPackage("hello.svip.server");
intent.setAction("this.is.server.action.for.adil");
//系結的時候服務自動創建
bindService(intent, conn, BIND_AUTO_CREATE);
}
定義銷毀服務的方法,重寫 Activity 的 onDestroy
@Override
protected void onDestroy() {
super.onDestroy();
//解綁服務
if (conn != null) {
unbindService(conn);
}
}
修改按鈕的點擊事件處理方式
//系結服務
this.btn_bind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService();
Toast.makeText(MainActivity.this, "系結服務 aidl ---> " + aidl, Toast.LENGTH_LONG).show();
}
});
//點擊訪問
this.btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點擊訪問", Toast.LENGTH_LONG).show();
try {
int num1 = Integer.parseInt(etNum01.getText().toString().trim());
int num2 = Integer.parseInt(etNum02.getText().toString().trim());
//執行遠程的加法操作
int result = aidl.add(num1, num2);
//執行結果
tvShow.setText("最終結果:" + result);
//日志展示結果
Log.i(TAG, "onClick: 最終結果是:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
});
第四章 完整代碼
第01節 AIDL檔案
// HelloAIDL.aidl
package hello.svip.server;
// Declare any non-default types here with import statements
interface HelloAIDL {
//計算 num1+num2
int add(int num1,int num2);
}
第02節 服務清單檔案
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="hello.svip.server">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyDemo">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 系結服務 -->
<service
android:name=".HelloService">
<intent-filter>
<action android:name="this.is.server.action.for.adil" />
</intent-filter>
</service>
</application>
</manifest>
第03節 服務端Service
package hello.svip.server;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.Nullable;
//定義服務 Service
public class HelloService extends Service {
public static final String TAG = "chc";
@Nullable
@Override
public IBinder onBind(Intent intent) {
//回傳的是下面產生的AIDL的實作類物件
return iBinder;
}
/***
* 在 AndroidStudio 當中.采用的是 Builder --> Make Project
*
* 等待編譯完畢之后,會產生一個 HelloAIDL的介面檔案.
*
* 產生的檔案具體在: build/generated/aidl_source_output_dir/debug/out/...
*/
private IBinder iBinder = new HelloAIDL.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.i(TAG, "add: 收到來自于客戶端的請求:" + num1 + "+" + num2);
//具體的操作,實作兩者相加的程序,
return num1 + num2;
}
};
}
第04節 客戶端Activity
package hello.svip.client;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import hello.svip.server.HelloAIDL;
public class MainActivity extends AppCompatActivity {
private EditText etNum01, etNum02;
private Button btn_bind, btn_call;
private TextView tvShow;
private static final String TAG = "chc";
//定義AIDL
private HelloAIDL aidl;
//客戶端的服務系結
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//系結服務
aidl = HelloAIDL.Stub.asInterface(service);
Log.i(TAG, "onServiceConnected: --aidl->" + aidl);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//解綁服務,設定為null
aidl = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.etNum01 = this.findViewById(R.id.et_num01);
this.etNum02 = this.findViewById(R.id.et_num02);
this.btn_bind = this.findViewById(R.id.btn_bind);
this.btn_call = this.findViewById(R.id.btn_call);
this.tvShow = this.findViewById(R.id.tv_show);
//系結服務
this.btn_bind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService();
Toast.makeText(MainActivity.this, "系結服務 aidl ---> " + aidl, Toast.LENGTH_LONG).show();
}
});
//點擊訪問
this.btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點擊訪問", Toast.LENGTH_LONG).show();
try {
int num1 = Integer.parseInt(etNum01.getText().toString().trim());
int num2 = Integer.parseInt(etNum02.getText().toString().trim());
//執行遠程的加法操作
int result = aidl.add(num1, num2);
//執行結果
tvShow.setText("最終結果:" + result);
//日志展示結果
Log.i(TAG, "onClick: 最終結果是:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/***
* 系結服務
*/
public void bindService() {
Intent intent = new Intent();
//系結服務
intent.setPackage("hello.svip.server");
intent.setAction("this.is.server.action.for.adil");
//系結的時候服務自動創建
bindService(intent, conn, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
//解綁服務
if (conn != null) {
unbindService(conn);
}
}
}
第五章 注意事項
第01節 包名稱相同
1、說明
服務端行程的 AIDL 所在的包名稱是 hello.svip.server
客戶端行程的 AIDL 所在的包名稱是 hello.svip.server
兩者的 AIDL 所在的包名稱是相同的
2、截圖

第02節 編譯版本問題
1、說明
我們采用的是編譯版本是 Android 29
如果采用的是 Android 31 會導致 binder 物件為 null 出現 NullPointerException 空指標例外的情況,
2、截圖

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/356131.html
標籤:其他
上一篇:Android 以雙擊亮屏為例,上層控制驅動節點的流程
下一篇:java版仿拼多多Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入駐商城 直播帶貨商城 電子商務 拼團商城原始碼
