安卓廣播在哪個線程
⑴ android系統睡眠狀態如何喚醒線程和廣播
不能!
(不能手動喚醒,因為肯定需要點亮屏幕(手動點亮屏幕),所以並不是真睡眠狀態)。
只能提前設置,比如鬧鍾,具體到「廣播」即收音機,那麼只建議使用第三方程序,如「蜻蜓FM」,就像鬧鍾可以定時自動開啟。
如果是自己造,相當於重新編個程序出來,需要掌握大量專業性的東西,得不償失
⑵ Android可以讓主線程在其他子線程執行完後再執行嗎如果可以,該怎麼做
android中什麼時候會選擇用廣播來進行線程間的通信 Android 多線程 通信 線程中通信就不要用廣播了吧 進程中通信可以用廣播或者aidl 可是,這兩天看到的項目都是這么做的;然後,自己分析了下,覺得一下的理由也是可以成立的; 1.正常情況下我們選擇handler消息機制來進行單向的線程間的通信;(工作線程向主線程發送消息) 因為主線程有現成的handler,而工作線程沒有現成的handler,這樣的話,主線程將handler交給工作線程而讓工作線程將工作的結果交給主線程; 相反,工作線程中沒有現成的handler(事實上是沒有消息隊列,也就是handler沒有綁定到工作線程),那麼,如果開辟的話,代碼角度上是挺麻煩的(相對應廣播機制來說); 2.廣播機制本身就是雙向的(工作線程向主線程發送廣播,主線程向工作線程發送廣播); //另外,對於像一個activity中通過fragment來進行界面的處理; 我們大多數情況下是採用廣播的機制來實現fragment中adapter的數據的更新;這樣做主要是考慮到工作線程的任務載入完成,而具體的對應刷新的activity可能還沒有啟動; 另外,基於介面隔離原則,如果用handler進行通信的話,則不能很好的滿足這一原則; 你要是周期比較長 用廣播好些吧 應該與周期關系不是很密切。最主要的原因是兩條線成是雙向通信。 Handler類似於P2P的通信。 廣播則類似於一個server端,用來處理分發不同線程的請求,從控制器的角度來說用廣播更好一點。 一般使用Handler的,多用於子線程處理事務,完成時告知主線程這一類的情況。 而類似樓主所說的多條線程之間需要頻繁交互的話,廣播是個很好的選擇,並且結構清晰,只是不知道廣播的性能與handler相比會怎麼樣。
⑶ 安卓關於handler和broadcast的問題
可以在Thread裡面直接發送廣播 依據Android開發文檔中關於sendBroadcast方法的說明 http://developer.android.com/reference/android/content/Context.html#sendBroadcast(ndroid.content.Intent) 其中提到了是非同步的 就是說明這冊伍個發拿者送廣播的方法最終是通過系統的線程來完成的 而且還可以參考這里所說的 http://stackoverflow.com/questions/11656763/is-it-ok-to-call-sendbroadcast-from-another-thread
至於消姿薯與使用Handler的方式來做有什麼區別 可能我感覺到的就是一個是在worker線程中來完成 一個是在UI線程中來完成~
⑷ Android主線程到底是什麼
Android中關於主線程的理解:
Android的主線程是UI線程,在Android中,四大組件運行在主線程中,在主線程中做耗時操作會導致程序出現卡頓甚至出現ANR異常,一個基本常識就是將耗時操作放到子線程中去處理,然後通過Handler回調到主線程。
有三點還需要注意:
因為四大組件運行在一個主線程中,那麼若果當前界面在顯示的時候,後台的activity仍有處理邏輯再運行的話,仍然會造成當前界面的卡頓。
通過Handler回調到主線程只是避免程序出現ANR的第一步,必須要注意handler中邏輯處理的耗時,如果將很多消息都扔給了handler,那麼也會給主線程造成壓力,導致程序運行卡頓。
四大組件、Handler都是在一個線程中,那麼主線程在同一時刻不可能發送兩個廣播,換句話說就是若果能夠保證所有的廣播都是在主線程中發送,那麼廣播內部其實不需要加上對非同步操作的處理。
⑸ 簡述在android中如何發送廣播消息
1.發送廣播
Intent intent = new Intent(BroadcastAction);
Bundle bundle = new Bundle();
bundle.putString("***", SUCCESS);
bundle.putString("FullPathName", mFullPathName);
intent.putExtras(bundle);
sendBroadcast(intent);
2.在Activity中創建一個內部類MyBroadcastReceiver擴展BroadcastReceiver,並在其中實現onReceive方法。
3.在Activity中聲明一個MyBroadcastReceiver類型的成員變數,並注冊:
private MyBroadcastReceiver myBroadcastReceiver;
...
myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(BroadcastAction);
registerReceiver(receiver, filter);
4.使用完後要記得釋放
unregisterReceiver(receiver);
註:1和2中的 BroadcastAction要是同一個Action
⑹ 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中什麼時候會選擇用廣播來進行線程間的通信 Android 多線程 通信
線程中通信就不要用廣播了吧 進程中通信可以用廣播或者aidl
可是,這兩天看到的項目都是這么做的;然後,自己分析了下,覺得一下的理由也是可以成立的;
1.正常情況下我們選擇handler消息機制來進行單向的線程間的通信;(工作線程向主線程發送消息)
因為主線程有現成的handler,而工作線程沒有現成的handler,這樣的話,主線程將handler交給工作線程而讓工作線程將工作的結果交給主線程;
相反,工作線程中沒有現成的handler(事實上是沒有消息隊列,也就是handler沒有綁定到工作線程),那麼,如果開辟的話,代碼角度上是挺麻煩的(相對應廣播機制來說);
2.廣播機制本身就是雙向的(工作線程向主線程發送廣播,主線程向工作線程發送廣播);
//另外,對於像一個activity中通過fragment來進行界面的處理; 我們大多數情況下是採用廣播的機制來實現fragment中adapter的數據的更新;這樣做主要是考慮到工作線程的任務載入完成,而具體的對應刷新的activity可能還沒有啟動;
另外,基於介面隔離原則,如果用handler進行通信的話,則不能很好的滿足這一原則;
你要是周期比較長 用廣播好些吧
應該與周期關系不是很密切。最主要的原因是兩條線成是雙向通信。
Handler類似於P2P的通信。
廣播則類似於一個server端,用來處理分發不同線程的請求,從控制器的角度來說用廣播更好一點。
一般使用Handler的,多用於子線程處理事務,完成時告知主線程這一類的情況。
而類似樓主所說的多條線程之間需要頻繁交互的話,廣播是個很好的選擇,並且結構清晰,只是不知道廣播的性能與handler相比會怎麼樣。
⑻ android怎麼發送特定廣播的
起一個線程,每發一個廣播後就sleep一分鍾,如此循環。(或者接受系統的timechanged這個廣播,這個廣播好像一分鍾發一次)。
Android 在發送廣播時的方法 sendBroadcast(Intent)。
①:Intent myIntent = new Intent();——【創建Intent對象】
②:myIntent.setAction(String)——【設置一般的要執行的動作。參數:動作一個動作的名稱,如ACTION_VIEW。應用程序的具體行動,應與供應商的包名作為前綴。】
③:myIntent.putExtra(String,Object)——【廣播中額外發送的數據,String為自定義key,Object表示多種數據類型】
④:sendBroadcast(myIntent);——【發送廣播】
接收廣播
Android在接收廣播的方法是注冊一個廣播接收器 registerReceiver(MyReceiver,IntentFilter)。
①:首先創建MyReceiver類(類名自定義) 繼承 BroadcastReceiver類。——【創建廣播接收器】
②:在MyReceiver中重寫public void onReceive(Context context, Intent intent)方法。這個方法在接收到廣播後觸發。——【重寫處理方法】
③:在Activity或者Service啟動時 onCreate()、onStartCommand()等方法中實例化 MyReceiver類——【啟動時實例化廣播接收器】
④:IntentFilter filter = new IntentFilter();——【創建IntentFilter對象 意圖過濾器】
⑤:filter.addAction(String);——【在過濾器中加入過濾條件,說明接收什麼廣播】
⑥:registerReceiver(cmdReceiver, filter);——【注冊廣播,參數為(廣播接收器,意圖過濾器)】
⑼ android 怎樣發送廣播更新ui
更新ui 可以直接在主線程里操作。一般用不到廣播。如果非要用廣播,一般都是服務更新線程才這么做。在服務里注冊/發送廣播。然後在ui線程里接受廣播,執行更新操作。
⑽ Android高效安全的本地廣播LocalBroadcast完全解析
廣播作為Android 四大組件有非常廣泛的用途。廣播可以用作進程間通信,也會用作進程內部某些組件內消息的傳遞。
這就會有個問題,如果想讓發送的廣播只有我自己能收到,不想被別人劫持到,來獲取到廣播中的敏感信息。
另外其他人如果發送相同Action的廣播來偽造真正的廣播,就會欺騙我的receiver.
如何安全高效的實現進程內部的廣播發送呢?
有人說可以使用給廣播加許可權啊,你可以在Intent中指定PackageName 啊,後面的文章詳解,先簡單看下:
當然這都是書上告訴我們的方式,但是我感覺還不夠簡單。當然經過一番配置你可以實現了。
好了,現在安全解決了,那高效呢?
我們翻看context.sendBroadcast源碼,看到發送廣播的流程真的是相當的復雜啊。曾經天真年少的我竟然幻想一天弄懂廣播的整個過程,但當我看到sendBroadcast方法的行數時我臉上是大寫的崩潰。暫且不談廣播隊列的分發規則和過程。這中間是存在的兩次binder call就讓這個過程變的不是那麼高效。
首先你sendBroadcast會把廣播信息告訴System_server (第一次Binder call),然後system_server經過一番查看找到你要的receivers,然後進入分發隊列等待分發(過程很復雜),然後調用APP進程receiver的onReceiver()方法(第二次Binder call).大昌純物兄弟,我明明只想在我的進程內部發送一個廣播在進程內部接收,為啥還要通過system_server呢。就算你長得帥,你有Free style,可是你很忙啊,找你的人那麼多。自己的事情自己做,這是小學了老師經常教導我們的。看來Google的程序員一直沒有忘記小學老師的教誨:
看,邁著整齊步伐雄赳赳氣昂昂向我們走來的是LocalBroadcast:
先來看官方說明:
意思就是這個很牛褲做逼,和全局廣播相比有很多數不清的優勢。(看來實現這個的哥們和實現全局廣播的哥們關系不大好,竟然用這個詞語: has a number of advantages) 。
我們下面來看下LocalBroadcastManager的源碼:
https://android.googlesource.com/platform/frameworks/support/+/android-support-lib-19.1.0/v4/java/android/support/v4/content/LocalBroadcastManager.java
1.先來看下LocalBroadcastManager的構造,是使用標準的單例模式實現的。
APP開發者拿到mInstance之後就可以調用registerReceiver、unregisterReceiver、sendBroadcast。
看到構造函數中沒有做復雜的操作,在主線程初始化了一個Handler.
可以猜測到這個Handler正是用於對廣播的分發。
2.廣播的注冊、反注冊、發送流程
如果讓我們來自己來實現廣播的注冊、反注冊、發送我們會怎麼搞呢?
首先,注冊的時候需要提供BroadcastReceiver和對應的IntentFilter,我們可以對這種數據結構進行封裝,放到一個類中ReceiverRecord。
然後維護一個ReceiverRecord對象列表,用於記錄當前注冊了哪些BroadcastReceiver。可以簡單使用ArrayList<ReceiverRecord>.
在unRegister的時候根據提供的BroadcastReceiver對象,遍歷List找出對應的receiver進行移除。
這樣每來一個unRegister我們都需要對Receiver列表做一次遍歷,耐液開銷有點大,在查操作比較多的時候我們可以使用MAP。
HashMap<BroadCastReceiver, ReceiverRecord>
ReceiverRecord中已經包含BroadcastReceiver對象了,所以value直接使用IntentFilte就行了,簡化數據結構。
那如果一個Receiver注冊了多個IntentFilter呢?比如說一個receiver對象注冊兩次傳入不同的IntentFilter.所以Value需要改造為ArrayList<IntentFilter>。 最終用於維護當前Reciver對象列表的數據結構是這樣事兒的:
HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers .
當刪除時可以通過receiver對象為key在map中快速查找並移除。
發送廣播的時候呢?我們知道sendBroadcast時只傳入了Intent對象,Intent攜帶了Action用於和已經注冊的receiver匹配。在查找receiver時,需要對 HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers 的Value進行遍歷,每一個Value ArrayList<IntentFilter> 又需要遍歷一次。這個查找的開銷實在太大了。
看來我們為了實現Action和receiver的快速匹配需要再維護一個數據結構了。同樣是頻繁查找的需求使用HashMap.
將Action作為Key,value肯定是與之匹配的receiver了。因為一個Action可能會對應多個receiver,receiver注冊的時候可以使用相同的Action.所以value需要使用ArrayList<BroadcastReceiver>. 當發送廣播時可以快速根據Action找到對應的receiver。對了,不僅僅要使用Action匹配,filter中還有其他信息匹配成功之後才能確認是真正的receiver.所以需要使用ReceiverRecord作為value,因為不僅包含了receiver對象,同時包含了IntentFilter.所以最終的數據結構是 HashMap<String,ArrayList<ReceiverRecord>>.
我們來看Google是怎麼實現的呢?
先來看兩個內部類:
再來看幾個成員變數:
廣播的發送過程
廣播的反注冊過程
可以看到最終把要發送的廣播加入隊列mPendingBroadcasts,然後使用Handler發送消息給主線程處理的,調用executePendingBroadcasts()進行分發。
LocalBroadcast也支持使用同步的方式進行分發:
1.LocalBroadcast是APP內部維護的一套廣播機制,有很高的安全性和高效性。
所以如果有APP內部發送、接收廣播的需要應該使用LocalBroadcast。
2.Receiver只允許動態注冊,不允許在Manifest中注冊。
3.LocalBroadcastManager所發送的廣播action,只能與注冊到LocalBroadcastManager中BroadcastReceiver產生互動。