1. 程式人生 > >寫給Android App開發人員看的Android底層知識(6)

寫給Android App開發人員看的Android底層知識(6)

(十一)BroadcastReceiver

BroadcastReceiver,也就是廣播,簡稱Receiver。

     很多App開發人員表示,從來沒用過Receiver。其實吧,對於音樂播放類App,用Service和Receiver還是蠻多的,如果你用過QQ音樂,App退到後臺,音樂照樣播放不會停止,這就是你寫的Service在後臺起作用。

     在前臺的Activity,點選停止按鈕,就會給後臺Service傳送一個Receiver,通知它停止播放音樂;點選播放按鈕,仍然是傳送這個Receiver,只是攜帶的值變了,所以Service收到請求後播放音樂。

     反過來,後臺Service播放每播放完一首音樂,接下來準備播放下一首音樂的時候,就會給前臺Activity發Receiver,讓Activity顯示下一首音樂的名稱。

所以音樂播放器的原理,就是一個前後臺Activity和Service互相傳送和接收Receiver的過程。

     

     Receiver分靜態廣播和動態廣播兩種。

     在Manifest中宣告的Receiver,是靜態廣播:

     

     在程式中手動寫註冊程式碼的,是動態廣播:

     

     二者具有相同的功能,只是寫法不同。既然如此,我們就可以把所有靜態廣播,都改為動態廣播,這就省的在Manifest檔案中聲明瞭,避免了AMS檢查。接下來你想到什麼?對,Receiver的外掛化解決方案,就是這個思路。

     接下來我們看Receiver是怎麼和AMS打交道的,分為兩部分,一是註冊,二是傳送廣播。

     你只有註冊了這個廣播,傳送這個廣播時,才能通知到你,執行onReceive方法。

     我們就拿音樂播放器來舉例,在Activity註冊Receiver,在Service傳送廣播。Service播放下一首音樂時,會通知Activity修改當前正在播放的音樂名稱。

     註冊過程如下所示:

     1)在Activity中,註冊Receiver,並通知AMS。

     

     這裡Activity使用了Context提供的registerReceiver方法,然後通過AMN/AMP,把一個receiver傳給AMS。

     在建立這個Receiver物件的時候,需要為receiver指定IntentFilter,這個filter就是Receiver的身份證,用來描述receiver。

     在Context的registerReceiver方法中,它會使用PMS獲取到包的資訊,也就是LoadedApk物件。

     就是這個LoadedApk物件,它的getReceiverDispatcher方法,將Receiver封裝成一個實現了IIntentReceiver介面的Binder物件。

     我們就是將這個Binder物件和filter傳遞給AMS。

     只傳遞Receiver給AMS是不夠的,當傳送廣播時,AMS不知道該發給誰啊?所以Activity所在的程序還要把自身物件也傳送給AMS。

     2)AMS收到訊息後,就會把上面這些資訊,存在一個列表中,這個列表中儲存了所有的Receiver。

     注意了,這裡忙活半天,都是在註冊動態receiver。

     靜態receiver什麼時候註冊到AMS的呢?是在App安裝的時候。PMS會解析Manifest中的四大元件資訊,把其中的receiver存起來。

     動態receiver和靜態receiver分別存在AMS不同的變數中,在傳送廣播的時候,會把兩種receiver合併到一起,然後以此傳送。其中動態的排在靜態的前面,所以動態receiver永遠優先於靜態receiver收到訊息。

     此外,Android系統每次啟動的時候,也會把靜態廣播接收者註冊到AMS。因為Android系統每次啟動時,都會重新安裝所有的apk,詳細流程,我們會在後面PMS的相關章節看到。

     - - - - - - - - - - - - - - - 華麗的分界線------------------------

    傳送廣播的流程如下:

     1)在Service中,通過AMM/AMP,傳送廣播給AMS,廣播中攜帶著Filter。

     2)AMS收到這個廣播後,在receiver列表中,根據filter找到對應的receiver,可能是多個,把它們都放到一個廣播佇列中。最後向AMS的訊息佇列傳送一個訊息。

     當訊息佇列中的這個訊息被處理時,AMS就從廣播佇列中找到合適的receiver,向廣播接收者所在的程序傳送廣播。

     3)receiver所在的程序收到廣播,並沒有把廣播直接發給receiver,而是將廣播封裝成一個訊息,傳送到主執行緒的訊息佇列中,當這個訊息被處理時,才會把這個訊息中的廣播發送給receiver。

     我們下面通過圖,仔細看一下這3個階段:

     第1步,Service傳送廣播給AMS

     

     傳送廣播,是通過Intent這個引數,攜帶了Filter,從而告訴AMS,什麼樣的receiver能接受這個廣播。

第2步,AMS接收廣播,傳送廣播。

     接收廣播和傳送廣播是不同步的。AMS每接收到一個廣播,就把它扔到廣播發送佇列中,至於傳送是否成功,它就不管了。

     因為receiver分為無序receiver和有序receiver,所以廣播發送佇列也分為兩個,分別傳送這兩種廣播。

     AMS傳送廣播給客戶端,這又是一個跨程序通訊,還是通過ATP,把訊息發給APT。因為要傳遞Receiver這個物件,所以它也是一個Binder物件,才可以傳過去。我們前面說過,在把Receiver註冊到AMS的時候,會把Receiver封裝為一個IIntentReceiver介面的Binder物件。那麼接下來,AMS就是把這個IIntentReceiver介面物件傳回來。

     第3步,App處理廣播

     

     這個流程描述如下:

     1)訊息從AMS傳到客戶端,把AMS中的IIntentReceiver介面物件轉為InnerReceiver物件,這就是receiver,這是一個AIDL跨程序通訊。

     2)然後在ReceiverDispatcher中封裝一個Args物件(這是一個Runnable物件,要實現run方法),包括廣播接收者所需要的所有資訊,交給ActivtyThread來發送

     3)接下來要走的路就是我們所熟悉的了,ActivtyThread把Args訊息扔到H這個Hanlder中,向主執行緒訊息佇列傳送訊息。等到執行Args訊息的時候,自然是執行Args的run方法。

     4)在Args的run方法中,例項化一個Receiver物件,呼叫它的onReceiver方法。

     5)最後,在Args的run方法中,隨著Receiver的onReceiver方法呼叫結束,會通過AMN/AMP傳送一個訊息個AMS,告訴AMS,廣播發送成功了。AMS得到通知後,就傳送廣播給下一個Receiver。

     注意:InnerReceiver是IIntentReceiver的stub,是Binder物件的接收端。

    廣播的種類

     Android廣播按傳送方式分類有三種:無序廣播、有序廣播(OrderedBroadcast)和粘性廣播(StickyBroadcast)。

     1)無序廣播是最普通的廣播。

     2)有序廣播區別於無序廣播,就在於它可以指定優先順序。

這兩種receiver存在AMS不同的變數中,可以認為是兩個receiver集合,傳送不同類別的廣播。

     3)粘性廣播是無序廣播的一種。

     粘性廣播,我們平常見的不多,但我說一個場景你就明白了,那就是電池電量。當電量小於20%的時候,就會提示使用者。

     而獲取電池的電量資訊,就是通過廣播來實現的。

     但是一般的廣播,發完就完了。我們需要有這樣一種廣播,發出後,還能一直存在,未來的註冊者也能收到這個廣播,這種廣播就是粘性廣播。

     由於動態receiver只能在Activity的onCreate()方法呼叫時才能註冊再接收廣播,所以當程式沒有執行就不能接受到廣播;但是靜態註冊的則不依賴於程式是否處於執行狀態。

     至此,關於廣播的所有概念,就全都介紹完了,就連我都比較驚訝的是,我居然沒貼什麼程式碼。希望上述這兩千多字,能引導App開發人員進入一個神奇的世界。

     下一篇文章,我們去看看ContentProvider。

相關推薦

Android App開發人員Android底層知識1

這個系列的文章一共8篇,我醞釀了很多年,參考了很多資源,查看了很多原始碼,直到今天把它寫出來,也是戰戰兢兢,生怕什麼地方寫錯了,貽笑大方 (一)引言 早在我還是Android菜鳥的時候,有很多技術我都不太明白,也都找不到答案,比如apk是怎麼安裝的,比如資源是怎

Android App開發人員Android底層知識8

(十)PMS及App安裝過程        PMS,全稱PackageManagerService,是用來獲取Apk包的資訊的。        在前面分析四大元件與AMS通訊的時候,我們介紹過,AMS總是會使用PMS載入包的資訊,將其封裝在LoadedApk這個類物件

Android App開發人員Android底層知識7

(十二)ContentProvider (1)ContentProvider是什麼? ContentProvider,簡稱CP。 做App開發的同學,尤其是電商類App,對CP並不熟悉,對這個概念的最大程度的瞭解,也僅僅是建立在書本上,它是Android四大元件中的一個。 做系統管理類的App,比

Android App開發人員Android底層知識5

     (十)Service      Service有兩套流程,一套是啟動流程,另一套是繫結流程。我們做App開發的同學都應該知道。            1)在新程序啟動Service        我們先看Service啟動過程,假設要啟動的Service是在一個新的程序中,分為5個階段:

Android App開發人員Android底層知識4

(八)App內部的頁面跳轉       在介紹完App的啟動流程後,我們發現,其實就是啟動一個App的首頁。       接下來我們看App內部頁面的跳轉。       從ActivityA跳轉到ActivityB,其實可以把ActivityA看作是Launcher,那麼這個跳轉過程,和Ap

Android App開發人員Android底層知識3

       (七)App啟動流程第2篇        書接上文,App啟動一共有七個階段,上篇文章篇幅所限,我們只看了第一階段,接下來講剩餘的六個階段,仍然是拿鬥魚App舉例子。        簡單回顧一下第一階段的流程,就是Launcher向AMS傳送一個跨程序通訊,通過AMN/AMP,告訴A

Android App開發人員Android底層知識2

(五)AMS 如果站在四大元件的角度來看,AMS就是Binder中的Server。       AMS全稱是ActivityManagerService,看字面意思是管理Activity的,但其實四大元件都歸它管。估計是Android底層開發人員先寫了ActivityManagerService用來管理A

Android App開發人員Android底層知識6

(十一)BroadcastReceiver BroadcastReceiver,也就是廣播,簡稱Receiver。      很多App開發人員表示,從來沒用過Receiver。其實吧,對於音樂播放類App,用Service和Receiver還是蠻多的,如果你用過QQ音樂,App退到後臺,音樂照樣播放

初次接觸Android APP開發之安裝Android studio軟體出現的問題以及解決方案錯誤史,一把辛酸淚

     序言     筆者由於心血來潮,想玩玩Android開發。本想著用eclipes開發Android APP。但是發現網上說eclipes不是最好的選擇,所以筆者就放棄了熟悉的eclipes來開發Android APP,改用Android studio。在此之前,筆

Android應用開發:網絡工具——Volley

respond sid 開發 多少 called creat miss 相等 eal 引言 在Android應用開發:網絡工具——Volley(一)中結合Cloudant服務介紹了Volley的一般使用方法,當中包括了兩種請求類型StringRequest和JsonOb

Android應用開發:網絡工具——Volley

要求 com 庫文件 urn welcom 順序 之前 air tin 引言 網絡一直是我個人的盲點,前一陣子抽空學習了一下Volley網絡工具的用法,也透過源代碼進行了進一步的學習,有一些心得想分享出來。在Android開發中,成熟的網絡工具不少,And

Android安全/開發基礎--8--Java本地介面JNI

8-1、JNI概述 JNI的本意是Java Native Interface(Java本地介面),是為了方便Java和C/C++等原生代碼所封裝的一層介面,使用JNI技術可以對Java層遮蔽不同作業系統平臺之間的差異,從而實現Java本身的平臺無關特性。JNI和

Android應用開發以及設計思想深度剖析1

本文內容,主題是透過應用程式來分析Android系統的設計原理與構架。我們先會簡單介紹一下Android裡的應用程式程式設計,然後以這些應用程 序在執行環境上的需求來分析出,為什麼我們的Android系統需要今天這樣的設計方案,這樣的設計會有怎樣的意義, Android究竟

一個android專案開發遇到的各種小問題

1、map格式字串如何解析? 藉助json,先將字串轉化為json格式,再取值 JSONObject object = new JSONObject(posMap); clientIden = object.getString("iden"); ---------

【安卓-自定義佈局】安卓App開發思路 一步一個腳印實現內嵌在app中的webview 騰訊開源X5 高效安全

實現內嵌在app中的webview 採用騰訊開源X5 高效安全 webview在app的使用中,十分頻繁,原生的webview載入速度相對來說很慢,而且很費流量。騰訊開源了x5的webview

【安卓-自定義佈局】安卓App開發思路 一步一個腳印實現自定義滾動的新聞條目上下滾動-仿蘑菇街

實現自定義滾動的新聞條目上下滾動-仿蘑菇街       這種上下滾動的自定義佈局,就像是公告那種上下的翻滾,一般為文字的滾動,很明顯,就是自定義佈局,一般是線性佈局。這裡提到的安卓原生的控制元件自然是

數據庫——6連接

style 連接 post 匹配 兩個 rom data- span 笛卡爾積 簡單介紹: 連接是多表查詢的基礎。 因為關系數據庫不包括指針或其它關聯記錄與記錄的機制,連接成為了生成跨表數據關系的唯一機制。這也就是要用連接的原因。 分類: 1、內連接 使用

遊戲開發中必備的數學知識——矩陣的基本變換

基本變換 使用Direct3D程式設計的時候,我們使用4×4的矩陣表示一個變換。其思路如下: 設定一個4×4的矩陣中元素的值,使其表示某一個具體變換,然後我們將某一點的座標或者某向量的分量放入一個1×4的行向量v中,乘積vX就是成為了一個新的經過變換的向量v。 此時,我們之所以使用4×4

[App Store Connect幫助]四、添加 App 圖標、App 預覽和屏幕快照6設置 App 預覽海報幀

ask 使用 eight body 顯示 屏幕快照 http conn https App 預覽海報幀僅在 App 狀態為可編輯時,才能被編輯。 必要職能:“帳戶持有人”職能、“管理”職能、“App 管理&rdq

java開發需要知道的linux知識

water RoCE ESS xshel watermark ref process 網上 .sh 做為一個後端開發,經常需要上服務器上看看哪裏出問題了,又報什麽錯了,所以對程序員的服務器技能提出了一定的要求,要學到專業運維那個程度肯定是不可能的,我們只用掌握常用的的些就可