1. 程式人生 > >Android中BroadcastReceiver的兩種註冊方式(靜態和動態)詳解

Android中BroadcastReceiver的兩種註冊方式(靜態和動態)詳解

今天我們一起來探討下安卓中BroadcastReceiver元件以及詳細分析下它的兩種註冊方式。

BroadcastReceiver也就是“廣播接收者”的意思,顧名思義,它就是用來接收來自系統和應用中的廣播。在Android系統中,廣播體現在方方面面,例如當開機完成後系統會產生一條廣播,接收到這條廣播就能實現開機啟動服務的功能;當網路狀態改變時系統會產生一條廣播,接收到這條廣播就能及時地做出提示和儲存資料等操作;當電池電量改變時,系統會產生一條廣播,接收到這條廣播就能在電量低時告知使用者及時儲存進度等等。Android中的廣播機制設計的非常出色,很多事情原本需要開發者親自操作的,現在只需等待廣播告知自己就可以了,大大減少了開發的工作量和開發週期。而作為應用開發者,就需要數練掌握Android系統提供的一個開發利器,那就是BroadcastReceiver。

在我們詳細分析建立BroadcastReceiver的兩種註冊方式前,我們先羅列本次分析的大綱:

(1)對靜態和動態兩種註冊方式進行概念闡述以及演示實現步驟

(2)簡述兩種BroadcastReceiver的型別(為後續註冊方式的對比做準備)

(3)在預設廣播型別下設定優先順序和無優先順序情況下兩種註冊方式的比較

(4)在有序廣播型別下兩種註冊方式的比較

(5)通過接受打電話的廣播,在程式(Activity)執行時和終止執行時,對兩種註冊方式的比較

(6)總結兩種方式的特點

第一步:靜態和動態註冊方式基本概念以及實現步驟

構建Intent,使用sendBroadcast方法發出廣播定義一個廣播接收器,該廣播接收器繼承BroadcastReceiver

,並且覆蓋onReceive()方法來響應事件註冊該廣播接收器,我們可以在程式碼中註冊(動態註冊),也可以AndroidManifest.xml配置檔案中註冊(靜態註冊)。

動態註冊:

效果如下圖:

這裡就不演示點選按鈕佈局的實現了,MainActivity.java中實現程式碼如下:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    DynamicReceiver dynamicReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		//例項化IntentFilter物件
        IntentFilter filter = new IntentFilter();
        filter.addAction("panhouye");
        dynamicReceiver = new DynamicReceiver();
		//註冊廣播接收
        registerReceiver(dynamicReceiver,filter);
    }
	//按鈕點選事件
    public void send2(View v){
        Intent intent = new Intent();
        intent.setAction("panhouye");
        intent.putExtra("sele","潘侯爺");
        sendBroadcast(intent);
    }
	/*動態註冊需在Acticity生命週期onPause通過
	 *unregisterReceiver()方法移除廣播接收器,
	 * 優化記憶體空間,避免記憶體溢位
	 */
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(new MyReceiver());
    }
	//通過繼承 BroadcastReceiver建立動態廣播接收器
    class DynamicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
			//通過土司驗證接收到廣播
            Toast t = Toast.makeText(context,"動態廣播:"+ intent.getStringExtra("sele"), Toast.LENGTH_SHORT);
            t.setGravity(Gravity.TOP,0,0);//方便錄屏,將土司設定在螢幕頂端
            t.show();
        }
    }
}


建立方法程式碼中做了詳細註釋,有不明白的地方請留言討論。

靜態註冊:

效果如下:

靜態註冊建立第一步,新建BroadcastReceiver,見下圖:

通過以上步驟,生成MyReceiver.java檔案:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.view.Gravity;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast t = Toast.makeText(context,"靜態廣播:"+intent.getStringExtra("info"), Toast.LENGTH_SHORT);
        t.setGravity(Gravity.TOP,0,0);
        t.show();
    }
}


生成MyReceiver.java的同時,修改AndroidMainfest.xml配置檔案中的程式碼:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.day19">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		//生成的receiver配置檔案
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
			//自定義Action
                <action android:name="MLY" />
            </intent-filter>
        </receiver>
    </application>
</manifest>


最後在MainActivity.java檔案中新增按鈕點選事件,如下:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    DynamicReceiver dynamicReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    //靜態廣播點選
    public void send(View v){
        Intent intent = new Intent();
        intent.setAction("MLY");
        intent.putExtra("info","panhouye");
        sendBroadcast(intent);
    }
}


至此,兩種註冊方式的實現程式碼演示完畢,歡迎探討。

第二步:為方便後續分析,這裡插入BroadcastReceiver的兩種常用型別

(1Normalbroadcasts:預設廣播

傳送一個預設廣播使用Context.sendBroadcast()方法,普通廣播對於多個接收者來說是完全非同步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。

(2)orderedbroadcasts:有序廣播

    傳送一個有序廣播使用Context.sendorderedBroadcast()方法,有序廣播比較特殊,它每次只發送到優先順序較高的接收者那裡,然後由優先順序高的接受者再傳播到優先順序低的接收者那裡,優先順序高的接收者有能力終止這個廣播。

傳送有序廣播:sendorderedBroadCast()

在註冊廣播中的<intent-filter>中使用android:priority屬性。這個屬性的範圍在-1000到1000,數值越大,優先順序越高。在廣播接收器中使用setResultExtras方法將一個Bundle物件設定為結果集物件,傳遞到下一個接收者那裡,這樣優先順序低的接收者可以用getResuttExtras獲取到最新的經過處理的資訊集合。使用sendorderedBroadcast方法傳送有序廣播時,需要一個許可權引數,如果為null則表示不要求接收者宣告指定的許可權,如果不為null則表示接收者若要接收此廣播,需宣告指定許可權。這樣做是從安全形度考慮的,例如系統的簡訊就是有序廣播的形式,一個應用可能是具有攔截垃圾簡訊的功能,當簡訊到來時它可以先接受到簡訊廣播,必要時終止廣播傳遞,這樣的軟體就必須宣告接收簡訊的許可權。

第三步:在預設廣播下兩種註冊方式的比較

(1)兩種註冊方式均不設定優先順序

這裡將動態與靜態兩種註冊的廣播觸發集中在一個按鈕上,顯示效果如下(未設定優先順序的情況下,先動態後靜態):

這裡同樣不演示按鈕佈局檔案,以及靜態註冊涉及AndroidMainfest.xml和MyReceiver.java檔案。直接展示MainActicity.java的實現程式碼:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    DynamicReceiver dynamicReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction("panhouye");
        dynamicReceiver = new DynamicReceiver();
        registerReceiver(dynamicReceiver,filter);
    }
    //靜態廣播點選
    public void send(View v){
        Intent intent = new Intent();
		//設定與動態相同的Action,方便同時觸發靜態與動態
        intent.setAction("panhouye");
        intent.putExtra("info","潘侯爺");
        sendBroadcast(intent);//預設廣播
    }
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(new MyReceiver());
    }
    class DynamicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast t = Toast.makeText(context,"動態廣播:"+ intent.getStringExtra("info"), Toast.LENGTH_SHORT);
            t.setGravity(Gravity.TOP,0,0);
            t.show();
        }
    }
}


(2)將動態優先順序設定為最低-1000,靜態優先順序設定為最高1000

顯示效果如下(動態仍先於靜態被接收到):

MainActivity中動態優先順序設定如下:
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction("panhouye");
		filter.setPriority(-1000);//設定動態優先順序
        dynamicReceiver = new DynamicReceiver();
        registerReceiver(dynamicReceiver,filter);
    }
AndroidMainfest.xml中靜態優先順序設定如下:
<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true">
	//設定靜態優先順序
    <intent-filter android:priority="1000">
          <action android:name="panhouye" />
    </intent-filter>
</receiver>

第四步:在有序廣播下兩種註冊方式比較

靜態廣播1(優先順序為200),靜態廣播2(優先順序為300),靜態廣播3(優先順序為400),靜態廣播優先順序為(-100),動態廣播優先順序為0。顯示效果如下:


出現順序由優先順序決定,由高到低分別為靜態3-靜態2-靜態1-動-靜態。(這裡參照前文程式碼)


第五步:接受打電話的廣播,比較程式執行中與結束執行時,兩種註冊方式的比較

本次比較採用比對Log的方式對兩種註冊方式進行比較,在MainActivity.java中會插入Activity全部生命週期用於檢測Log分析。

AndroidMainfest.xml配置檔案程式碼如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.test19">
    //新增撥打電話許可權
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name=".StaticReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                //設定打電話對應的action
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
    </application>
</manifest>


MainActivity.java中實現程式碼動態註冊將解除註冊放在onDestory方法內是因為在真機測試過程中撥打電話,需要返回主頁面,而此操作會造成Activity處於onStop狀態,若放在onPause中,將無法在程式執行時啟用動態註冊接受廣播。真實環境下建議在onpause下解除註冊,儘早釋放記憶體,避免記憶體溢位):

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    DynamicReceiver dynamicReceiver;//宣告動態註冊廣播接收
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
        dynamicReceiver = new DynamicReceiver();
        registerReceiver(dynamicReceiver,filter);
        Log.i("Tag","Activity-onCreate");
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.i("Tag","Activity-onStart");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.i("Tag","Activity-onResume");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.i("Tag","Activity-onPause");
    }
    @Override
    protected void onStop() {
        super.onPause();
        Log.i("Tag","Activity-onStop");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("Tag","Activity-onDestroy");
        unregisterReceiver(dynamicReceiver);
    }
    class DynamicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("Tag","動態註冊廣播接收到您正在撥打電話"+getResultData());
        }
    }
}


StaticReceiver.java中實現程式碼:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class StaticReceiver extends BroadcastReceiver {
    public StaticReceiver() {
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("Tag","靜態註冊廣播接收到您正在撥打電話"+getResultData());
    }
}


(1)在未退出Activity時,撥打電話,Log如下:



由Log可知在未退出Activity是,兩種方式均可接受到廣播。

(2)在退出Activity時,撥打電話,Log如下(即便不解除註冊,動態仍無法接受到廣播):

在退出程式(Activity)時,只有靜態註冊方式可以接受到廣播。

第六步:總結兩種註冊方式特點

廣播接收器註冊一共有兩種形式:靜態註冊和動態註冊.

兩者及其接收廣播的區別:

1)動態註冊廣播不是常駐型廣播,也就是說廣播跟隨Activity的生命週期。注意在Activity結束前,移除廣播接收器。

靜態註冊是常駐型,也就是說當應用程式關閉後,如果有資訊廣播來,程式也會被系統呼叫自動執行。

2)當廣播為有序廣播時:優先順序高的先接收(不分靜態和動態)。同優先順序的廣播接收器,動態優先於靜態

3)同優先順序的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先註冊的優先於後註冊的。

4)當廣播為預設廣播時:無視優先順序,動態廣播接收器優先於靜態廣播接收器。同優先順序的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先註冊的優先於後冊的。

相關推薦

AndroidBroadcastReceiver註冊方式靜態動態

今天我們一起來探討下安卓中BroadcastReceiver元件以及詳細分析下它的兩種註冊方式。 BroadcastReceiver也就是“廣播接收者”的意思,顧名思義,它就是用來接收來自系統和應用中的廣播。在Android系統中,廣播體現在方方面面,例如當開機完成後系統會

android------引導頁實現方式原生WebView網頁實現

有的App當你第一次開啟的是和常常會有引導頁來描述一些App資訊(功能,特點),當然也要做驗證,驗證第二次進入不進入引導頁,直接進入App,此部落格藉助ViewPager來實現引導頁, ViewPager類提供了多介面切換的新效果,是谷歌在3.0之後加入的新特性,所以需要引

普通字元裝置驅動的註冊方式新&舊

普通字元裝置驅動的兩種註冊方式(新&舊) 在核心中,對於一個普通的字元裝置驅動,不難發現有兩種註冊方式: register_chrdev族函式+建立裝置類、檔案的函式:這種方法是2.4版本

引導方式MBR 、 uefi下安裝ubuntu系統

1. 下載Ubuntu 14.04映象軟體;製作U盤啟動盤;、       2.保證有空閒空間 30G以上 ,插入Ubuntu啟動盤 USB啟動  (安裝過程) 3.分配空間      磁碟為MBR引導方式    /boot   200M空間 系統引導   /  

資料庫連線的實現方式讀取配置檔案——DBCP&C3P0;DBCP實現連線程式碼,C3P0實現連線程式碼——包含完整程式碼

兩種資料庫連線實現方式 第一種方式:DBCP DBCP使用流程 導jar包使用DBCP建立資料庫連線物件 DataSource ds=BasicDataSourceFactory.createDatasource("一個儲存連線資訊的properties集合");使

動態代理及其實現方式JDK、CGLIB

什麼是代理模式 為某物件提供一個代理,從而通過代理來訪問這個物件。 代理模式的角色組成 代理模式有三種角色組成: 抽象角色:通過介面或抽象類宣告真實角色實現的業務方法。 代理角色:實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象

PPP的配置方法papchap

pap chapPAP的配置R1上的配置[R1]int s4/0/0[R1-Serial4/0/0]ppp authentication-mode pap[R1-Serial4/0/0]q[R1]aaa[R1-aaa]local-user huawei password cipher 123456Info:

Android 實現簡單的登陸註冊功能SharedPreferencesSQLite

最近剛好做了一個Android的登入註冊介面,將資料利用SharedPreferences或者SQLite繫結到Android程式中,實現簡單的登陸註冊功能,本文未涉及到與伺服器的交流。 首先,對於登陸註冊要有一個明確的邏輯順序,不管是對於SharedPreferences

Android的人臉檢測靜態動態

(1)背景。        Google 於2006年8月收購Neven Vision 公司 (該公司擁有10多項應用於移動裝置領域的影象識別的專利),以此獲得了影象識別的技術,並加入到android中。Android 中的人臉識別技術,用到的底層庫:android/ex

禁用頁面快取的幾方法靜態動態

 1、在Asp頁面首部<head>加入    以下是引用片段:   Response.Buffer   =   True       Response.ExpiresAbsolute   =   Now()   -   1       Response.Exp

java代理,靜態代理,動態代理以及spring aop代理方式,實現原理統一彙總 SpringAOP的代理方式Java動態代理CGLIB代理

若代理類在程式執行前就已經存在,那麼這種代理方式被成為 靜態代理 ,這種情況下的代理類通常都是我們在Java程式碼中定義的。 通常情況下, 靜態代理中的代理類和委託類會實現同一介面或是派生自相同的父類。 一、概述1. 什麼是代理我們大家都知道微商代理,簡單地說就是代替廠家賣商品,廠家“委託”代理為

獲取IOC容器的bean的方式idclass的區別

// ClassPathXmlApplicationContext: 是 ApplicationContext的實現類,從類路徑下來載入配置檔案 ApplicationContext ctx=new ClassPathXmlApplicationContext("a

二、C++迭代器的實現方式 Range forC#、Java的foreach

一、迭代器概述   這個標題其實有點“標題黨”的含義,因為C++在標準庫中的實現迭代器的方式只有一種,也就是為類定義begin()和end()函式,C++11增加了range for語句,可以用來遍歷迭代器中的元素。實現迭代器的第二種方式,就是用C++模擬C#和Java中的

BroadcastReceiver廣播接收者的註冊方式

廣播是android四大元件之一,在我們的應用開發中也佔據著重要的地位,我們在很多時候和很多場景中都需要使用到廣播,那麼接下來我們就說一下廣播接收者的兩種註冊方式: 第一種:在androidmanifest.xml中註冊。 在配置檔案中註冊的接收者的特點是即使應用程式已被

Android 的廣播機制註冊方式

1.Android 的廣播機制 在 Android 裡面有各種各樣的廣播,比如電池的使用狀態,電話的接收和簡訊的接收都會產生一個廣播,應用程式開發者也可以監聽這些廣播並做出程式邏輯的處理。下面我畫一張粗略的圖來幫助大家理解廣播的執行機制。 Android 中有各式各

Android-動態載入外掛化的實現方式:介面

上一篇部落格中http://blog.csdn.net/lxping51/article/details/71480239,主要通過反射的方式來實現動態載入外掛化,今天我們以介面的方式來達到目的。介面的實現比反射更為簡單,而且直接呼叫對效能有很大的提高。但是這也

BroadcastReceiver註冊方式使用

BroadcastReceiver是android中的一個非常重要的元件,常用於接收廣播資訊。廣播的註冊使用有兩種方式:靜態註冊(在 AndroidManifest.xml 中 )<receiverandroid:name=".BroadcastReceiverDemo">            

Android序列化方式

1.Serializable,官方文件給出這種說明 類通過實現 java.io.Serializable 介面以啟用其序列化功能。未實現此介面的類將無法使其任何狀態序列化或反序列化。可序列化類的所有子型別本身都是可序列化的。序列化介面沒有方法或欄位,僅用於標識

xml解析方式封裝了獲得文件回寫

開始時間:2018年10月6日13:16:37 結束時間:2018年10月6日14:26:25 累計時間:1  xml解析: 這一篇挺好 https://blog.csdn.net/CristianoJason/article/details/51777853

依賴注入的常用方式(構造器Setter)與注入內容(裝配資料)——Spring IOC/DI

本章主要講解一下Spring中依賴注入方式,接上一章依賴注入原理和方式: https://blog.csdn.net/qq_34598667/article/details/83315669 依賴注入常用的兩種方式以及注入的內容(裝配資料) Spring通過DI(依賴注入)實現I