1. 程式人生 > >AIDL介紹以及簡單使用

AIDL介紹以及簡單使用

send 時間 進程 系統 cast memory sco 不能 一起

目錄

  • 一. AIDL 介紹.
  • 二. AIDL簡單應用.
    • Aidl_Server端
    • Aidl_Client端
  • 三.註意事項

一. AIDL 介紹.

 AIDL(Android接口描述語言)是一個IDL語言,它可以生成一段代碼,可以是一個在Android設備上運行的兩個進程使用內部通信進程進行交互。

如果你想在一個進程中(例如在一個Activity中)訪問另一個進程中(例如service)某個對象的方法,你就可以使用AIDL來生成這樣的代碼來偽裝傳遞各種參數。

稍微了解下幾個常見的名詞(IPC,匿名共享內存,Binder,Aidl,消息,廣播,ContentProvider,Intent):
IPC是一種概念,即進程間通信;其它幾個都是Android裏的概念;


匿名共享內存(Anonymous Shared Memory):其作用之一即通過Binder進程間通信機制來實現進程間的內存共享。
Binder:Binder是對IPC的具體實行,是IPC的一種具體實現.其本質也是調用系統底層的共享內存實現.
AIDL:進程間的通信,速度快(系統底層直接是共享內存),性能穩,效率高,一般進程間通信就用它. AIDL是Binder機制向外提供的接口,目的就是為了方便對Binder的使用;
消息(Messager):Messenger本質也是AIDL,只是進行了封裝,開發的時候不用再寫.aidl文件,效率應該是和Aidl是一樣的,與Aidl的區別在於Messager是線程安全的,而Aidl是非線程安全的,所以Aidl在使用的時候應該註意這個問題;

廣播(BroadcastReceiver):只要註冊了廣播,都能收到,有點範圍廣,缺點速度慢必須在一定時間完成處理操作,同其他Android四大組件一樣,都不能執行耗時操作;
ContentProvider:暴露app的數據訪問接口,讓其他應該訪問app數據.同時也能通過ContentProvider來訪問第三方的一些app數據(如通訊錄,日歷等暴露接口的應用);
Intent:Intent是最高層級的封裝,實質是封裝了對Binder的使用,當然Intent也常常在同一進程中調用,只是把兩種方式封裝在一起了.
技術分享圖片

二. AIDL簡單應用.

編寫兩個app應用程序,一個實現Aidl傳遞的Server端,一個實現Aidl的Client端:
aidl的Server端,接收Client端傳過來的兩個int值,定義一個加法計算的邏輯規則, 並返回 兩個int數之和, return num1 + num2;
aidl的Client端,從界面用戶輸入兩個int數,點擊綁定Server端服務,點擊計算,調用Server端加法邏輯,將返回結果 輸入到用戶界面展示,兩數之和.

Aidl_Server端

技術分享圖片

// IImoocAIDL.aidl
 package com.example.administrator.aidl_server.service;

// Declare any non-default types here with import statements

interface IImoocAIDL {
     //計算num1 + num2
        int add(int num1,int num2);
}

編譯後會生成

public interface IImoocAIDL extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.example.administrator.aidl_server.service.IImoocAIDL {
            ...
            private static class Proxy implements com.example.administrator.aidl_server.service.IImoocAIDL {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public int add(int num1, int num2) throws android.os.RemoteException {
                ...
            }
            
            ...
        }
            ...
    }
}

技術分享圖片

//om.example.administrator.aidl_server.IRemoteService

public class IRemoteService extends Service {
    public static final String TAG = "IRemoteService";
    //客戶端綁定service時會執行
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new IImoocAIDL.Stub() {
        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.e(TAG,"收到了來自客戶端的請求" + num1 + "+" + num2 );
            return num1 + num2;
        }

    };
}

//AndroidManifest.xml

<application
    ...
        <service android:name=".IRemoteService"
            android:process=":remote"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.administrator.aidl_server"/>
            </intent-filter>
        </service>
    ...
</application>

Aidl_Client端

技術分享圖片

com.example.administrator.aidl_client.MainActivity
public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";
    private EditText et_send_input,nub_1,nub_2;
    private TextView tv_send;
    private TextView tv_bind;
    private IImoocAIDL iImoocAIDLService;

    private ServiceConnection conn = new ServiceConnection() {

        //綁定服務,回調onBind()方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iImoocAIDLService = IImoocAIDL.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iImoocAIDLService = null;
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bindService();

        et_send_input = findViewById(R.id.et_send_input);
        nub_1 = findViewById(R.id.nub_1);
        nub_2 = findViewById(R.id.nub_2);
        tv_send = findViewById(R.id.tv_send);
        tv_bind = findViewById(R.id.tv_bind);

        tv_send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    int nub1 = Integer.parseInt(nub_1.getText().toString().trim());
                    int nub2 = Integer.parseInt(nub_2.getText().toString().trim());

                    int result = iImoocAIDLService.add(nub1,nub2);
                    et_send_input.setText(result+"");
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        });

        tv_bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bindService();
                Log.e(TAG,"bindService"+iImoocAIDLService);
            }
        });
    }

    private void bindService() {
        Intent intent = new Intent();
        //綁定服務端的service
        intent.setAction("com.example.administrator.aidl_server.IRemoteService");
        //新版本(5.0後)必須顯式intent啟動 綁定服務
        intent.setComponent(new ComponentName("com.example.administrator.aidl_server","com.example.administrator.aidl_server.IRemoteService"));
        //綁定的時候服務端自動創建
        bindService(intent,conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}

layout/activity_main.xml

<?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">

    <LinearLayout
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/nub_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="+" />

        <EditText
            android:id="@+id/nub_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="=" />

        <EditText
            android:id="@+id/et_send_input"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number" />
    </LinearLayout>

    <TextView
        android:id="@+id/tv_bind"
        android:layout_width="200dp"
        android:layout_height="55dp"
        android:layout_gravity="center"
        android:layout_marginBottom="15dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="bind" />

    <TextView
        android:id="@+id/tv_send"
        android:layout_width="200dp"
        android:layout_height="55dp"
        android:layout_gravity="center"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="計算" />


</LinearLayout>

技術分享圖片

技術分享圖片

三.註意事項

如果運行中報錯:

aidl Method threw ‘java.lang.SecurityException‘ exception.

需要 確保客戶端的aidl文件包名要與服務端的包名一樣.也就是本項目中的IImoocAIDL.aidl文件包名一致.


[1] 參考資料: https://blog.csdn.net/jinxinliu1/article/details/70174591

AIDL介紹以及簡單使用