candroid通信
⑴ Android之Binder通信篇
Binder跨進程通信的本質是依賴內核驅動將屬於不同Binder進程的數據,從原始進程復制到目標進程,這樣就完成了跨進程通信了。
Binder通過獨特的內存映射機制,在跨進程通信時,可以做到一次拷貝,兩個空間同時使用!如下圖:
Binder跨進程通信是要傳遞數據的,既然有數據必然要佔用內存空間,Android系統規定每一個進程都有一塊Binder內存區,也就是圖1中的 共享內存 ,系統最多隻能給該區域分配4M的物理內存,由於申請這塊內存是通過系統的mmap函數完成的,所以整個映射機制又被稱為mmap機制
為了把這部分說明白,就再盜圖一張,命名圖2吧!
對於Binder驅動,通過 binder_procs 鏈表記錄所有創建的 binder_proc 結構體,binder 驅動層的每一個 binder_proc 結構體都與用戶空間的一個用於 binder 通信的進程一一對應,且每個進程有且只有一個 ProcessState 對象,這是通過單例模式來保證的。在每個進程中可以有很多個線程,每個線程對應一個 IPCThreadState 對象,IPCThreadState 對象也是單例模式,即一個線程對應一個 IPCThreadState 對象,在 Binder 驅動層也有與之相對應的結構,那就是 Binder_thread 結構體。在 binder_proc 結構體中通過成員變數 rb_root threads,來記錄當前進程內所有的 binder_thread。
Binder 線程池:每個 Server 進程在啟動時創建一個 binder 線程池,並向其中注冊一個 Binder 線程;之後 Server 進程也可以向 binder 線程池注冊新的線程,或者 Binder 驅動在探測到沒有空閑 binder 線程時主動向 Server 進程注冊新的的 binder 線程。對於一個 Server 進程有一個最大 Binder 線程數限制,默認為16個 binder 線程,例如 Android 的 system_server 進程就存在16個線程。對於所有 Client 端進程的 binder 請求都是交由 Server 端進程的 binder 線程來處理的。
⑵ Android:AIDL進程間通信基本框架
在某些業務場景下,我們需要在應用中單獨開啟一個進程進行一些操作。比如性能監控,如果讓原始業務和性能監控本身的業務跑在同一個進程下,那麼就會導致性能統計的數據的失真。
而進程間通信,一般採用AIDL機制的客戶端與服務端通信。
AIDL只能傳遞如下幾類數據:
當傳遞自定義 Parcelable 時,有三處地方需要注意:
當傳遞其他 aidl 介面時,同樣必須要 import 這個 aidl 文件
編寫完 aidl 文件後,make一下工程,會在 build 下的 generated 下的 source 下的 aidl 目錄生成對應的介面類文件。aidl 介面其實就是 API 介面,通過實現對應介面類的 Stub 子類來實現具體的 API 邏輯;通過對應介面類的 Stub 子類的 asInterface 方法得到具體的實現類,調用具體的 API 方法。
一個基本的客戶端服務端的通信結構一般包括如下功能
客戶端的功能
服務端的功能
客戶端的相關功能實現比較簡單,麻煩的是服務端的功能。因為 AIDL 介面定義的都是服務端的介面,是由客戶端來調用的。而想要實現服務端反向調用客戶端則需要通過其他手段實現。
想要實現服務端主動連接客戶端,最好的辦法就是 服務端發送廣播,客戶端收到廣播後再主動連接服務端 ,通過這種方式變相地實現服務端主動連接客戶端的功能
想要實現服務端主動斷開客戶端,除了上面 發送廣播是一種實現方式外,還可以通過 android 的系統API RemoteCallbackList,用包名作為key值來注冊遠程回調介面的方式,讓服務端持有客戶端的回調介面,服務端調用回調介面,客戶端在回調介面中實現主動斷開服務端 ,通過這種方式變數地實現服務端主動斷開客戶端的功能。而採用後者會顯得更加優雅
既然所有的操作歸根結底都是由客戶端來完成的,那麼客戶端必須得有如下的功能模塊:
服務端必須得有的功能模塊:
那麼,整體的通信流程就是如下的步驟:
首先是通信的 aidl 介面定義
然後是客戶端的連接操作與斷開連接操作,包括廣播接收者的注冊以及回調介面的實現
然後是客戶端的拉取數據和推送數據操作
接著是服務端的 iBinder 介面的實現,完成回調介面的注冊、業務子線程的開啟和關閉、數據的推送和數據的拉取操作
然後是服務端的主動連接和主動斷開連接操作
最後是服務端的 onUnbind 方法的實現,對回調介面進行反注冊
服務端模仿 FloatViewPlugin 自定義插件,實現 IServicePlugin 介面,定製個性化的懸浮窗插件
客戶端在 Appliaction 的 onCreate方法中初始化
在 MainActivity 上實現連接、斷開、數據通信
⑶ Android-Handle(線程間通信)詳解
線程間通信是在Android開發中比較經常遇到的,我們刷新UI界面一般是通過子線程做完某些事情後,要改變主頁面就要通過數據的通信,讓主線程接收到信息後自己改變UI界面。
1. Handle 先進先出原則;
2. Looper 類用來管理特定線程內對象之間的消息交換(MessageExchange);
3. Message 類用來保存數據。
1.Looper: 一個線程可以產生一個Looper對象,由它來管理此線程里的MessageQueue(消息隊列);
2.Handler: 你可以構造Handler對象來與Looper溝通,以便push新消息到MessageQueue里;或者接收Looper從Message Queue取出)所送來的消息;
android.os.Message的主要功能是進行消息的封裝,同時可以指定消息的操作形式,Message類定義的變數和常用方法如下:
在整個消息處理機制中,message又叫task,封裝了任務攜帶的信息和處理該任務的handler。message的用法比較簡單,但是有這么幾點需要注意:
在使用Handler處理Message時,需要Looper(通道)來完成。在一個Activity中,系統會自動幫用戶啟動Looper對象,而在一個用戶自定義的類中,則需要用戶手工調用Looper類中的方法,然後才可以正常啟動Looper對象。Looper的字面意思是「循環者」,它被設計用來使一個普通線程變成Looper線程。所謂Looper線程就是循環工作的線程。在程序開發中(尤其是GUI開發中),我們經常會需要一個線程不斷循環,一旦有新任務則執行,執行完繼續等待下一個任務,這就是Looper線程。使用Looper類創建Looper線程很簡單:
這是在子線程中創建Handler的情況,如果在主線程中創建Handler是不需要調用 Looper.prepare(); 和 Looper.loop(); 方法。
Handler是更新UI界面的機制,也是消息處理的機制。我們可以通過Handle發送消息,也可以處理消息。
Android在設計的時候,封裝了一套消息創建、傳遞、處理機制,如果不遵循這樣的機制就沒有辦法更新UI信息,就會拋出異常。
創建Handler實例化對象時,可以重寫的回調方法:
⑷ Android進程間通信
1. 簡要說說進程與線程的區別和聯系。
2. 應用內使用多進程可能導致哪些問題?
當一個APP啟用了多進程後,系統會為不同的進程分配不同的內存空間,因此所有需要通過內存共享的行為都會失敗。另外,還會導致以下幾個問題:
3. Android中有哪些進程間通信方式?
由於不同的進程擁有不同的數據空間,所以無論是應用內還是應用間,均無法通過共享內存來實現進程間通信。
進程和線程的主要區別(總結) - CSDN
線程和進程的區別是什麼? - 知乎
Android 多進程通信之幾個基本問題
面試題:IPC(跨進程通信)
⑸ Flutter與Android通信的三種方式
一、 MethodChannel
主要是flutter端調用android方法。flutter調取android方法,也可以android主動跟flutter通信,但是這個只能是傳遞數據,不是調方法。MethodChannel的flutter調取android方法,我之前寫過,可以查看如下鏈接, https://www.jianshu.com/p/6b677ff3350e
Android主動跟flutter通信,如下
二、 BasicMessageChannel
它是可以雙端通信的,flutter端可以給Android發送消息,Android也可以給Flutter發送消息。
三、EventChannel
只能是原生發送消息給Flutter端,例如監聽手機電量變化,網路變化,感測器等。
列印結果如下:
總結一下:
MethodChannel 用於傳遞方法調用(method invocation),是flutter調取原生方法的,也可以原生主動傳遞數據給Flutter。
BasicMessageChannel 用於傳遞字元串和半結構化的信息。是兩個端相互發送數據,接收數據的。
EventChannel 用於數據流(event streams)的通信。通長用於Nativie向flutter的通信,如:手機電量變化,網路連接變化,陀螺儀,感測器等;
tip:多種類型的通道混用可能會出現報錯問題。
⑹ Android進程間和線程間通信方式
進程:是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
線程:是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一些在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
區別:
(1)、一個程序至少有一個進程,一個進程至少有一個線程;
(2)、線程的劃分尺度小於進程,使得多線程程序的並發性高;
(3)、進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉。
---------------------
一、Android進程間通信方式
1.Bundle
由於Activity,Service,Receiver都是可以通過Intent來攜帶Bundle傳輸數據的,所以我們可以在一個進程中通過Intent將攜帶數據的Bundle發送到另一個進程的組件。
缺點:無法傳輸Bundle不支持的數據類型。
2.ContentProvider
ContentProvider是Android四大組件之一,以表格的方式來儲存數據,提供給外界,即Content Provider可以跨進程訪問其他應用程序中的數據。用法是繼承ContentProvider,實現onCreate,query,update,insert,delete和getType方法,onCreate是負責創建時做一些初始化的工作,增刪查改的方法就是對數據的查詢和修改,getType是返回一個String,表示Uri請求的類型。注冊完後就可以使用ContentResolver去請求指定的Uri。
3.文件
兩個進程可以到同一個文件去交換數據,我們不僅可以保存文本文件,還可以將對象持久化到文件,從另一個文件恢復。要注意的是,當並發讀/寫時可能會出現並發的問題。
4.Broadcast
Broadcast可以向android系統中所有應用程序發送廣播,而需要跨進程通訊的應用程序可以監聽這些廣播。
5.AIDL方式
Service和Content Provider類似,也可以訪問其他應用程序中的數據,Content Provider返回的是Cursor對象,而Service返回的是java對象,這種可以跨進程通訊的服務叫AIDL服務。
AIDL通過定義服務端暴露的介面,以提供給客戶端來調用,AIDL使伺服器可以並行處理,而Messenger封裝了AIDL之後只能串列運行,所以Messenger一般用作消息傳遞。
6.Messenger
Messenger是基於AIDL實現的,服務端(被動方)提供一個Service來處理客戶端(主動方)連接,維護一個Handler來創建Messenger,在onBind時返回Messenger的binder。
雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串列的,也就是說,Handler接到多個message時,就要排隊依次處理。
7.Socket
Socket方法是通過網路來進行數據交換,注意的是要在子線程請求,不然會堵塞主線程。客戶端和服務端建立連接之後即可不斷傳輸數據,比較適合實時的數據傳輸
二、Android線程間通信方式
一般說線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:
1.AsyncTask機制
AsyncTask,非同步任務,也就是說在UI線程運行的時候,可以在後台的執行一些非同步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進行後台操作,並在不顯示使用工作線程或Handler機制的情況下,將結果反饋給UI線程。但是AsyncTask只能用於短時間的操作(最多幾秒就應該結束的操作),如果需要長時間運行在後台,就不適合使用AsyncTask了,只能去使用Java提供的其他API來實現。
2.Handler機制
Handler,繼承自Object類,用來發送和處理Message對象或Runnable對象;Handler在創建時會與當前所在的線程的Looper對象相關聯(如果當前線程的Looper為空或不存在,則會拋出異常,此時需要在線程中主動調用Looper.prepare()來創建一個Looper對象)。使用Handler的主要作用就是在後面的過程中發送和處理Message對象和讓其他的線程完成某一個動作(如在工作線程中通過Handler對象發送一個Message對象,讓UI線程進行UI的更新,然後UI線程就會在MessageQueue中得到這個Message對象(取出Message對象是由其相關聯的Looper對象完成的),並作出相應的響應)。
三、Android兩個子線程之間通信
面試的過程中,有些面試官可能會問Android子線程之間的通信方式,由於絕大部分程序員主要關注的是Android主線程和子線程之間的通信,所以這個問題很容易讓人懵逼。
主線程和子線程之間的通信可以通過主線程中的handler把子線程中的message發給主線程中的looper,或者,主線程中的handler通過post向looper中發送一個runnable。但looper默認存在於main線程中,子線程中沒有Looper,該怎麼辦呢?其實原理很簡單,把looper綁定到子線程中,並且創建一個handler。在另一個線程中通過這個handler發送消息,就可以實現子線程之間的通信了。
子線程創建handler的兩種方式:
方式一:給子線程創建Looper對象:
new Thread(new Runnable() {
public void run() {
Looper.prepare(); // 給這個Thread創建Looper對象,一個Thead只有一個Looper對象
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
Looper.loop(); // 不斷遍歷MessageQueue中是否有消息
};
}).start();
---------------------
方式二:獲取主線程的looper,或者說是UI線程的looper:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper()){ // 區別在這!!!
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();
---------------------
⑺ Android多進程通信之 Binder
在 Linux 中一個進程空間可以分為 用戶空間 和 內核空間 ,不同的進程它們的用戶空間數據不可共享,但是它們的內核空間的數據可共享,即所有進程共用 1 個內核空間。進程內用戶空間和內核空間進行交互需通過系統調用。
Android 系統時基於 Linux 內核的,Linux 已經提供了多種 IPC 方式,如下:
所以,Android 為啥又單獨弄出一個 Binder 呢?主要有如下原因:
直觀地說,Binder 是 Android 中的一個類,它實現了 IBinder 介面;從 Android Framework 角度來說,Binder 是 ServiceManager 連接各種 Manager(ActivityManager、WindowManager...) 和相應 ManagerService 的橋梁;從 Android 應用層來說,Binder 是客戶端和服務端進行通信的媒介,當 bindService 的時候,服務端會返回一個包含了服務端業務調用的 Binder 對象,通過這個 Binder 對象,客戶端就可以獲取服務端提供的服務或者數據,這里的服務包括普通服務和基於 AIDL 服務。
Binder 定義了四個角色:Server,Client,ServiceManager 和 Bidner 驅動,其中 Server、Client、ServiceManager 運行於用戶空間,Binder 驅動運行於內核空間。
Binder 工作原理:
⑻ Android 進程間通信的幾種實現方式
Android 進程間通信的幾種實現方式
主要有4種方式:
這4種方式正好對應於android系統中4種應用程序組件:Activity、Content Provider、Broadcast和Service。
主要實現原理:
由於應用程序之間不能共享內存。為了在不同應用程序之間交互數據(跨進程通訊),AndroidSDK中提供了4種用於跨進程通訊的方式進行交互數據,實現進程間通信主要是使用sdk中提供的4組組件根據實際開發情況進行實現數據交互。
詳細實現方式:
Acitivity實現方式
Activity的跨進程訪問與進程內訪問略有不同。雖然它們都需要Intent對象,但跨進程訪問並不需要指定Context對象和Activity的 Class對象,而需要指定的是要訪問的Activity所對應的Action(一個字元串)。有些Activity還需要指定一個Uri(通過 Intent構造方法的第2個參數指定)。 在android系統中有很多應用程序提供了可以跨進程訪問的Activity,例如,下面的代碼可以直接調用撥打電話的Activity。
IntentcallIntent=newIntent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent);
Content Provider實現方式
Android應用程序可以使用文件或SqlLite資料庫來存儲數據。Content Provider提供了一種在多個應用程序之間數據共享的方式(跨進程共享數據)
應用程序可以利用Content Provider完成下面的工作
1. 查詢數據
2. 修改數據
3. 添加數據
4. 刪除數據
Broadcast 廣播實現方式
廣播是一種被動跨進程通訊的方式。當某個程序向系統發送廣播時,其他的應用程序只能被動地接收廣播數據。這就象電台進行廣播一樣,聽眾只能被動地收聽,而不能主動與電台進行溝通。在應用程序中發送廣播比較簡單。只需要調用sendBroadcast方法即可。該方法需要一個Intent對象。通過Intent對象可以發送需要廣播的數據。
Service實現方式
常用的使用方式之一:利用AIDL Service實現跨進程通信
這是我個人比較推崇的方式,因為它相比Broadcast而言,雖然實現上稍微麻煩了一點,但是它的優勢就是不會像廣播那樣在手機中的廣播較多時會有明顯的時延,甚至有廣播發送不成功的情況出現。
注意普通的Service並不能實現跨進程操作,實際上普通的Service和它所在的應用處於同一個進程中,而且它也不會專門開一條新的線程,因此如果在普通的Service中實現在耗時的任務,需要新開線程。
要實現跨進程通信,需要藉助AIDL(Android Interface Definition Language)。Android中的跨進程服務其實是採用C/S的架構,因而AIDL的目的就是實現通信介面。
總結
跨進程通訊這個方面service方式的通訊遠遠復雜於其他幾種通訊方式,實際開發中Activity、Content Provider、Broadcast和Service。4種經常用到,學習過程中要對沒種實現方式有一定的了解。
⑼ 了解Android進程間通信的四種方式
由於應用程序之間不能共享內存。在不同應用程序之間交互數據(跨進程通訊),在android
SDK中提供了4種用於跨進程通訊的方式。這4種方式正好對應於android系統中4種應用程序組
件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨進程調用其他應
用程序的Activity;Content Provider可以跨進程訪問其他應用程序中的數據(以Cursor對象形
式返回),當然,也可以對其他應用程序的數據進行增、刪、改操 作;Broadcast可以向
android系統中所有應用程序發送廣播,而需要跨進程通訊的應用程序可以監聽這些廣播;
Service和Content Provider類似,也可以訪問其他應用程序中的數據,但不同的是,Content
Provider返回的是Cursor對象,而Service返回的是Java對象,這種可以跨進程通訊的服務叫
AIDL服務。
⑽ android中的進程通信和Binder機制
如果統觀Binder中的各個組成元素,就會驚奇的發現它和TCP/IP網路有很多相似之處:
首先Binder是android進程間通信的一種方式,
基本原理:binder定義了4個角色:client,server,serviceManager ,binder驅動
server會創建一個binder實體並起一個名字,然後將名字一塊以數據包的形式通過binder驅動發送給serviceManager ,通知servicemanager注冊一個名字為xx的Binder,然後client通過名字查詢到該Binder 的引用。
注意