Android中BroadcastReceiver的使用


1、Android中廣播分為靜態注冊和動態注冊

2、下面是一個簡單靜態注冊的例子

  • 創建一個繼承BroadcastReceiver的子類
public class DeviceBootReceiver extends BroadcastReceiver {

    private static final String TAG = DeviceBootReceiver.class.getName();
    
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "開機了:" + intent.getAction());
    }
}

該類的功能用於接收手機開機的廣播。

  • AndroidManifest.xml中注冊該組件
<receiver android:name=".DeviceBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

action標簽中的值用於匹配廣播的類型,這里是開機廣播。
這樣當手機開機時,便會收到來自系統的消息。

同樣,我們也可以監聽應用安裝,應用卸裝,USB插拔等系統廣播。只是action的值稍有不同。

<receiver android:name=".OtherStateReceiver">
    <intent-filter>
        <!--電量過低-->
        <action android:name="android.intent.action.BATTERY_LOW" />
        <!--USB連接-->
        <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
        <!--USB斷開-->
        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        <!--軟件包安裝-->
        <action android:name="android.intent.action.PACKAGE_ADDED" />
        <!--軟件包卸裝-->
        <action android:name="android.intent.action.PACKAGE_REMOVED" />
    </intent-filter>
</receiver>

上面除了開機廣播,其他廣播這樣注冊能成功的前提是 API Level < 26(Android8.0以下)
。Google為了防止接收者程序常駐內存消耗資源,禁止了一些Manifest declared receiver。我們想要繼續監聽,就要使用動態注冊的方式。

3、下面是一個動態注冊的例子:

public class SystemBroadcastReceiverActivity extends AppCompatActivity {

    private SystemBroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_system_broadcast_receiver);

        IntentFilter filter = new IntentFilter();
        //USB連接
        filter.addAction(Intent.ACTION_POWER_CONNECTED);
        //USB斷開
        filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        receiver = new SystemBroadcastReceiver();
        registerReceiver(receiver, filter);
    }

    private class SystemBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            System.out.println(intent.getAction());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }
}

然后在AndroidManifest.xml注冊該Activity即可。

4、自定義廣播

前面說的都是接收系統廣播,我們也可以發送自定義的廣播,然后在同一個應用或不同應用中接收。

下面是一個靜態注冊的自定義廣播:
  • 建立一個Activity,提供一個Button,點擊后發送廣播
public class CustomSenderActivity extends AppCompatActivity {

    public static final String BROADCAST_ACTION = "com.hncj.android.manifest.CustomSenderActivity";
    public static final String BROADCAST_CONTENT = "broadcast_content";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_sender);
    }

    @SuppressLint("WrongConstant")
    public void sendBroadcast(View view) {
        Intent intent = new Intent();
        intent.setAction(BROADCAST_ACTION);
        intent.putExtra(BROADCAST_CONTENT, "我發送了廣播,你看收沒收到?");
        
        //解決API26及以上的Android靜態注冊的Receiver收不到廣播
        //第一種解決方案:設置標志 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
        intent.addFlags(0x01000000); //不論是一個應用自己發自己收還是一個應用發一個應用收,都可以實現效果

        //第二種解決方案:指定包名(這里是一個應用,自己發,自己收,都在一個包下)
        //intent.setPackage(getPackageName());  //如果是給另一個應用發廣播 則寫成intent.setPackage("另一個項目應用接收者的包名");

        //第三種解決方案: 明確指定包名,類名
        //intent.setComponent(new ComponentName(this, CustomReceiver.class)); //如果是給另一個應用發廣播 則寫成 intent.setComponent(new ComponentName("另一個應用接收者包名", "另一個應用接收者類名"));

        //發送廣播
        sendBroadcast(intent);
    }
}
  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="40dp">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="sendBroadcast"
        android:background="#008080"
        android:textSize="30dp"
        android:text="發送廣播"></Button>
</LinearLayout>
  • 接收者
public class CustomReceiver extends BroadcastReceiver {

    private static final String TAG = CustomReceiver.class.getName();

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "我收到了來自" + action + "的廣播");
    }
}
  • AndroidManifest.xml文件
<activity android:name=".manifest.CustomSenderActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<receiver android:name=".manifest.CustomReceiver">
    <intent-filter>
        <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
    </intent-filter>
</receiver>

這里的一個接收者是在當前項目,還有一個接收者在另一個項目,代碼基本是一致的。
相關的API:

發送有序廣播:

<!--廣播中攜帶數據-->
Bundle bundle = new Bundle();
bundle.putString("username", "nacy");
sendOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, null, bundle);

為接收者設置優先級:(-1000-1000),即定義哪個接收者先收到,優先級越大,越早收到廣播

<receiver android:name=".manifest.CustomReceiver">
    <!--priority可以設置優先級-->
    <intent-filter android:priority="9">
        <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
    </intent-filter>
</receiver>

終止廣播:

<!--廣播不再向下傳遞-->
abortBroadcast();

取出廣播中的數據:

//取出Bundle對象,類似於一個map
 Bundle bundle = getResultExtras(true);

設置接收者權限:(誰能收到)

  • 先在發送方AndroidManifest.xml中聲明一個權限(包名+權限名)
<permission android:name="com.hncj.android.RECEIVER_PERMISSION" />
  • 發送時定義接收者需要擁有的權限:
sendOrderedBroadcast(intent, Manifest.permission.RECEIVER_PERMISSION, null, null, Activity.RESULT_OK, null, bundle);
  • 接收者需要在AndroidManifest.xml使用權限:
<uses-permission android:name="com.hncj.android.RECEIVER_PERMISSION" />

設置發送者權限:(誰能給我發)

  • 先在接收方AndroidManifest.xml聲明一個權限
<permission android:name="com.hncj.android.SENDER_PERMISSION" />
  • 在Receiver標簽中說明發送者要擁有的權限:
<receiver android:name=".manifest.CustomReceiver" android:permission="com.hncj.android.SENDER_PERMISSION">
    <intent-filter android:priority="9">
        <action android:name="com.hncj.android.manifest.CustomSenderActivity" />
    </intent-filter>
</receiver> 
  • 在發送方AndroidManifest.xml中使用權限
<uses-permission android:name="com.hncj.android.SENDER_PERMISSION" />

還有動態注冊的自定義廣播,與上面提到的動態注冊的例子差不多,只是自定義action的內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM