導航:首頁 > 操作系統 > android跨進程調用

android跨進程調用

發布時間:2022-12-19 09:06:15

1. android開發中跨進程通信有幾種方式

Android進程間通信的幾種方式 定義多進程
第一:Android應用中使用多進程只有一個辦法(用NDK的fork來做除外),就是在AndroidManifest.xml中聲明組件時,用android:process屬性來指定。
不知定process屬性,則默認運行在主進程中,主進程名字為包名。
android:process = package:remote,將運行在package:remote進程中,屬於全局進程,其他具有相同shareUID與簽名的APP可以跑在這個進程中。
android:process = :remote ,將運行在默認包名:remote進程中,而且是APP的私有進程,不允許其他APP的組件來訪問。
第二:多進程引發的問題
靜態成員和單例失效:每個進程保持各自的靜態成員和單例,相互獨立。
線程同步機制失效:每個進程有自己的線程鎖。
SharedPreferences可靠性下降:不支持並發寫,會出現臟數據。
Application多次創建:不同進程跑在不同虛擬機,每個虛擬機啟動會創建自己的Application,自定義Application時生命周期會混亂。
綜上,不同進程擁有各自獨立的虛擬機,Application,內存空間,由此引發一系列問題。
第三: 進程間通信
Bundle/Intent傳遞數據:
可傳遞基本類型,String,實現了Serializable或Parcellable介面的數據結構。Serializable是java的序列化方法,Parcellable是Android的序列化方法,前者代碼量少(僅一句),但I/O開銷較大,一般用於輸出到磁碟或網卡;後者實現代碼多,效率高,一般用戶內存間序列化和反序列化傳輸。
文件共享:
對同一個文件先後寫讀,從而實現傳輸,Linux機制下,可以對文件並發寫,所以要注意同步。順便一提,Windows下不支持並發讀或寫。
Messenger:
Messenger是基於AIDL實現的,服務端(被動方)提供一個Service來處理客戶端(主動方)連接,維護一個Handler來創建Messenger,在onBind時返回Messenger的binder。
雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串列的,也就是說,Handler接到多個message時,就要排隊依次處理。
AIDL:
AIDL通過定義服務端暴露的介面,以提供給客戶端來調用,AIDL使伺服器可以並行處理,而Messenger封裝了AIDL之後只能串列運行,所以Messenger一般用作消息傳遞。
通過編寫aidl文件來設計想要暴露的介面,編譯後會自動生成響應的java文件,伺服器將介面的具體實現寫在Stub中,用iBinder對象傳遞給客戶端,客戶端bindService的時候,用asInterface的形式將iBinder還原成介面,再調用其中的方法。
ContentProvider:
系統四大組件之一,底層也是Binder實現,主要用來為其他APP提供數據,可以說天生就是為進程通信而生的。自己實現一個ContentProvider需要實現6個方法,其中onCreate是主線程中回調的,其他方法是運行在Binder之中的。自定義的ContentProvider注冊時要提供authorities屬性,應用需要訪問的時候將屬性包裝成Uri.parse("content://authorities")。還可以設置permission,readPermission,writePermission來設置許可權。 ContentProvider有query,delete,insert等方法,看起來貌似是一個資料庫管理類,但其實可以用文件,內存數據等等一切來充當數據源,query返回的是一個Cursor,可以自定義繼承AbstractCursor的類來實現。
Socket:
學過計算機網路的對Socket不陌生,所以不需要詳細講述。只需要注意,Android不允許在主線程中請求網路,而且請求網路必須要注意聲明相應的permission。然後,在伺服器中定義ServerSocket來監聽埠,客戶端使用Socket來請求埠,連通後就可以進行通信。

2. Carson帶你學Android:全面剖析Binder跨進程通信原理

從而全方位地介紹 Binder ,希望你們會喜歡。

在本文的講解中,按照 大角度 -> 小角度 去分析 Binder ,即:

從而全方位地介紹 Binder ,希望你們會喜歡。

在講解 Binder 前,我們先了解一些 Linux 的基礎知識

具體請看文章: 操作系統:圖文詳解 內存映射

Binder 跨進程通信機制 模型 基於 Client - Server 模式

此處重點講解 Binder 驅動作用中的跨進程通信的原理:

原因:

所以,原理圖可表示為以下:

所以,在進行跨進程通信時,開發者只需自定義 Client & Server 進程 並 顯式使用上述3個步驟,最終藉助 Android 的基本架構功能就可完成進程間通信

注冊服務後, Binder 驅動持有 Server 進程創建的 Binder 實體

此時, Client 進程與 Server 進程已經建立了連接

Client 進程 根據獲取到的 Service 信息( Binder 代理對象),通過 Binder 驅動 建立與 該 Service 所在 Server 進程通信的鏈路,並開始使用服務

步驟1: Client 進程 將參數(整數a和b)發送到 Server 進程

步驟2: Server 進程根據 Client 進要求 調用 目標方法(即加法函數)

步驟3: Server 進程 將目標方法的結果(即加法後的結果)返回給 Client 進程

對比 Linux ( Android 基於 Linux )上的其他進程通信方式(管道、消息隊列、共享內存、
信號量、 Socket ), Binder 機制的優點有:

特別地,對於從模型結構組成的Binder驅動來說:

不定期分享關於 安卓開發 的干貨,追求 短、平、快 ,但 卻不缺深度

3. Android如何跨進程同步

兩個進程要進行同步,如果用IPC機制通信來同步,那麼就會遇到一個問題,那就是這兩個進程必須都已經啟動才可以,如果遇到一個進程啟動,但是另外一個進程不知道什麼時候啟動,這個辦法就很難行得通了。

這時候就可以用到Android系統根據java提供的 FileLock 類

1.FileLock是線程安全的

2.FileLock適用於進程間文件讀寫控制,不適用於同一進程的不同線程

3.分為共享鎖和獨占鎖,共享鎖允許其他進程同樣獲取共享鎖,獨占鎖不允許其他進程獲得鎖。

4.有兩種方式獲得文件鎖,FileChannel的lock和tryLock,用lock會阻塞當前線程,直到獲取到鎖,用tryLock會嘗試獲取,如果獲取失敗則返回null,不會阻塞線程。

5.FileLock釋放的條件是:自己調用release/close或者所使用的FileChannel調用close或者是JVM終止運行。

6.文件鎖的效果是與操作系統相關的。一些系統中文件鎖是強制性的,當Java的某進程獲得文件鎖後,操作系統將保證其它進程無法對文件做操作了。而另一些操作系統的文件鎖是詢問式的(advisory),意思是說要想擁有進程互斥的效果,其它的進程也必須也按照API所規定的那樣來申請或者檢測文件鎖,不然將起不到進程互斥的功能。所以文檔里建議將所有系統都當做是詢問式系統來處理,這樣程序更加安全也更容易移植。

我們這里用的就是獨占鎖。

這個是先運行的獲取鎖的類,獲取鎖後持有10s後釋放。

這個類是在第一個類運行後再運行的類,此時該進程會一直等到FileLockTest釋放鎖後才能獲得鎖然後繼續運行。我們可以在獲得鎖之後do any thing you want,從而實現進程間同步。

多次運行後可能有人會發現有時候先列印獲得鎖後列印釋放鎖,其實是這樣的,這是兩個進程,一個進程釋放鎖之後另外一個進程才可能獲得鎖,但是兩個進程的列印時間的執行不是同步的,所以不一定是先列印釋放鎖,只要時間基本一致即可(本人多次運行時間差小於2ms)。

通過這兩個類的分別運行,可以看到即使不是都啟動完成,一樣可以跨進程同步。

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服務。

5. 安卓IPC跨進程通訊:AIDL+Retrofit——AndLinker的初步使用

需要用到安卓跨進程通訊,IPC (進程間通信) 的時候,AndLinker是一款Android上的IPC (進程間通信) 庫,結合了 AIDL 和 Retrofit 的諸多特性,且可以與 RxJava 和 RxJava2 的Call Adapters無縫結合使用。

個人簡單理解就是:簡化AIDL流程的一個第三方庫。使用時需要先了解一下AIDL、retrofit。

以普通Java介面代替AIDL介面

像 Retrofit 一樣生成遠程服務介面的IPC實現

支持的Call Adapters:Call, RxJava  Observable, RxJava2  Observable & Flowable

支持遠程服務回調機制

支持AIDL的所有數據類型

支持AIDL的所有數據定向tag:in,out,inout

支持AIDL的oneway關鍵字

在服務端以及客戶端的項目根目錄的build.gradle中添加jcenter()倉庫

在App的build.gradle中添加如下依賴

AndLinker支持AIDL所有數據類型:

Java語言中的所有原始類型 (如:int,long,char,boolean,等等)

String

CharSequence

Parcelable

List (List中的所有元素必須是此列表中支持的數據類型)

Map (Map中的所有元素必須是此列表中支持的數據類型)

介面里的方法就是按需求需創建。這里只舉幾個簡單的示例。

6. Android跨進程通信-共享內存

還是先看共享內存的使用方法,我主要介紹兩個函數:

通過 shmget() 函數申請共享內存,它的入參如下

通過 shmat() 函數將我們申請到的共享內存映射到自己的用戶空間,映射成功會返回地址,有了這個地址,我們就可以隨意的讀寫數據了,我們繼續看一下這個函數的入參

共享內存的原理是在內存中單獨開辟的一段內存空間,這段內存空間其實就是一個tempfs(臨時虛擬文件),tempfs是VFS的一種文件系統,掛載在/dev/shm上,前面提到的管道pipefs也是VFS的一種文件系統。

由於共享的內存空間對使用和接收進程來講,完全無感知,就像是在自己的內存上讀寫數據一樣,所以也是 效率最高 的一種IPC方式。

上面提到的IPC的方式都是 在內核空間中開辟內存來存儲數據 ,寫數據時,需要將數據從用戶空間拷貝到內核空間,讀數據時,需要從內核空間拷貝到自己的用戶空間,
共享內存就只需要一次拷貝 ,而且共享內存不是在內核開辟空間,所以可以 傳輸的數據量大

但是 共享內存最大的缺點就是沒有並發的控制,我們一般通過信號量配合共享內存使用,進行同步和並發的控制

共享內存在Android系統中主要的使用場景是 用來傳輸大數據 ,並且 Android並沒有直接使用Linux原生的共享內存方式,而是設計了Ashmem匿名共享內存

之前說到有名管道和匿名管道的區別在於有名管道可以在vfs目錄樹中查看到這個管道的文件,但是匿名管道不行, 所以匿名共享內存同樣也是無法在vfs目錄中查看到 的, Android之所以要設計匿名共享內存 ,我覺得主要是為了安全性的考慮吧。

我們來看看共享內存的一個使用場景,在Android中,如果我們想要將當前的界面顯示出來,需要將當前界面的圖元數據傳遞Surfaceflinger去做圖層混合,圖層混合之後的數據會直接送入幀緩存,送入幀緩存後,顯卡就會直接取出幀緩存里的圖元數據顯示了。

那麼我們如何將應用的Activity的圖元數據傳遞給SurfaceFlinger呢?想要將圖像數據這樣比較大的數據跨進程傳輸,靠binder是不行的,所以這兒便用到匿名共享內存。

從谷歌官方提供的架構圖可以看到,圖元數據是通過BufferQueue傳遞到SurfaceFlinger去的,當我們想要繪制圖像的時候, 需要從BufferQueue中申請一個Buffer,Buffer會調用Gralloc模塊來分配共享內存 當作圖元緩沖區存放我們的圖元數據。

可以看到Android的匿名共享內存是通過 ashmem_create_region() 函數來申請共享內存的,它會在/dev/ashmem下創建一個虛擬文件,Linux原生共享內存是通過shmget()函數,並會在/dev/shm下創建虛擬文件。

匿名共享內存是通過 mmap() 函數將申請到的內存映射到自己的進程空間,而Linux是通過*shmat()函數。

雖然函數不一樣,但是Android的匿名共享內存和Linux的共享內存在本質上是大同小異的。

要使用一塊共享內存

7. Android 跨進程通信--Binder篇

話說Binder 其實是由George Hoffman 老哥,在1991年Be公司啟動了一個「openBinder」的項目,該項目的宗旨是研究一個高效的信號傳遞工具,允許多個軟體相互合作,構成一個軟體系統。在BE被parmSource收購以後,openBinder由hackborn繼續開發。在Hackborn加入google之後,他繼續開發出了Android Binder。

而Android系統是基於Linux內核實現的,Linux已經提供了多種進程間通信機制,比如:管道、消息隊列、共享內存和套接字(Socket)等等。

講它們優缺點前先補充說明:
「進程隔離」--這個技術是為了避免進程A寫入進程B的情況發生。 進程的隔離實現,使用了虛擬地址空間進程A的虛擬地址和進程B的虛擬地址不同,這樣就防止進程A將數據信息寫入進程B。進程隔離的安全性通過禁止進程間內存的訪問可以方便實現。相比之下,一些不安全的操作系統DOS能夠允許任何進程對其他進程的內存進行寫操作。

「虛擬內存」-- 是計算機系統內存管理的一種技術。它使得應用程序認為它擁有連續可用的內存(一個連續完整的地址空間),而實際上,它通常是被分隔成多個物理內存碎片,還有部分暫時存儲在外部磁碟存儲器上,在需要時進行數據交換。與沒有使用虛擬內存技術的系統相比,使用這種技術的系統使得大型程序的編寫變得更容易,對真正的物理內存的使用也更有效率。

注意: 虛擬內存 不只是「用磁碟空間來擴展物理內存」的意思——這只是擴充內存級別以使其包含硬碟驅動器而已。把內存擴展到磁碟只是使用虛擬內存技術的一個結果,它的作用也可以通過覆蓋或者把處於不活動狀態的程序以及它們的數據全部交換到磁碟上等方式來實現。對虛擬內存的定義是基於對地址空間的重定義的,即把地址空間定義為「連續的虛擬內存地址」,以藉此「欺騙」程序,使它們以為自己正在使用一大塊的「連續」地址。

8. Android跨進程通信

Android 為我們提供了以下幾種進程通信機制(供開發者使用的進程通信 API)對應的文章鏈接如下:

Android 進階:進程通信之 Binder 機制淺析
Android 進階:進程通信之 AIDL 解析

9. android開發中跨進程通信有幾種方式

  1. Activity可以跨進程調用其他應用程序;

  2. Content Provider可以跨進程訪問其他應用程序中的數據;

  3. Broadcast可以向android系統中所有應用程序發送廣播;

  4. Content Provider返回的是Cursor對象,而Service返回的是Java對象,這種可以跨進程通訊的服務叫AIDL服務;

10. Android 使用Messenger實現跨進程之間通信

以前講到跨進程通信,我們總是第一時間想到AIDL(Android介面定義語言),實際上,使用Messenger在很多情況下是比使用AIDL簡單得多的。
大家看到Messenger可能會很輕易的聯想到Message,然後很自然的進一步聯想到Handler——沒錯,Messenger的核心其實就是Message以及Handler來進行線程間的通信。

以下是如何使用Messenger的步驟:

綜上六步就能完成客戶端與Service的跨進程雙向通信過程:
客戶端 -> Service -> 客戶端
簡單的例子(客戶端向伺服器端發送消息,伺服器接收):

服務端主要是返給客戶端一個IBinder實例,以供服務端構造Messenger,並且處理客戶端發送過來的Message。當然,不要忘了要在Manifests文件裡面注冊.

客戶端就主要是發起與服務端的綁定,以及通過onServiceConnected()方法來過去服務端返回來的IBinder,藉此構造Messenger,從而可以通過發送Message的方式與服務端進行交互。

伺服器接收消息後回復消息給客戶端

客戶端修改:
客戶端需要添加一個handler用於接收消息

服務端修改:
在服務端的handler獲取客戶端發送的msg.replyTo

閱讀全文

與android跨進程調用相關的資料

熱點內容
扣扣加密技巧 瀏覽:720
蘋果如何創建伺服器錯誤 瀏覽:495
軟考初級程序員大題分值 瀏覽:473
js壓縮視頻文件 瀏覽:578
linux如何通過命令創建文件 瀏覽:989
應用加密app還能訪問應用嘛 瀏覽:433
安卓怎麼用支付寶交違章罰款 瀏覽:665
php面向對象的程序設計 瀏覽:504
數據挖掘演算法書籍推薦 瀏覽:894
投訴聯通用什麼app 瀏覽:150
web伺服器變更ip地址 瀏覽:954
java正則表達式驗證郵箱 瀏覽:360
成熟商務男裝下載什麼軟體app 瀏覽:609
加密2h代表長度是多少厘米 瀏覽:23
拍賣程序員 瀏覽:101
電腦的圖片放在哪個文件夾 瀏覽:276
unsignedintjava 瀏覽:217
編譯器下載地址 瀏覽:43
什麼是面對對象編程 瀏覽:709
b站伺服器什麼時候恢復 瀏覽:722