android廣播用法
❶ android中的廣播怎麼使用
廣播操作有兩種
1、發送廣播,就是你自己發送出去一個廣播,讓別人接收
2、接收廣播,這個是自己實現一個廣播接收器,接收那些你自己過濾的廣播,然後處理
具體的代碼實現,可以在網上找找
❷ 說說Android的廣播(1)
對於Activity的啟動流程,我們已經有了幾個版本的分析了。這里我們分析一個更容易一些的,四大組件中最簡單的Broadcast Receiver。
關於Broadcast,有幾點需要了解。首先是廣播的類型,然後是廣播的發送方法,最後是廣播是如何被接收的。這三者相輔相承的,比如普通廣播和有序廣播只有在詳細了解了廣播的接收過程了之後,才能真正明白它的含義。
普通的廣播是不在意順序的,最簡單的理解是同時可以收到這個廣播。如果應用是動態注冊這個廣播的,且廣播發送時這個進程還活著,那麼當然可以並發的把廣播盡快地傳送出去是最好的。
但是,如果是通過AndroidManifest.xml靜態注冊的情況,也就是說這個廣播首先要把一個進程啟動起來,這時並發啟動很多進程就是個問題了。Android目前的做法是,對這種靜態的廣播接收者,自動按有序廣播的方式來串列處理。但是這對應用是透明的,應用不能假設系統已經把靜態的無序廣播當成有序廣播來處理。
這個時候講粘性廣播有福了,因為從Android 5.0(API 21)開始,因為安全性的問題,官方已經正式廢棄了粘性廣播。
Context類提供兩個方法可以用於發送普通廣播:
差別是第二個設置許可權。
發給特定的用戶:
有序廣播因為要處理消息的處理結果,所以要復雜一些。
如果只是想讓廣播可以按優先順序來收取,並不在意處理的結果,可以用下面的版本:
同樣,在多用戶環境下,也可以選擇給哪個用戶發廣播:
不管是普通的還是有序的廣播都對應有粘性的版本:
以上的API都是定義於Context類中: https://developer.android.com/reference/android/content/Context.html
首先我們先看看發送端是如何發送的。
我們首先先放一個大圖,讓大家先有一個直觀的印象,不管普通廣播、有序廣播、粘性廣播如何組合,最終都匯集到一個大方法中。
我們先看應用發送普通廣播的一個簡單的例子:
非常簡單,調用ContentWrapper的sendBroadcast方法就可以了。
然後我們順藤摸瓜就好了。
Activity中的sendBroadcast,實際上調用的是:
我們來看frameworks/base/core/java/android/content/ContextWrapper.java中對sendBroadcast的定義:
ContextWrapper只是一個包裝,真正的實現在ContextImpl中
我們來看/frameworks/base/core/java/android/app/ContextImpl.java中真正實現sendBroadcast的功能:
它會通過IPC去調用AMS的broadcastIntent。由於我們這個普通的廣播的方法參數最少,所以好多都是傳null。
加鎖,定參數,然後調用真正的邏輯的實現。
我們先把broadcastIntentLocked的真正邏輯放一下,先看看有序廣播是如何發送的。
ContextWrapper.sendOrderedBroadcast
Context是abstract方法,調用的是ContextWrapper的實現:
跟普通廣播一樣,還是會調用到ContextImpl.sendOrderedBroadcast
有序廣播調用broadcastIntent的區別在於serialized參數,普通廣播為false,有序廣播為true.
原型為:
前面講過帶有回調的版本,我們看看它是如何實現的:
當然還是調用ContextImpl.sendOrderedBroadcast
這次變成只是一個封裝了,它會調用一個更多參數的版本:
這次是一個全參數調用broadcastIntent的版本了,除了sticky就齊了
我們也不繞圈子了,直接看ContextImpl.sendStickyBroadcast.
❸ Android啟動廣播時怎樣往廣播中傳遞參數
在android中使用廣播來讓其他監聽廣播的地方能夠對相應的事情做處理,但有的時候需要傳遞一些其他的附帶值,而這個時候是可以直接用播放廣播的intent來傳遞的。x0dx0a例:x0dx0aIntent intent = new Intent();x0dx0aintent.putExtra("msgPersons", msgPersons);x0dx0aintent.setAction(Constant.hasMsgUpdatedAction);x0dx0aintent.putExtra("userId", userId);x0dx0aintent.putExtra("msgCount", messages.size());x0dx0asendBroadcast(intent);
❹ Android系統廣播(Broadcast)注冊,發送,接收流程解析
以下廣播簡稱Broadcast
是Android四大組件之一,在四大組件的另外兩個組件 和 擁有發送和接收廣播的能力。Android 是在 進程間通信機制的基礎上實現的,內部基於消息發布和訂閱的事件驅動模型,廣播發送者負責發送消息,廣播接收者需要先訂閱消息,然後才能收到消息。 進程間通信與 的區別在於:
有三種類型
存在一個注冊中心,也可以說是一個調度中心,即 。廣播接收者將自己注冊到 中,並指定要接收的廣播類型;廣播發送者發送廣播時,發送的廣播首先會發送到 , 根據廣播的類型找到對應的 ,找到後邊將廣播發送給其處理。
這里以普通廣播為例子, 接收者有兩種注冊方式,一種是 ,一種是 :
(廣播的發送分為 兩種,這里針對有序的廣播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用來設置廣播接收者的優先順序,默認都是0 , 范圍是[-1000, 1000],值越大優先順序越高,優先順序越高越早收到。
在相同優先順序接收同個類型廣播時, 的廣播接收器比 的廣播接收者更快的接收到對應的廣播,這個之後會進行分析。
註:以下源碼基於rk3399_instry Android7.1.2
的流程可分為 , 和 三個部分,這里依次分析下
在Android系統的 機制中,前面提到, 作為一個注冊和調度中心負責注冊和轉發 。所以 的注冊過程就是把它注冊到 的過程。
這里我們分析 廣播的過程, 和 有一個共同的父類 ,所以它們對應的注冊過程其實是調用 ,接下來我們按照流程逐步分析調用流程的源碼。
frameworks/base/core/java/android/content/ContextWrapper.java
在之前的 Android應用程序啟動入口ActivityThread.main流程分析 分析過,在我們啟動 Activity 時會創建一個 對象,然後通過 傳給我們啟動的 ,其內部就會將該對象賦值給 ; 的 方法也是類似的賦值流程,這里放個簡易的源碼應該更好理解
可以看到最後都會將生成的 對象賦值給對應的
對象。接下來繼續分析 , 即 函數。
/frameworks/base/core/java/android/app/ContextImpl.java
這里我們首先看下如何將廣播接收者 封裝成一個 介面的 本地對象
/frameworks/base/core/java/android/app/LoadedApk.java
每一個注冊過廣播接收者的 或 組件在<font color='Crimson'> LoadedApk </font>類中都有個對應的 對象,該對象負責將 與 組件關聯起來。這些對象,以關聯的 作為關鍵字保存在一個 中。之後對應的 又以 的 作為關鍵字保存在 的成員變數 對象中。最後通過 對應的 方法獲得其 介面的 本地對象。之後再回到 注冊方法內,將 對象發給 進行注冊。
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
在的 或 注冊一個 時,並不是將其注冊到<font color='OrangeRed'>AMS</font>中,而是將與它關聯的<font color='OrangeRed'>InnerReceiver</font>對象注冊到<font color='OrangeRed'>AMS</font>中,當<font color='OrangeRed'>AMS</font>接收到廣播時,會根據 在內部找到對應的<font color='OrangeRed'>InnerReceiver</font>對象,然後在通過這個對象將這個廣播發送給對應的 處理。
注冊過程這邊畫了一個簡單的流程圖:
<font color='OrangeRed'>Broadcast</font>的發送過程可簡單描述為以下幾個過程:
frameworks/base/core/java/android/content/ContextWrapper.java
/frameworks/base/core/java/android/app/ContextImpl.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
❺ Android 使用廣播系統解決app開機自啟動問題
關注 【網羅開發】微信公眾號,回復【160】便可領取。
網羅天下方法,方便你我開發 ,更多Android技術干貨等待領取,所有文檔會持續更新,歡迎關注一起成長!
總結一下使用ACTION_BOOT_COMPLETED的廣播,解決app開機自啟動的問題
1.首先在你的工程上建一個廣播接受的類,繼承BroadcastReceiver:
2.然後要在AndroidManifest.xml中加入許可權和配置相關信息:
3.在application標簽中,配置以下相關信息:
補充說明:
1.查看系統中是否安裝了類似360管家的軟體,為了加快開機速度,默認是關閉掉開機廣播的,只需要在設置中打開即可。
2.如果監聽不到廣播,可以嘗試同時監聽廣播和sd卡。
3.同時監聽廣播和sd卡,在application標簽中,配置以下相關信息:
❻ 22 AndroidBroadcast廣播機制
廣播(Broadcast)機制用於進程/線程間通信,廣播分為廣播發送和廣播接收兩個過程,其中廣播接收者BroadcastReceiver便是Android四大組件之一。
BroadcastReceiver分為兩類:
從廣播發送方式可分為三類:
廣播在系統中以BroadcastRecord對象來記錄, 該對象有幾個時間相關的成員變數.
廣播注冊,對於應用開發來說,往往是在Activity/Service中調用 registerReceiver() 方法,而Activity或Service都間接繼承於Context抽象類,真正幹活是交給ContextImpl類。另外調用getOuterContext()可獲取最外層的調用者Activity或Service。
[ContextImpl.java]
其中broadcastPermission擁有廣播的許可權控制,scheler用於指定接收到廣播時onRecive執行線程,當scheler=null則默認代表在主線程中執行,這也是最常見的用法
[ContextImpl.java]
ActivityManagerNative.getDefault()返回的是ActivityManagerProxy對象,簡稱AMP.
該方法中參數有mMainThread.getApplicationThread()返回的是ApplicationThread,這是Binder的Bn端,用於system_server進程與該進程的通信。
[-> LoadedApk.java]
不妨令 以BroadcastReceiver(廣播接收者)為key,LoadedApk.ReceiverDispatcher(分發者)為value的ArrayMap 記為 A 。此處 mReceivers 是一個以 Context 為key,以 A 為value的ArrayMap。對於ReceiverDispatcher(廣播分發者),當不存在時則創建一個。
此處mActivityThread便是前面傳遞過來的當前主線程的Handler.
ReceiverDispatcher(廣播分發者)有一個內部類 InnerReceiver ,該類繼承於 IIntentReceiver.Stub 。顯然,這是一個Binder服務端,廣播分發者通過rd.getIIntentReceiver()可獲取該Binder服務端對象 InnerReceiver ,用於Binder IPC通信。
[-> ActivityManagerNative.java]
這里有兩個Binder服務端對象 caller 和 receiver ,都代表執行注冊廣播動作所在的進程. AMP通過Binder驅動將這些信息發送給system_server進程中的AMS對象,接下來進入AMS.registerReceiver。
[-> ActivityManagerService.java]
其中 mRegisteredReceivers 記錄著所有已注冊的廣播,以receiver IBinder為key, ReceiverList為value為HashMap。
在BroadcastQueue中有兩個廣播隊列mParallelBroadcasts,mOrderedBroadcasts,數據類型都為ArrayList<broadcastrecord style="box-sizing: border-box;">:</broadcastrecord>
mLruProcesses數據類型為 ArrayList<ProcessRecord> ,而ProcessRecord對象有一個IApplicationThread欄位,根據該欄位查找出滿足條件的ProcessRecord對象。
該方法用於匹配發起的Intent數據是否匹配成功,匹配項共有4項action, type, data, category,任何一項匹配不成功都會失敗。
broadcastQueueForIntent(Intent intent)通過判斷intent.getFlags()是否包含FLAG_RECEIVER_FOREGROUND 來決定是前台或後台廣播,進而返回相應的廣播隊列mFgBroadcastQueue或者mBgBroadcastQueue。
注冊廣播:
另外,當注冊的是Sticky廣播:
廣播注冊完, 另一個操作便是在廣播發送過程.
發送廣播是在Activity或Service中調用 sendBroadcast() 方法,而Activity或Service都間接繼承於Context抽象類,真正幹活是交給ContextImpl類。
[ContextImpl.java]
[-> ActivityManagerNative.java]
[-> ActivityManagerService.java]
broadcastIntent()方法有兩個布爾參數serialized和sticky來共同決定是普通廣播,有序廣播,還是Sticky廣播,參數如下:
broadcastIntentLocked方法比較長,這里劃分為8個部分來分別說明。
這個過程最重要的工作是:
BroadcastReceiver還有其他flag,位於Intent.java常量:
主要功能:
這個過主要處於系統相關的10類廣播,這里不就展開講解了.
這個過程主要是將sticky廣播增加到list,並放入mStickyBroadcasts裡面。
其他說明:
AMS.collectReceiverComponents :
廣播隊列中有一個成員變數 mParallelBroadcasts ,類型為ArrayList<broadcastrecord style="box-sizing: border-box;">,記錄著所有的並行廣播。</broadcastrecord>
動態注冊的registeredReceivers,全部合並都receivers,再統一按串列方式處理。
廣播隊列中有一個成員變數 mOrderedBroadcasts ,類型為ArrayList<broadcastrecord style="box-sizing: border-box;">,記錄著所有的有序廣播。</broadcastrecord>
發送廣播過程:
處理方式:
可見不管哪種廣播方式,都是通過broadcastQueueForIntent()來根據intent的flag來判斷前台隊列或者後台隊列,然後再調用對應廣播隊列的scheleBroadcastsLocked方法來處理廣播;
在發送廣播過程中會執行 scheleBroadcastsLocked 方法來處理相關的廣播
[-> BroadcastQueue.java]
在BroadcastQueue對象創建時,mHandler=new BroadcastHandler(handler.getLooper());那麼此處交由mHandler的handleMessage來處理:
由此可見BroadcastHandler採用的是」ActivityManager」線程的Looper
[-> BroadcastQueue.java]
此處mService為AMS,整個流程還是比較長的,全程持有AMS鎖,所以廣播效率低的情況下,直接會嚴重影響這個手機的性能與流暢度,這里應該考慮細化同步鎖的粒度。
❼ android 之廣播機制
Android 中的廣播主要可以分為兩種類型:標准廣播和有序廣播
一種完全非同步執行的廣播,在廣播發出之後,所有的BroadcastReceiver幾乎會在同一時刻收到這條廣播消息,因此它們之間沒有任何先後順序可言。這種廣播的效率會比較高,但同時也意味著它是無法被截斷
標准廣播工作示意圖:
一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個BroadcastReceiver能夠收到這條廣播消息,當這個BroadcastReceiver中的邏輯執行完畢後,廣播才會繼續傳遞。所以此時的BroadcastReceiver是有先後順序的,優先順序高的BroadcastReceiver就可以先收到廣播消息,並且前面的BroadcastReceiver還可以截斷正在傳遞的廣播,這樣後面的BroadcastReceiver就無法收到廣播消息了
有序廣播工作示意圖:
可以讓程序在未啟動的情況下接收廣播
在Android 8.0系統之後,所有隱式廣播都不允許使用靜態注冊的方式來接收了。隱式廣播指的是那些沒有具體指定發送給哪個應用程序的廣播,大多數系統廣播屬於隱式廣播,但是少數特殊的系統廣播目前仍然允許使用靜態注冊的方式來接收,詳見網址: https://developer.android.google.cn/guide/components/broadcast-exceptions.html
在 AndroidManifest.xml 文件中注冊
在 AndroidManifest.xml 文件中進行許可權聲明
不要在 onReceive() 方法中添加過多的邏輯或者進行任何的耗時操作,因為BroadcastReceiver中是不允許開啟線程的,當 onReceive() 方法運行了較長時間而沒有結束時,程序就會出現錯誤
先定義一個BroadcastReceiver來准備接收此廣播
在 AndroidManifest.xml 文件中注冊
有序廣播是一種同步執行的廣播,並且是可以被截斷的。為了驗證這一點,我們需要再創建一個新的BroadcastReceiver。新建AnotherBroadcastReceiver
同樣,在 AndroidManifest.xml 文件中注冊,同時,使用 intent-filter 標簽的 android:priority 屬性設置優先順序
前面的 AnotherBroadcastReceiver 的優先順序比較高,因此 AnotherBroadcastReceiver 一定比 MyBroadcastReceiver 先收到廣播,因此,可以在 AnotherBroadcastReceiver 的 onReceive 方法中使用 abortBroadcast() 方法截斷廣播,這樣 MyBroadcastReceiver 就收不到該廣播了
在界面上彈出一個對話框,讓用戶無法進行任何其他操作,必須點擊對話框中的「確定」按鈕,關閉所有的Activity,然後回到登錄界面即可
ActivityCollector 類用於管理所有的Activity,具有關閉所有Activity的功能
創建 BaseActivity 類作為所有 Activity 的父類,並在裡面實現強制下線功能,在這里實現此功能,有以下幾點原因
創建一個LoginActivity來作為登錄界面
activity_login.xml
LoginActivity 如果輸入 123 就到 MainActivity界面
MainActivity 中點擊強制下線按鈕,就發送強制下線的廣播
MainActivity 布局
❽ Android BroadcastReceiver詳解
BroadcastReceiver(廣播接收器)是Android四大組件之一,顧名思義,通過廣播的方式進行消息傳遞,其本質是一個全局的監聽器,可以監聽到各種廣播,可以用來實現不同組件之間的通信。廣播最大的特點就是發送方並不關心接收方是否接到數據,也不關心接收方是如何處理數據的,通過這樣的形式來達到接、收雙方的完全解耦合。
又稱無序廣播,這種廣播完全是非同步的,所有與廣播Intent匹配的BroadcastReceiver,都可以收到這條廣播,並且不分先後順序,視為同時收到,通過Context.sendBroadcast()方法發送。這種廣播的效率比較高,但缺點是接收器不能將處理結果傳遞給下一個接收器,並且無法在中途終止廣播。
這是一種同步執行的廣播,通過Context.sendOrderedBroadcast()方法發送,這種廣播發出後,通過receiver的intent-filter中的android:priority屬性來設置優先順序,優先順序從-1000~1000,數越大,優先順序越高,使用setResult()方法把結果傳遞給下一個接收者,通過getResult()方法獲取上一個接收者傳遞過來的結果,並可以通過abortBroadcast()方法丟棄該廣播,使該廣播不再傳遞給下一個接收者。
粘性廣播通過Context.sendStickBroadcast()方法來發送,用此方法發送的廣播會一直滯留,當有匹配此廣播的接收器被注冊後,該廣播接收器就會收到此廣播。使用此廣播時,需要獲得BROADCAST_STICKY許可權。(在 android 5.0/api 21後不再推薦使用)
Android系統中內置了多個系統廣播,只要涉及到手機的基本操作,基本上都會發出相應的系統廣播。如:開啟啟動,網路狀態改變,拍照,屏幕關閉與開啟,點亮不足等等。每個系統廣播都具有特定的intent-filter,其中主要包括具體的action,系統廣播發出後,將被相應的BroadcastReceiver接收。系統廣播在系統內部當特定事件發生時,有系統自動發出。
以上廣播都屬於全局廣播,發出去的廣播,只要有匹配的接收者,就可以收到廣播。這樣一來會造成一些問題,一是消耗性能,二是容易引起安全性的問題,為了能夠簡單的解決這方面的問題,Android引入了一套廣播本地廣播機制,使用該機制發出的廣播只能夠在本應用內部進行傳遞,並且廣播接收器也只能接收來自本應用發出的廣播。
使用方法
1.注冊本地廣播接收器
2.發送本地廣播
3.注銷本地廣播接收器
本文用到的BroadcastReceiver
Android 8.0(API級別26)取消大部分靜態注冊廣播,建議使用動態廣播
https://developer.android.google.cn/about/versions/oreo/android-8.0
❾ android 廣播機制(2) 粘性廣播
android的粘性廣播,是指廣播接收器一注冊馬上就能接收到廣播的一種機制,當然首先系統要存在廣播。而普通廣播就是要先注冊廣播接收器,然後廣播被發送到系統,廣播接收器才能接收到廣播。
所以他們的區別是:
粘性廣播調用registerReceiver能馬上接受廣播,而普通廣播不行。
對於粘性廣播:
1.系統首先存在粘性廣播
2.注冊廣播接收器
3.處理廣播
下面用一個例子展示下他們的區別
主Acitivity
布局
布局有兩個按鈕,一個是注冊粘性廣播,一個是注冊普通廣播。點擊注冊粘性廣播按鈕會馬上返回結果。而點擊注冊普通廣播按鈕則沒有反應