⑴ 動態廣播和靜態廣播的區別和用法
兩種廣播有如下區別:
生存期,靜態廣播的生存期可以比動態廣播的長很多,因為靜態廣播很多都是用來對系統時間進行監聽,比如我們可以監聽手機開機。而動態廣播會隨著context的終止而終止
優先順序動態廣播的優先順序比靜態廣播高
動態廣播無需在androidManifest.xml中聲明即可直接使用,也即動態;而靜態廣播則需要,有時候還要在AndroidManifest.xml中加上一些許可權的聲明
⑵ Android 第六講 廣播接收器和服務
兩種方式:靜態注冊和動態注冊
動態注冊:
1)動態注冊:需要定義一個繼承自BroadcastReceiver類的子類,該接收器需要在Activity中的onDestroy中注銷
2)靜態注冊:通過在AndroidManifest.xml中配置
兩種廣播形式:有序廣播和無序廣播
1)無序廣播:接受標准廣播的接收器將同時收到廣播消息,非同步執行,沒有先後順序 sendBroadCast
2)有序廣播:sendOrderedBroadCast,按照一定順序先後被接受順序,由priority屬性決定,abortBroadCast中斷廣播
如果只想在本應用中發送和接受廣播,使用LocalBroadcastReceiver來對廣播進行管理
本地廣播不支持靜態注冊
優點 :安全高效
Service是Android中的一種組件,和Activity的級別一致,但不能自己運行,只能後台運行,和其他組件交互,服務必須注冊才能使用
本地服務:服務依附在主線程中,節約資源,主線程死掉服務終止
遠程服務:服務在獨立進程中,靈活性好 ,佔用資源高
兩種服務的啟動模式:
1)start方式:調用者和服務之間沒有關聯,調用者退出不會影響服務,startService啟動服務,如果服務不存在,調用onCreat方法,然後onStartCommand被調用。stopService關閉服務,onDestroy方法被調用
2)bind方式:調用者和服務綁定,調用者退出,服務終止bindService啟動服務,onCreate方法創建服務,onBind方法綁定服務,onUnbind方法解綁,onDestory在服務結束時調用
⑶ 廣播兩種注冊方式的區別
BroadcastReceiver是Android四大組件之一,主要用於接收系統廣播和其他應用程序的廣播。
BroadcastReceiver的使用非常簡單
寫一個類繼承BroadcastReceiver
注意onReceive是主線程不要做耗時操作否則阻塞10s會ANR
注冊廣播(靜態注冊)
動態注冊
動態注冊的廣播一定要再適當的時機調用 unregisterReceiver();解除注冊。
發送廣播
兩種注冊方式的區別
1.動態注冊的廣播是非常駐型廣播,此時廣播是跟隨宿主的生命周期的,宿主不在了廣播也就不在了。
2.靜態注冊的廣播是常駐型廣播,即應用程序關閉後,依然能夠收到廣播。
⑷ 為什麼Android要使用各種BroadcastReceiver
作為Android四大組件之一的BroadcastReceiver(廣播接收者),同Activity(活動)一樣,經常被大家用到,網上也是一堆對它的講解,那麼為什麼Android要用廣播接收者這種機制呢?
廣播分為:普通廣播和有序廣播
1.Normal broadcasts(普通廣播):Normal broadcasts是完全非同步的可以同一時間被所有的接收者接收到。消息的傳遞效率比較高。但缺點是接收者不能將接收的消息的處理信息傳遞給下一個接收者也不能停止消息的傳播。可以利用Context.sendBroadcast發送。
2.Ordered broadcasts(有序廣播):Ordered broadcasts的接收者按照一定的優先順序進行消息的接收。一次傳送到一個接收器。 隨著每個接收器依次執行,它可以將結果傳播到下一個接收器,或者它可以完全中止廣播,使得它不會被傳遞到其他接收器。 命令接收器運行可以用匹配的意圖過濾器的android:priority屬性控制; 具有相同優先順序的接收器將以任意順序運行。可以利用Context.sendOrderedBroadcast發送。
官網上介紹廣播是用的監聽系統網路狀況的例子,其實關鍵字在於「監聽」。
(1) 創建廣播接收者
BroadcastReceiver是一個抽象類,所以我們要創建自己的廣播接收者就要繼承它,繼承後會有提示重寫onReceive方法。
public class NetworkBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
if (activeNetwork != null && activeNetwork.isAvailable()) {
Toast.makeText(context, "有網路連接", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "無網路連接", Toast.LENGTH_SHORT).show();
}
}
}
}
廣播接收者的生命周期是從接收廣播開始,到onRecevier方法執行完成結束,時間很短,一般不允許處理大批量耗時操作。這里順便給出列印NetworkInfo的信息以供參考:
NetworkInfo:
type: WIFI[,type_ext: WIFI],
state: CONNECTED/CONNECTED,
reason: (unspecified),
extra: "TP-LINK_EFE8",
roaming: false,
failover: false,
isAvailable: true,
: false,
isIpv4Connected: true,
isIpv6Connected: false
[type: MOBILE[LTE],
state: CONNECTED/CONNECTED,
reason: connected,
extra: cmnet,
roaming: false,
failover: false,
isAvailable: true,
: false]
(2) 靜態注冊廣播
靜態注冊廣播,需要在AndroidManifest.xml中,添加<recevier/> 標簽,將廣播接收者注冊到應用中。要添加過濾器IntentFilter,由於系統網路變化時會發送ConnectivityManager.CONNECTIVITY_ACTION ("android.net.conn.CONNECTIVITY_CHANGE")的廣播,所以我們要監聽這條廣播。
<receiver android:name=".NetworkBroadcastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
這里priority代表的是執行順序的優先順序,取值[-1000,1000],後面的有序廣播會講到。
(3) 動態注冊廣播
i.意圖過濾器 IntentFilter 用於給BroadcastReceiver綁定監聽廣播類型
ii.自定義的BroadcastReceiver,例如上文的
iii.注冊方法 Context.registerReceiver(Receiver, IntentFilter)
iv.反注冊方法 unregisterReceiver(Receiver)
IntentFilter mFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver = new ();
registerReceiver(mReceiver, mFilter);
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
這段代碼是成對出現的,可以在onCreate的時候注冊,在onDestroy的時候反注冊,也可以在onResume和onPause中執行這寫方法。不過Google API推薦的做法,在activity的onResume()中注冊,在onPause()反注冊。效果是當界面pause時,就不接收廣播,從而減少不必要的系統開銷。還有就是一定要主動反注冊你的廣播,否則會出現異常。
動態注冊和靜態注冊的差別:動態注冊後,廣播接收者會依賴Activity的生命周期,而靜態注冊的廣播不會,只要是系統有發出的廣播,它都會接收,與程序是否啟動無關。
(4) 發送普通廣播
具體使用的方法是sendBroadcast(Intent intent),通過隱式調用就可以,注意action是你自定義的,意思就是不可以發送系統廣播,我試了,直接就崩了。
Intent intent = new Intent();
intent.setAction("com.fleming.chen.mybroadcast");
sendBroadcast(intent);
針對(3)(4)兩點,如果你要用到的廣播僅僅是應用里的,那麼你可以用LocalBroadcastManager這個類,它與上述描述中的區別在於:
LocalBroadcastManager.getInstance(context).registerReceiver(mReceiver, mFilter);
LocalBroadcastManager.getInstance(context).unregisterReceiver(mReceiver);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
通過sendBroadcast發送的廣播,不會被通過LocalBroadcastManager類注冊的廣播接收者接收,反之也是如此,兩者是不可以」互通友誼「的,推薦使用LocalBroadcastManager來管理廣播。
(5) 發送有序廣播
上面講了那麼多都是普通廣播,那什麼又是有序廣播呢?
有序廣播關鍵在於這類廣播是有序的,上文中提到priority,這是IntentFilter的屬性,用來讓不同的廣播擁有不同的執行順序,即優先順序不同。
定義三種不同優先順序的廣播接收者:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.fleming.chen.myreceiver")) {
String message = getResultData();
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
setResultData("這是修改後的數據");//第一個接收後處理一下,再交給下一個
}
}
}
public class MyBroadcastReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.fleming.chen.myreceiver")) {
String message = getResultData();//得到上一個的處理結果
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
abortBroadcast();//主動停止廣播,不再繼續傳下去
}
}
}
public class MyBroadcastReceiver3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.fleming.chen.myreceiver")) {
//此時雖然該廣播接收者也監聽了,不過也沒有內容
Toast.makeText(context, getResultData(), Toast.LENGTH_SHORT).show();
}
}
}
<receiver android:name=".MyBroadcastReceiver" >
<intent-filter android:priority="1000">
<action android:name="com.fleming.chen.myreceiver"/>
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver2">
<intent-filter android:priority="0">
<action android:name="com.fleming.chen.myreceiver"/>
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiver3">
<intent-filter android:priority="-1000">
<action android:name="com.fleming.chen.myreceiver"/>
</intent-filter>
</receiver>
Intent intent = new Intent();
intent.setAction("com.fleming.chen.myreceiver");
sendOrderedBroadcast(intent, null, null, null, 0, "這是初始的數據", null);
對於廣播的內容,在Android 7.0上做了修改,即Project Svelte:後台優化
Android 7.0 移除了三項隱式廣播,以幫助優化內存使用和電量消耗。此項變更很有必要,因為隱式廣播會在後台頻繁啟動已注冊偵聽這些廣播的應用。刪除這些廣播可以顯著提升設備性能和用戶體驗。
移動設備會經歷頻繁的連接變更,例如在 WLAN 和移動數據之間切換時。目前,可以通過在應用清單中注冊一個接收器來偵聽隱式 CONNECTIVITY_ACTION 廣播,讓應用能夠監控這些變更。由於很多應用會注冊接收此廣播,因此單次網路切換即會導致所有應用被喚醒並同時處理此廣播。
同理,在之前版本的 Android 中,應用可以注冊接收來自其他應用(例如相機)的隱式 ACTION_NEW_PICTURE 和 ACTION_NEW_VIDEO 廣播。當用戶使用相機應用拍攝照片時,這些應用即會被喚醒以處理廣播。
為緩解這些問題,Android 7.0 應用了以下優化措施:
面向 Android 7.0 開發的應用不會收到 CONNECTIVITY_ACTION 廣播,即使它們已有清單條目來請求接受這些事件的通知。在前台運行的應用如果使用 BroadcastReceiver 請求接收通知,則仍可以在主線程中偵聽 CONNECTIVITY_CHANGE。
應用無法發送或接收 ACTION_NEW_PICTURE 或 ACTION_NEW_VIDEO 廣播。此項優化會影響所有應用,而不僅僅是面向 Android 7.0 的應用。
如果您的應用使用任何 intent,您仍需要盡快移除它們的依賴關系,以正確適配 Android 7.0 設備。Android 框架提供多個解決方案來緩解對這些隱式廣播的需求。例如,JobScheler API 提供了一個穩健可靠的機制來安排滿足指定條件(例如連入無限流量網路)時所執行的網路操作。您甚至可以使用 JobScheler 來適應內容提供程序變化。
所以說,在Android的世界,到處都充滿著廣播,就是為了用來監聽手機的各種狀態,給用戶提醒,這是一種很好的用戶體驗,不過任何事情都是如此,廣播也不可以多用哦,
⑸ 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 這個模塊卻更加的不懂了,以後有機會一定要分析一下這塊是怎樣設計的,才能確定本文的問題所在。暫時記錄,以後分析!
⑹ Broadcast注冊方式與區別
Broadcast廣播,注冊方式主要有兩種
第一種是靜態注冊,也可成為常駐型廣播,這種廣播需要在Androidmanifest.xml中進行注冊,這中方式注冊的廣播,不受頁面生命周期的影響,即使退出了頁面,也可以收到廣播這種廣播一般用於想開機自啟動啊等等,由於這種注冊的方式的廣播是常駐型廣播,所以會佔用CPU的資源。
第二種是動態注冊,而動態注冊的話,是在代碼中注冊的,這種注冊方式也叫非常駐型廣播,收到生命周期的影響,退出頁面後,就不會收到廣播,我們通常運用在更新UI方面。這種注冊方式優先順序較高。最後需要解綁,否會會內存泄露
廣播是分為有序廣播和無序廣播。
⑺ Android注冊廣播有幾種方式,分別是什麼
注冊方式有兩種:
1、靜態注冊,就是在manifest文件里配置一下,這種方式注冊的廣播屬於系統級廣播。你的應用沒打開也能收到廣播。比如你要做一個收到某廣播就啟動你的應用的功能可以這樣搞。
2、動態注冊,在代碼里執行一個rigisterBroadcastReciver(可能拼寫有誤)的方法。這種你要自己作好反注冊。這種廣播可以做成你的應用啟動後才監聽,關閉後就不監聽的效果。