Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 深入Android中BroadcastReceiver的兩種注冊方式(靜態和動態)詳解

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

編輯:關於Android編程

今天我們一起來探討下安卓中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的兩種常用類型

(1)Normalbroadcasts:默認廣播

發送一個默認廣播使用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中實現代碼:

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)當廣播為默認廣播時:無視優先級,動態廣播接收器優先於靜態廣播接收器。同優先級的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先注冊的優先於後冊的。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved