亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

安卓開發基礎篇——Anroid四大組件之Broadcast Receiver

2019-11-09 17:04:32
字體:
來源:轉載
供稿:網友

Broadcast Receiver——廣播接受者,用來監聽系統或者開發者開發的事件做出響應,比如說開機、電池電量的變化、網絡狀況的變化,客戶交互中發出的事件廣播,可以通過廣播接收并通知用戶。

一、廣播的功能與特征

1、廣播的生命周期很短,從context.sendBroadcast(Intent intent),Broadcast Receiver.onReceiver方法,廣播就結束生命周期。

2、與其他四大組件一樣,廣播也是在同一進程的主線程中完成,是同步并快速的,不推薦在廣播中新開子線程,因為往往子線程還未完成任務,廣播已經被銷毀,如果要進行耗時操作,最好通過intent啟動Service,在服務中進行耗時操作。

3、如果onReceiver方法10秒內沒有執行完畢任務,Android認為該程序沒反應。

二、廣播監聽的兩種方法

廣播監聽有靜態注冊和動態注冊(在實際開發中,動態注冊常用一些,靜態注冊也必不可少)。

靜態注冊,將廣播接收器的配置信息寫在應用的配置文件中(AndroidManifest.xml),當有廣播發生時,組件管理服務會從應用安裝包管理服務中獲取已經安裝的廣播組件信息。

動態注冊,Context.register,動態將廣播接收器與所需監聽的事件綁定起來。

1.靜態注冊——跟其他組件一樣,寫在AndroidManifest.xml文件中application標簽之內

<receiver android:name=".ColdReceiver"><!-- 你的Receiver名稱 -->     <intent-filter>        <action android:name="android.intent.action.COLD_BROADCAST"/>  <!-- 你廣播要接受的intent名稱 -->      <category android:name="android.intent.category.DEFAULT" />     </intent-filter>  </receiver>然后我們創建一個ColdReceiver類,繼承BroadcastRecevier類

public class ColdReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        //跳轉到service中        intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(1);        //開啟service        context.startService(intent);        //日志打印        Log.d("TEST","靜態注冊");    }}上面的Service啟動看到了嗎,這里我用了上次說過的快捷跳轉。其中service的配置和內容如下

<service android:name=".BroadcastService"><!-- 你自定義的service文件   (在<application></application>里面加)-->        <intent-filter>                <action android:name="android.intent.action.BroadcastService" /><!-- 用intent啟動時的快捷名(也可以用常規的方式啟動) -->                <category android:name="android.intent.category.default" />        </intent-filter>        </service>
public class BroadcastService extends Service{    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        return null;    }        @Override    public void onCreate() {        //開啟服務時會首先調用該方法        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        //根據每次intent傳過來的信息進行判斷來顯示不同信息        switch(intent.getFlags()){            case 1:{                Toast.makeText(getApplicationContext(), "靜態注冊", Toast.LENGTH_SHORT).show();                break;            }            case 2:{                Toast.makeText(getApplicationContext(), "動態注冊", Toast.LENGTH_SHORT).show();                break;            }            case 3:{                Toast.makeText(getApplicationContext(), "普通廣播", Toast.LENGTH_SHORT).show();                break;            }            case 4:{                Toast.makeText(getApplicationContext(), "有序廣播", Toast.LENGTH_SHORT).show();                break;            }        }        return START_STICKY;    }    @Override    public void onDestroy() {        // 停止service后會調用此方法        Log.d("TEST", "destroy");        super.onDestroy();    }}那么靜態廣播的創建就完成了,簡單吧,就兩個步驟,一是配置廣播,二是繼承BroadcastReceiver,重寫里面的onReceive函數。接下來我們在新建一個工程來檢測廣播是否可以響應消息。
public class MainActivity extends Activity implements OnClickListener{    PRivate Button b1,b2,b3,b4;    private Intent intent;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        intent = new Intent();        //獲得界面的控件        b1 = (Button) findViewById(R.id.button1);        b1.setOnClickListener(this);        b2 = (Button) findViewById(R.id.button2);        b2.setOnClickListener(this);        b3 = (Button) findViewById(R.id.button3);        b3.setOnClickListener(this);        b4 = (Button) findViewById(R.id.button4);        b4.setOnClickListener(this);        Log.d("TEST","===初始化完成===");    }        @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch(v.getId()){            case R.id.button1:{//發送到靜態注冊廣播                intent = new Intent("android.intent.action.COLD_BROADCAST");                  sendBroadcast(intent);                //intent.putExtra("msg", "hello coldreceiver.");                  break;            }            case R.id.button2:{//發送到動態注冊廣播                intent = new Intent("android.intent.action.HOT_BROADCAST");                  //intent.putExtra("msg", "hello hotreceiver.");                  sendBroadcast(intent);                break;            }            case R.id.button3:{//普通廣播                intent = new Intent("android.intent.action.NORMAL_BROADCAST");                  sendBroadcast(intent);                break;            }            case R.id.button4:{//有序廣播                intent = new Intent("android.intent.action.SORT_BROADCAST");                  sendOrderedBroadcast(intent, "scott.permission.SORT_BROADCAST_PERMISSION");                  break;            }        }    }        public void show(String str){        Toast.makeText(this, str, Toast.LENGTH_LONG).show();    }    @Override    protected void onDestroy() {        // TODO Auto-generated method stub        super.onDestroy();    }}

ok,將兩個應用都安裝到設備上,啟動測試用的應用,點擊第一個按鈕,運行的效果如下

同時,會出現"靜態注冊"的Toast,可以看出靜態注冊廣播能夠跨應用來響應信息,這都要歸功于安卓上的組件管理服務,它會讀取每個應用的配置文件,然后獲取里面的組件信息,每當有消息響應時,組件管理服務會從中查找有沒有需要調用的組件,并判斷是否進行執行

2、動態注冊

動態注冊也可以分成兩部分,一在代碼中進行動態注冊,二還是繼承BroadcastReceiver,重寫里面的onReceive函數。我們在廣播應用中新建一個HotReceiver,繼承BroadcastReceiver。

public class HotReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        //String msg = intent.getStringExtra("msg");          intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(2);        context.startService(intent);        Log.d("TEST","動態注冊");    }}在Activity中進行動態注冊

public class MainActivity extends Activity {    private HotReceiver receiver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                //動態注冊廣播        //新建一個廣播對象        receiver = new HotReceiver();          //新建一個intent管理機制,(功能是對組件進行過濾,只獲取需要的消息)        IntentFilter filter = new IntentFilter();         //添加白名單(只獲取該動作的信息)        filter.addAction("android.intent.action.HOT_BROADCAST");                  //與廣播綁定,進行注冊        registerReceiver(receiver, filter);    }    @Override    protected void onDestroy() {        //取消注冊,一定要記得,不然系統會報錯誤        unregisterReceiver(receiver);        stopService(new Intent("android.intent.action.BroadcastService"));        super.onDestroy();    }}

ok,再使用測試應用來檢查一下效果,注意步驟,安裝好廣播應用打開,不要讓它退出,切換到測試用的廣播,點擊第二個按鈕。

測試成功。那么我們關掉廣播應用在測試一下,會發現不會再出現動態注冊的打印消息。這說明動態注冊的廣播是與Activity綁定的,當Activity銷毀時,廣播也會被銷毀。在Android中,很多時候最好是使用動態注冊的方式使用廣播,比如時間變化事件,電量變更事件等,這些事件觸發率太高,如果使用靜態注冊,會導致進程頻繁的被構造和銷毀從而影響整個系統的效率。

三、廣播的兩種類型

1、普通廣播——普通廣播對于多個接收者來說完全是異步的,通常每個接收者無需等待即可接收到廣播,接收者相互之間不影響,對于這種廣播接收者無法阻止廣播,也就是無法阻止其他接收者接受廣播。

新建三個靜態廣播進行測試——調用abortBroadcast阻礙廣播向下一級傳播

public class NormalReceiver1 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(3);        context.startService(intent);        Log.d("TEST","普通廣播1");        abortBroadcast();    }}

public class NormalReceiver2 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(3);        context.startService(intent);        Log.d("TEST","普通廣播2");        abortBroadcast();    }}
public class NormalReceiver3 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(3);        context.startService(intent);        Log.d("TEST","普通廣播3");        abortBroadcast();    }}進行配置

<receiver android:name=".NormalReceiver1">              <intent-filter>                  <action android:name="android.intent.action.NORMAL_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>         <receiver android:name=".NormalReceiver2">              <intent-filter>                  <action android:name="android.intent.action.NORMAL_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>         <receiver android:name=".NormalReceiver3">              <intent-filter>                  <action android:name="android.intent.action.NORMAL_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>

安裝完畢后,我們點擊檢測應用的第三個按鈕,可以看到

經過測試,abortBroadcast在這里不起作用,并會讓系統報錯。所以如果要讓廣播有一定的優先級進行傳播就要使用到有序廣播。

2、有序廣播

有序廣播通過調用sendOrderedBroadcast函數進行發送。它每次只發送到優先級較高的接收者那里,然后由優先級高的接受者再傳播到優先級低的接收者那里,優先級高的接收者有能力終止這個廣播。在有序廣播的傳遞過程中,每個執行中的觸發器組件都可以通過BroadcastReceiver.setResult等函數附加額外的數據,而下一個廣播則可以使用這些數據(BroadcastReceiver.getResultData)。這樣可以構成一個消息數據處理鏈。為了保證某一事件一定會被處理,可以指明默認的廣播接收器(Final Receiver)。一樣的,新建三個靜態廣播樣例

public class SortReceiver1 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        // TODO Auto-generated method stub        //String msg = intent.getStringExtra("msg");          intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(4);        context.startService(intent);        Log.d("TEST","有序廣播1");        abortBroadcast();    }}
public class SortReceiver2 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        // TODO Auto-generated method stub        //String msg = intent.getStringExtra("msg");          intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(4);        context.startService(intent);        Log.d("TEST","有序廣播2");    }}
public class SortReceiver3 extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        // TODO Auto-generated method stub        //String msg = intent.getStringExtra("msg");          intent = new Intent("android.intent.action.BroadcastService");         intent.addFlags(4);        context.startService(intent);        Log.d("TEST","有序廣播3");    }}

<receiver android:name=".SortReceiver1">              <intent-filter android:priority="1000">                  <action android:name="android.intent.action.SORT_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>         <receiver android:name=".SortReceiver2">              <intent-filter android:priority="999">                  <action android:name="android.intent.action.SORT_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>         <receiver android:name=".SortReceiver3">              <intent-filter android:priority="998">                  <action android:name="android.intent.action.SORT_BROADCAST"/>                  <category android:name="android.intent.category.DEFAULT" />              </intent-filter>          </receiver>我們看到,現在這三個接收者的<intent-filter>多了一個android:priority屬性,并且依次減小。這個屬性的范圍在-1000到1000,數值越大,優先級越高。

同樣發送廣播的代碼也是不一樣的

sendOrderedBroadcast(intent, "scott.permission.SORT_BROADCAST_PERMISSION");注意,使用sendOrderedBroadcast方法發送有序廣播時,需要一個權限參數,如果為null則表示不要求接收者聲明指定的權限,如果不為 null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信 的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。所以我們在AndroidMainfest.xml中定義一個權限,并獲得權限:(是要在廣播的應用中聲明)

<permission android:protectionLevel="normal"              android:name="scott.permission.SORT_BROADCAST_PERMISSION" /><uses-permission android:name="scott.permission.SORT_BROADCAST_PERMISSION" />

(這里不是寫在application內部,而是同application同級)

運行后只會出現這么一個消息:

運行后只執行了第一個廣播,因為在第一個廣播出我們就終止了廣播的繼續傳遞,所以就只會出現這么一條打印消息。

四、形形色色的廣播(系統發出的廣播)

在android中有很多系統自帶的intent.action,通過監聽這些事件我們可以完成很多功能。

開機:String BOOT_COMPLETED_ACTION 廣播:在系統啟動后。這個動作被廣播一次(只有一次)。監聽: “android.intent.action.BOOT_COMPLETED”電話撥入:String ANSWER_ACTION 動作:處理撥入的電話。監聽: “android.intent.action.ANSWER”電量變化:String BATTERY_CHANGED_ACTION 廣播:充電狀態,或者電池的電量發生變化。監聽: “android.intent.action.BATTERY_CHANGED”日期改變:String DATE_CHANGED_ACTION 廣播:日期被改變。 監聽:“android.intent.action.DATE_CHANGED”取消更新下載:String FOTA_CANCEL_ACTION 廣播:取消所有被掛起的 (pending) 更新下載。 監聽:“android.server.checkin.FOTA_CANCEL”更新開始安裝:String FOTA_READY_ACTION 廣播:更新已經被下載 可以開始安裝。監聽 “android.server.checkin.FOTA_READY”主屏幕:String HOME_CATEGORY 類別:主屏幕 (activity)。設備啟動后顯示的第一個 activity。 監聽:"android.intent.category.HOME”新應用:String PACKAGE_ADDED_ACTION 廣播:設備上新安裝了一個應用程序包。監聽: “android.intent.action.PACKAGE_ADDED”刪除應用:String PACKAGE_REMOVED_ACTION 廣播:設備上刪除了一個應用程序包。監聽: “android.intent.action.PACKAGE_REMOVED”屏幕關閉:String SCREEN_OFF_ACTION 廣播:屏幕被關閉。監聽: “android.intent.action.SCREEN_OFF”屏幕開啟:String SCREEN_ON_ACTION 廣播:屏幕已經被打開。 監聽:“android.intent.action.SCREEN_ON”時區改變:String TIMEZONE_CHANGED_ACTION 廣播:時區已經改變。監聽: “android.intent.action.TIMEZONE_CHANGED”時間改變:String TIME_CHANGED_ACTION 廣播:時間已經改變(重新設置)。 “android.intent.action.TIME_SET”時間流逝:String TIME_TICK_ACTION 廣播:當前時間已經變化(正常的時間流逝)。 “android.intent.action.TIME_TICK”進入大容量存儲模式:String UMS_CONNECTED_ACTION 廣播:設備進入 USB 大容量存儲模式。 “android.intent.action.UMS_CONNECTED”退出大容量存儲模式:String UMS_DISCONNECTED_ACTION 廣播:設備從 USB 大容量存儲模式退出。 “android.intent.action.UMS_DISCONNECTED”壁紙改變:String WALLPAPER_CHANGED_ACTION 廣播:系統的墻紙已經改變。 “android.intent.action.WALLPAPER_CHANGED”web搜索:String WEB_SEARCH_ACTION 動作:執行 web 搜索。 “android.intent.action.WEB_SEARCH”網絡變化:String CONNECTIVITY_CHANGE_ACTION 動作:網絡變化?!癮ndroid.intent.action.CONNECTIVITY_CHANGE_ACTION”

廣播本身的使用很簡單,它所包含的內容也很少,但是結合廣播來進行應用的開發卻會給用戶帶來更好的體驗,廣播的使用會讓用戶覺得開發者能夠為用戶考慮到各個情況的發生,這點往往能夠留住大多數的用戶。所以多考慮各種情況的發生,不要吝嗇廣播的使用。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人久久一区二区三区| 亚洲第一综合天堂另类专| 国产中文字幕91| 蜜臀久久99精品久久久久久宅男| 久久久久久一区二区三区| 亚洲精品国产美女| 国产精品极品美女在线观看免费| 欧美电影在线观看| 成人免费自拍视频| 69影院欧美专区视频| 国产91免费看片| 久久精品成人一区二区三区| 久久高清视频免费| 久久亚洲一区二区三区四区五区高| 国产成人精品在线观看| 久99九色视频在线观看| 久久天天躁日日躁| www.欧美三级电影.com| 欧美一区二三区| 亚洲男女性事视频| 九九久久久久99精品| 日韩在线观看精品| 国产精品国产亚洲伊人久久| 日产精品99久久久久久| 国产精品jizz在线观看麻豆| 亚洲欧美日韩一区二区在线| 精品性高朝久久久久久久| 国产精品jizz在线观看麻豆| 欧美极品第一页| 亚洲va欧美va国产综合久久| 日本欧美国产在线| 日韩av男人的天堂| 欧美大成色www永久网站婷| 深夜福利国产精品| 欧美性猛交xxxx免费看| 日韩av免费在线看| 亚洲白拍色综合图区| 日韩国产高清污视频在线观看| 亚洲女同精品视频| 96pao国产成视频永久免费| 日韩欧美第一页| 亚洲成人精品久久| 亚洲欧美综合精品久久成人| 欧美黄色成人网| 欧美精品免费播放| 欧美精品aaa| 欧美精品日韩三级| 亚洲精品一区二区在线| 亚洲国产精品悠悠久久琪琪| 国产精品久久久久久久久久久不卡| 国内偷自视频区视频综合| 久久免费视频网站| 久久久免费精品视频| 亚洲欧洲午夜一线一品| 国产成人拍精品视频午夜网站| 国产精品永久在线| 国产精品视频久久| 97视频在线观看亚洲| 国产精品一区二区三区久久久| 尤物九九久久国产精品的特点| 国产国产精品人在线视| 欧美日韩xxx| 国产精品你懂得| 亚洲一区制服诱惑| 欧美色videos| 国产精品夜间视频香蕉| 国产69精品99久久久久久宅男| 亚洲精品福利在线观看| 国产精品女主播视频| 亚洲韩国日本中文字幕| 久久在线免费观看视频| 亚洲韩国欧洲国产日产av| 国产成人精品日本亚洲| 国产精品草莓在线免费观看| 国模吧一区二区| 亚洲色图50p| 国产精品最新在线观看| 国产精品久久久久久久久久| 久久久噜噜噜久久| 亚洲欧美综合区自拍另类| 日韩经典中文字幕在线观看| 26uuu国产精品视频| 欧美在线视频免费观看| 热久久美女精品天天吊色| 精品中文字幕视频| 欧美另类99xxxxx| 日韩一区二区三区在线播放| 成人做爰www免费看视频网站| 国内外成人免费激情在线视频| 亚洲国产精品国自产拍av秋霞| 欧美激情a在线| 这里只有精品视频在线| 精品久久香蕉国产线看观看亚洲| 亚洲日本aⅴ片在线观看香蕉| 庆余年2免费日韩剧观看大牛| 性色av一区二区三区红粉影视| 国产精品丝袜久久久久久高清| 日韩成人在线视频| 91在线精品视频| 亚洲久久久久久久久久久| 欧美一区深夜视频| 国内精品视频一区| 日韩视频在线免费观看| 国产97色在线| 91色视频在线导航| 国产视频精品在线| 国产欧美久久一区二区| 九九精品在线观看| 欧美日韩国产区| 亚洲电影av在线| 国产成人aa精品一区在线播放| 国产精品久久久久久久一区探花| 欧美精品一区二区三区国产精品| 亚洲国产精品电影在线观看| 中文字幕日韩视频| 在线观看日韩专区| 国产精品免费视频久久久| 91av免费观看91av精品在线| 精品欧美aⅴ在线网站| 精品久久香蕉国产线看观看gif| 久久精品福利视频| 欧美日韩激情美女| 日韩欧美一区二区三区久久| 日韩av大片在线| 亚洲精品视频网上网址在线观看| 日韩在线精品视频| 91性高湖久久久久久久久_久久99| 欧美国产日韩一区二区三区| 亚洲精品天天看| 姬川优奈aav一区二区| 日韩av成人在线| 欧美激情欧美狂野欧美精品| 国产精品视频自拍| 国产日韩精品一区二区| 九九热精品视频| 欧美激情视频播放| 国产精品欧美日韩久久| 自拍视频国产精品| 狠狠躁夜夜躁人人躁婷婷91| 欧美性猛交xxxxx免费看| 国产欧美一区二区三区在线| 亚洲最新av在线网站| 国产日韩欧美视频| 欧美激情一二区| 成人www视频在线观看| 欧美伊久线香蕉线新在线| 日韩精品福利在线| 久久精品在线视频| 欧美成人在线网站| 久久99热精品| 亚洲第一福利网站| 日韩视频免费大全中文字幕| 欧美激情一区二区久久久| 中文字幕一区二区三区电影| 亚洲毛茸茸少妇高潮呻吟| 91天堂在线观看| 成人在线视频网站| 成人免费大片黄在线播放| 亚洲片国产一区一级在线观看| 日韩在线观看成人| 日韩亚洲一区二区| 亚洲第一页中文字幕| 久久国产精品偷| 91tv亚洲精品香蕉国产一区7ujn|