日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > ChatGpt >内容正文

ChatGpt

AIDL 客户端与服务端的双向通信

發布時間:2025/4/16 ChatGpt 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AIDL 客户端与服务端的双向通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

時隔一年半了,終于寫下了這個續篇,我發現我的很多博客有頭無尾,都是有前面一點點,后面就沒寫去了,也正在想辦法都補上

  • 初涉IPC,了解AIDL的工作原理及使用方法

今天聊聊的是客戶端和服務端的相互通信,何謂雙向通信,事實上,我們在上一篇的博客中,只是講解了客戶端請求服務端的方法,然后服務端返回一個值給我們這樣,其實是最簡單的用法,但是常常在我們的開發過程中,如果調用了某些方法,比如網絡請求,那么就需要等待請求有結果了之后再回調給我們,這個回調的過程就是服務端向客戶端通信,作為ipc通信的一種,如果你不會雙向通信,那么你可以比較low的用廣播,但是我還是建議你直接用一整套的AIDL復用,好的,那么問題來了,我們怎么下手呢?

服務端

我們新建兩個工程,一個叫ADILClient,一個叫AIDLService,分別代表的是客戶端和服務端

我們現在開始編寫我們的aidl,這里我需要編寫兩個AIDL文件,一個是我們對外的方法,一個是我們對外的回調方法,如圖

這里我做一下講解,首先我new了一個aidl的文件夾,在main下,和java同級,然后定義了一個公共的包名:com.android.openimpl,最后在里面實現了兩個aidl文件,我們來看下具體的文件內容

IMyLifeStyleInterface

// IMyLifeStyleInterface.aidl package com.android.openimpl;import com.android.openimpl.IMyLifeStyleListener;interface IMyLifeStyleInterface {//計算void sum(int a ,int b);//睡覺void sleep(boolean isSleep);//注冊void registerCallback(IMyLifeStyleListener il);//解綁void unregisterCallback(IMyLifeStyleListener il);}

IMyLifeStyleListener

// IMyLifeStyleListener.aidl package com.android.openimpl;//回調接口 interface IMyLifeStyleListener {//回調方法void OnCallBackSleep(String text);void OnCallBackSize(int size); }

這里我定義了IMyLifeStyleInterface ,里面有兩個方法,假設我定義的事一個人,他有基本的兩個本能,一個是計算,我傳兩個數字給他,他進行一系列的處理,那么,問題來, 我不想用返回值,我想通過回調知道,這是一點,另一個是睡覺,而在IMyLifeStyleListener,我也定義了兩個對應的回調OnCallBackSleep和OnCallBackSize,好了,現在開始來實現我們的遠程Service服務

public class OpenImplService extends Service {private IMyLifeStyleListener lifeStyleListener;private IBinder mBinder = new IMyLifeStyleInterface.Stub() {@Overridepublic void sum(int a, int b) throws RemoteException {//經過一系列的計算后將值告知客戶端int c = a * 2 + b;if (lifeStyleListener != null) {lifeStyleListener.OnCallBackSize(c);}}@Overridepublic void sleep(boolean isSleep) throws RemoteException {//告訴客戶端我已經睡著if(isSleep){if (lifeStyleListener != null) {lifeStyleListener.OnCallBackSleep("幫我關下燈,謝謝!");}}}@Overridepublic void registerCallback(IMyLifeStyleListener il) throws RemoteException {if (il != null) {lifeStyleListener = il;}}@Overridepublic void unregisterCallback(IMyLifeStyleListener il) throws RemoteException {if (il != null) {lifeStyleListener = null;}}};@Overridepublic IBinder onBind(Intent intent) {return mBinder;} }

這里,我定義了一個遠程的服務OpenImplService,里面我只是new了IMyLifeStyleInterface.Stub并且把Binder對象給了onBind方法,而在Binder內部,我做的操作相信大家都看的明白吧,很簡單,Ok,那我們的服務端就已經搞定了,我們來看下服務端的整體結構

當然,別忘了在清單文件中注冊

<service android:name=".service.OpenImplService"android:enabled="true"android:exported="true" />

客戶端

好的,現在就開始來實現我們的客戶端,客戶端也需要同樣的AIDL文件,所以我可以直接復制過去,但是要注意的是包名一定要相同,如圖

這里,我的客戶端就是app包下的東西,那么我們來實現UI上的邏輯

<?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"android:padding="10dp"><EditText android:id="@+id/et_numer_1"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="請輸入a" /><EditText android:id="@+id/et_numer_2"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="請輸入b" /><Button android:id="@+id/btn_sum"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="計算"android:textAllCaps="false" /><Button android:id="@+id/btn_sleep"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="睡覺"android:textAllCaps="false" /></LinearLayout>

這里,我定義了兩個輸入框和有個按鈕,對應的計算和睡覺,好的,我們run一下

我們來開始實現具體的邏輯了,這也是我們客戶端經常要干的事情首先,我們initService來初始化了服務,在android5.0之后綁定遠程服務都需要完整的包名了,如下

private void initService() {Intent i = new Intent();//Android 5.0 之后需要直接定義包名i.setComponent(new ComponentName("com.liuguilin.aidlservice", "com.liuguilin.aidlservice.service.OpenImplService"));bindService(i, mConnection, Context.BIND_AUTO_CREATE);}

這里需要傳一個mConnection,這是一個對應的關系,如果現在bind,你銷毀的時候需要unBind

@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConnection);}

好的,我們具體來看下mConnection的內容吧

private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Log.i(TAG, "onServiceConnected");//獲取AIDL對象iMyLifeStyleInterface = IMyLifeStyleInterface.Stub.asInterface(iBinder);//注冊接口try {iMyLifeStyleInterface.registerCallback(new OpenImpleListener());} catch (RemoteException e) {e.printStackTrace();}isBind = true;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.i(TAG, "onServiceDisconnected");try {iMyLifeStyleInterface.unregisterCallback(new OpenImpleListener());} catch (RemoteException e) {e.printStackTrace();}iMyLifeStyleInterface = null;isBind = false;}};

他一共會重寫兩個方法,服務綁定onServiceConnected和服務解綁onServiceDisconnected,所以這里我們用了一個標志位isBind來標記綁定狀態,然后通過AIDL的asInterface方法來實例化對應的AIDL對象,然后就是注冊這個接口回調了

class OpenImpleListener extends IMyLifeStyleListener.Stub {@Overridepublic void OnCallBackSleep(String text) throws RemoteException {Toast.makeText(MainActivity.this, "text:" + text, Toast.LENGTH_SHORT).show();}@Overridepublic void OnCallBackSize(int size) throws RemoteException {Toast.makeText(MainActivity.this, "size:" + size, Toast.LENGTH_SHORT).show();}}

這里要注意的事需要繼承的是AIDL的Stub,最后就是我們的點擊事件了

@Overridepublic void onClick(View v) {if (isBind) {switch (v.getId()) {case R.id.btn_sum:String a = et_numer_1.getText().toString().trim();String b = et_numer_2.getText().toString().trim();try {iMyLifeStyleInterface.sum(Integer.parseInt(a),Integer.parseInt(b));} catch (RemoteException e) {e.printStackTrace();}break;case R.id.btn_sleep:try {iMyLifeStyleInterface.sleep(true);} catch (RemoteException e) {e.printStackTrace();}break;}} else {Toast.makeText(this, "服務未連接", Toast.LENGTH_SHORT).show();}}

這里算是比較簡單的了,傳值調用即可,好的,下面貼上全部的代碼

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "AIDL";private EditText et_numer_1;private EditText et_numer_2;private Button btn_sum;private Button btn_sleep;//綁定狀態private static boolean isBind = false;private IMyLifeStyleInterface iMyLifeStyleInterface;private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Log.i(TAG, "onServiceConnected");//獲取AIDL對象iMyLifeStyleInterface = IMyLifeStyleInterface.Stub.asInterface(iBinder);//注冊接口try {iMyLifeStyleInterface.registerCallback(new OpenImpleListener());} catch (RemoteException e) {e.printStackTrace();}isBind = true;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.i(TAG, "onServiceDisconnected");try {iMyLifeStyleInterface.unregisterCallback(new OpenImpleListener());} catch (RemoteException e) {e.printStackTrace();}iMyLifeStyleInterface = null;isBind = false;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initService();initView();}private void initService() {Intent i = new Intent();//Android 5.0 之后需要直接定義包名i.setComponent(new ComponentName("com.liuguilin.aidlservice", "com.liuguilin.aidlservice.service.OpenImplService"));bindService(i, mConnection, Context.BIND_AUTO_CREATE);}private void initView() {et_numer_1 = (EditText) findViewById(R.id.et_numer_1);et_numer_2 = (EditText) findViewById(R.id.et_numer_2);btn_sum = (Button) findViewById(R.id.btn_sum);btn_sleep = (Button) findViewById(R.id.btn_sleep);btn_sum.setOnClickListener(this);btn_sleep.setOnClickListener(this);}@Overridepublic void onClick(View v) {if (isBind) {switch (v.getId()) {case R.id.btn_sum:String a = et_numer_1.getText().toString().trim();String b = et_numer_2.getText().toString().trim();try {iMyLifeStyleInterface.sum(Integer.parseInt(a),Integer.parseInt(b));} catch (RemoteException e) {e.printStackTrace();}break;case R.id.btn_sleep:try {iMyLifeStyleInterface.sleep(true);} catch (RemoteException e) {e.printStackTrace();}break;}} else {Toast.makeText(this, "服務未連接", Toast.LENGTH_SHORT).show();}}class OpenImpleListener extends IMyLifeStyleListener.Stub {@Overridepublic void OnCallBackSleep(String text) throws RemoteException {Toast.makeText(MainActivity.this, "text:" + text, Toast.LENGTH_SHORT).show();}@Overridepublic void OnCallBackSize(int size) throws RemoteException {Toast.makeText(MainActivity.this, "size:" + size, Toast.LENGTH_SHORT).show();}}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConnection);} }

可以發現,代碼很是簡潔,希望大家能夠學會,最后我們運行一遍

這里可以看到,點擊睡覺,服務端會叫我們關下燈,而計算的話,我傳的是2和3,服務端計算了一下 2 * 2 + 3 = 7 并且返回回來了。

Demo下載:點擊下載

我的公眾號,期待你的關注

總結

以上是生活随笔為你收集整理的AIDL 客户端与服务端的双向通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。