當前位置:首頁 » 安卓系統 » android動態廣播

android動態廣播

發布時間: 2023-02-12 17:05:17

『壹』 Android開發中怎麼把廣播中處理後的信息傳遞給Activity

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

『貳』 Android 動態廣播 和 靜態廣播的區別

同一優先順序的廣播接收器,動態的要比靜態注冊的早。 動態注冊:即由代碼注冊的廣播接收器靜態注冊:即在 AndroidManifest.xml 中注冊的廣播接收器 優先順序: 當廣播為有序發送的時候,要按這個排序並順序發送。 sendBroadcast 發送的是無序廣播。sendOrderedBroadcast 發送的是有序廣播。 好了,現在尋找問題原因,在找原因前肯定有這樣的想法,一個有序隊列,既然允許有相同的優先順序存在,那麼在同優先順序內要不然有排序子因素,要不基就是按照某種操作可能影響順序。後者可能性很大。 打開源碼,順著 動態注冊廣播接受器 找,最後是 ActivityManagerService.java 這個文件找到了 registerReceiver 的實現。同地也看到,存儲的廣播接收器列表是 HashMap mRegisteredReceivers 這個變理。 裡面有一段代碼為: ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, Binder.getCallingPid(), Binder.getCallingUid(), receiver); if (rl.app != null) { rl.app.receivers.add(rl); } else { try { receiver.asBinder().linkToDeath(rl, 0); } catch (RemoteException e) { return sticky; } rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); } 在裡面查找有沒有這個 Receiver , 如果沒有 put 進去。 看到這里貌似沒有對廣播的順序做處理。是不是有別的地方做排序呢,找找成員變理,發現一個可疑的變數:final ArrayList mOrderedBroadcasts沒錯,感覺就應該是它了。 找找對它的操作,只有一處 mOrderedBroadcasts.set ,把代碼摘錄一下: BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, sticky, false); mOrderedBroadcasts.set(i, r);在這里放入了一個 BroadcastRecord 對像,而這個對像中主要的東西其實是 receivers向上跟蹤 int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; while (it < NT && ir < NR) { if (curt == null) { curt = (ResolveInfo)receivers.get(it); } if (curr == null) { curr = registeredReceivers.get(ir); } if (curr.getPriority() >= curt.priority) { // Insert this broadcast record into the final list. receivers.add(it, curr); ir++; curr = null; it++; NT++; } else { // Skip to the next ResolveInfo in the final list. it++; curt = null; } } 發現了一段 對 receivers 排序的代碼,並且判斷也是 priority 的值,用的是 >= 方式 感覺的找到了地方,但是對 Activity Manager Service 這個模塊卻更加的不懂了,以後有機會一定要分析一下這塊是怎樣設計的,才能確定本文的問題所在。暫時記錄,以後分析!

『叄』 Android廣播阻塞、延遲問題

        最近項目中,多次碰到app研發人員反饋廣播從發送到接收器接收,間隔時間太長,要求系統進行優化,特別是開機階段。對此,專門閱讀了一下廣播從發送到接收這個流程的源碼,以徹底搞明白怎樣讓自己發送的廣播盡快到達接收器。

涉及到的源碼類不多,主要就是ActivityManagerService.java 和 BroadcastQueue.java。發送廣播進程調用發送介面,通過IPC到達AMS,AMS根據Intent是否配置Intent.FLAG_RECEIVER_FOREGROUND,選擇當前廣播加入前台廣播隊列還是後台廣播隊列。根據當前廣播是否有序,將廣播加入廣播隊列的串列列表還是並行列表。廣播隊列和廣播隊列中的廣播列表是影響廣播接收時間的主要因素。

BroadcastQueue廣播隊列,負責將廣播發送給廣播接收器。AMS中有兩個成員變數, 

BroadcastQueue mFgBroadcastQueue;//前台廣播隊列

BroadcastQueue mBgBroadcastQueue;//後台廣播隊列

前台廣播隊列和後台廣播隊列的區別有兩處:1 超時時間,前台10s,後台60s. 2 是否延遲廣播等待前一個廣播進程完成。這兩個區別已經說明前台廣播對廣播接收器要求更高,響應時間更短,如果廣播要排隊,時間上前台廣播更短。同時系統默認使用後台廣播隊列,所以前台廣播隊列處理的廣播要少,避免了可能的大量廣播排隊情況。

廣播隊列中的列表

//存放無序並發送給動態廣播接收器的廣播任務

final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();

//存放無序發送給靜態廣播接收器的廣播任務或者存放有序廣播任務

final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();

mParallelBroadcasts 此列表中存放的是無序廣播動態廣播接收器任務,廣播隊列會在處理任務時通過嵌套循環,把每個廣播通過ipc發送到關注它的所有進程。所有無序廣播+動態廣播接收器,廣播不需要排隊。這種情況是最快能讓廣播到達目標進程的方式。

mOrderedBroadcasts存放的廣播任務特點:廣播有序,或者廣播接收器是靜態注冊的。此種類型的廣播全部要在mOrderedBroadcasts中排隊,廣播之間按時間先後,同一個廣播不同廣播接收器按優先順序。mOrderedBroadcasts存放的廣播必須等一個廣播任務處理完畢才能處理下一個,中間可能包含進程的啟動等。

由此可見,廣播最快的情況是前台廣播、無序廣播、動態注冊廣播接收器。最糟糕的情況是:後台廣播、有序或靜態注冊廣播接收器、廣播接收器優先順序低。如果一個應用只是簡單的靠注冊一個靜態廣播接收器拉起進程,對應的正是最糟糕的情況。如果又發生在開機階段,自然延遲嚴重。

如果必須注冊靜態廣播接收器,縮短時間的辦法為:配置Intent.FLAG_RECEIVER_FOREGROUND,加入前台廣播隊列,設置廣播優先順序

源碼:

廣播發送:Context .sendBroadcast ->ActivityManagerNative.broadcastIntent->ActivityManagerService.broadcastIntent->ActivityManagerService.broadcastIntentLocked.到此階段,跟發送廣播的進程通信結束。此階段AMS完成的工作主要是根據Intent查找該廣播對應的動態廣播接收器、靜態廣播接收器、以此發送該廣播使用的廣播隊列。

private final int broadcastIntentLocked(

......//許可權檢查

......//特殊系統廣播進行必要處理

if (sticky) {//粘性廣播處理

......

//查找靜態注冊的接收器

receivers = collectReceiverComponents(intent, resolvedType, users);

if (intent.getComponent() == null) {

    // 查找動態廣播接收器

            registeredReceivers = mReceiverResolver.queryIntent(intent,

                    resolvedType, false, userId);

        }

//動態廣播接收器

        int NR = registeredReceivers != null ? registeredReceivers.size() : 0;

        if (!ordered && NR > 0) { 

//確定隊列

            final BroadcastQueue queue = broadcastQueueForIntent(intent);

//創建廣播任務BroadcastRecord

            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                    callerPackage, callingPid, callingUid, resolvedType, requiredPermission,

                    appOp, registeredReceivers, resultTo, resultCode, resultData, map,

                    ordered, sticky, false, userId);

......

//廣播任務加入並行列表中

                queue.(r);

//啟動非同步發送廣播任務

                queue.scheleBroadcastsLocked();

registeredReceivers = null;

            NR = 0;

......

while (it < NT && ir < NR) {

......

//根據優先順序排序

          if (curt == null) {

                    curt = (ResolveInfo)receivers.get(it);

                }

                if (curr == null) {

                    curr = registeredReceivers.get(ir);

                }

                if (curr.getPriority() >= curt.priority) {

                    // Insert this broadcast record into the final list.

                    receivers.add(it, curr);

//獲取廣播隊列

            BroadcastQueue queue = broadcastQueueForIntent(intent);

//創建廣播任務

            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

                    callerPackage, callingPid, callingUid, resolvedType,

                    requiredPermission, appOp, receivers, resultTo, resultCode,

                    resultData, map, ordered, sticky, false, userId);

//加入到廣播隊列串列列表中

                queue.enqueueOrderedBroadcastLocked(r);

//啟動非同步發送任務

                queue.scheleBroadcastsLocked();

廣播隊列處理廣播:

final void processNextBroadcast(boolean fromMsg) {

......

//並行列表,遍歷廣播任務

            while (mParallelBroadcasts.size() > 0) {

final int N = r.receivers.size();

//遍歷接收器

                for (int i=0; i<N; i++) {

//IPC調用發送給目標進程

(r, (BroadcastFilter)target, false);

}

}

//有串列廣播任務正在執行

if (mPendingBroadcast != null) {

             //接收廣播的目標進程正常

                if (!isDead) {

                    // It's still alive, so keep waiting 繼續等待目前進程反饋

                    return;

                }

}

             //取出第一個廣播

                r = mOrderedBroadcasts.get(0);//判斷是否超時,

                    if ((numReceivers > 0) && 

                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {

                         //廣播超時

                          broadcastTimeoutLocked(false);//超時處理,終止當前廣播,啟動下一個任務。

                          }

                if (r.receivers == null || r.nextReceiver >= numReceivers

                        || r.resultAbort || forceReceive) {

                 //所有廣播任務執行完畢

}

int recIdx = r.nextReceiver++;//下一個廣播接收器

r.dispatchTime = r.receiverTime;//設置派發時間

setBroadcastTimeoutLocked(timeoutTime);//啟動超時計時

if (nextReceiver instanceof BroadcastFilter){//動態廣播接收器

(r, filter, r.ordered);//發送

return;

}

.//靜態廣播

            ResolveInfo info =

                (ResolveInfo)nextReceiver;

......

//檢查進程是否已啟動

            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,

                    info.activityInfo.applicationInfo.uid, false);

            if (app != null && app.thread != null) { /進程啟動

               processCurBroadcastLocked(r, app);//發送靜態廣播

               return;

            }

     if ((r.curApp=mService.startProcessLocked(targetProcess,//啟動進程

                    info.activityInfo.applicationInfo, true,

                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,

                    "broadcast", r.curComponent,

                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))

                            == null) {

                      //進程啟動失敗

                  }

             //標志正在發送的串列廣播

            mPendingBroadcast = r;

            mPendingBroadcastRecvIndex = recIdx;//正在發送的廣播任務對應的接收器索引

}

『肆』 Android動態注冊鎖屏、解鎖、開屏系統廣播

先自定義一個廣播類

然後在Application中進行動態注冊

因為是動態注冊所以無需在AndroidManifest.xml中進行注冊

『伍』 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 注冊的靜態廣播和動態廣播的區別

1.動態注冊廣播不是常駐型廣播,也就是說廣播跟隨activity的生命周期。注意: 在activity結束前,移除廣播接收器。
靜態注冊是常駐型,也就是說當應用程序關閉後,如果有信息廣播來,程序也會被系統調用自動運行。
它的生命周期為從回調onReceive()方法開始到該方法返回結果後結束。
2.當廣播為有序廣播時:
1 優先順序高的先接收
2 同優先順序的廣播接收器,動態優先於靜態
3 同優先順序的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先注冊的優先於後注冊的。

『柒』 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動態廣播(Android8.0)

   (a).動態注冊             在UI中注冊的廣播,例如:

  (b).靜態注冊             

   需要在manifest中進行注冊(在安卓8.0後系統廢除了大部分靜態廣播,最好使用動態注冊)。

 (a).系統廣播             

   系統中已經定義的廣播,此類廣播只能由系統發出,並且需要在intent-filter中加上系統已經寫的action。             

  (b).自定義廣播         

    顧名思義,是用戶自己定義的廣播。

 (a)我們首先需要一個廣播接收類                                     

(b)其次注冊動態廣播

(c)最後需要通過send方法發送一個廣播供廣播接收者接受

另外還有有序廣播和無序廣播,這篇博客寫的比較詳細,供大家參考: Android的有序廣播和無序廣播(解決安卓8.0版本之後有序廣播的接收問題) - ming3 - 博客園 (cnblogs.com)

『玖』 說說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 中如何在server 中動態注冊廣播。

在Service中的onStartCommand中動態注冊廣播。
如下代碼:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK); //注冊IntentFilter
filter.setPriority(Integer.MAX_VALUE); //設置級別
receiver = new AppReceiver();//本地服務
registerReceiver(receiver, filter);//注冊廣播

return START_STICKY;
}

廣播代碼:
package com.sevencolorbox.sdk.service;

import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AppReceiver extends BroadcastReceiver{

private boolean isServiceRunning = false;
private String serviceName = "com.sevencolorbox.sdk.service.SevenColorService";
@Override
public void onReceive(Context context, Intent intent) {

if (intent.getAction().equals(Intent.ACTION_TIME_TICK)){

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> infos = am.getRunningServices(Integer.MAX_VALUE);

for (RunningServiceInfo info : infos) {

if (info.service.getClassName().equals(serviceName)) {

isServiceRunning = true;
}
}
if (!isServiceRunning) {

Log.i("ss", "本地服務未開啟");
Intent tIntent = new Intent(context,SevenColorService.class);
context.startService(tIntent);
}
}
}
}

熱點內容
破解exe加密視頻 發布:2025-05-17 11:23:41 瀏覽:976
我的世界伺服器圈太大了怎麼辦 發布:2025-05-17 11:15:21 瀏覽:614
便宜的免費雲伺服器 發布:2025-05-17 11:08:50 瀏覽:777
中國頂級dhcp解析伺服器地址 發布:2025-05-17 11:06:27 瀏覽:34
php轉義html 發布:2025-05-17 11:04:00 瀏覽:567
鋼筋籠加密區規范 發布:2025-05-17 10:59:50 瀏覽:4
我的世界網易手機版主播伺服器房號 發布:2025-05-17 10:40:59 瀏覽:227
豎編譯 發布:2025-05-17 09:56:08 瀏覽:229
編程畫飛機 發布:2025-05-17 09:54:03 瀏覽:803
手機如何解鎖密碼屏幕鎖怎麼刪除 發布:2025-05-17 09:52:04 瀏覽:125