Android學習(四)廣播

廣播

這個機制使得Android開發更加靈活,方便。類似於發佈—訂閱設計模式。不僅系統提供了豐富的廣播供我們監聽,還可以自定義廣播進行使用。

廣播隨Android版本帶來的變動

廣播經常隨着Android版本的發佈而發生改變,儘量在使用前關注一下每個版本的廣播變動。詳細官方描述。簡單列舉一下:

  1. Android 9.0

從Android 9(API級別28)開始, NETWORK_STATE_CHANGED_ACTION 廣播不會接收有關用戶位置或個人身份數據的信息。

此外,如果您的應用安裝在運行Android 9或更高版本的設備上,則來自Wi-Fi的系統廣播不包含SSID,BSSID,連接信息或掃描結果。要獲取此信息,請使用getConnectionInfo()方法 。

  1. Android 8.0

從Android 8.0(API級別26)開始,系統對清單聲明的接收者施加了其他限制。

如果您的應用程序針對Android 8.0或更高版本,則不能使用清單爲大多數隱式廣播(不專門針對您的應用程序的廣播)聲明接收方。

  1. Android 7.0

Android 7.0(API級別24)及更高版本不會發送以下系統廣播:
ACTION_NEW_PICTURE
ACTION_NEW_VIDEO

另外,定位到Android 7.0及更高版本的應用必須使用registerReceiver(BroadcastReceiver, IntentFilter)來註冊廣播CONNECTIVITY_ACTION。在清單中聲明廣播接收者無效。

接收廣播

接收廣播的方式主要分爲兩種動態註冊靜態註冊

靜態註冊

靜態註冊主要是在清單中聲明註冊。如果您在清單中聲明瞭廣播接收者,則發送廣播時,系統會啓動您的應用程序(如果該應用程序尚未運行)。
注意,大部分系統廣播在Android 7.0以上,不支持靜態註冊,無法監聽到廣播。

  1. 創建一個廣播接收器

在這裏插入圖片描述
在onReceive()方法內編寫邏輯。

  1. 在AndroidManifest.xml文件內註冊。

在< receiver >標籤內,添加< intent-filter >標籤,再添加相應的action即可。
部分廣播,還需要額外權限,這裏申請開機廣播權限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

動態註冊

動態註冊主要是在代碼中使用context註冊廣播接收者。可以節省資源、使廣播可控。這也是官方推薦的用法。但必須要程序運行到註冊廣播的代碼纔可以監聽廣播。還需要自己手動取消註冊,否則容易造成內存泄漏。

  1. 創建一個類繼承BroadcastReceiver,並重寫onReceive()方法。
package com.example.testapplication;


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

public class NetworkReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "大人時代變了", Toast.LENGTH_SHORT).show();
    }
}

  1. 註冊廣播。在不需要廣播時,取消註冊廣播。

注意,網絡變化廣播,需要申請權限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
package com.example.testapplication;

import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class FourthActivity extends AppCompatActivity {

    private NetworkReceiver networkReceiver;

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

    private void register() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);    //聲明監聽廣播
        networkReceiver = new NetworkReceiver();    //做邏輯處理
        registerReceiver(networkReceiver, intentFilter);    //註冊廣播
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(networkReceiver);    //取消註冊
    }
}

在這裏插入圖片描述

發送廣播

發送廣播的方式分爲三種標準廣播有序廣播本地廣播

標準廣播

廣播以不確定順序向所有監聽廣播者發送,效率高。但安全性低,且無法中斷廣播。
發送廣播之前,需要選創建廣播接收器。

  1. 創建廣播接收器
package com.example.testapplication;

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

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "廣播收到了", Toast.LENGTH_SHORT).show();
    }
}

  1. 代碼動態註冊廣播,最後調用sendBroadcast()方法發送廣播

activity佈局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.testapplication.FourthActivity">

    <Button
        android:id="@+id/send_br"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="標準廣播"/>
</android.support.constraint.ConstraintLayout>

註冊廣播,發送廣播

package com.example.testapplication;

import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class FourthActivity extends AppCompatActivity {

    private MyReceiver myReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fourth);
        register();
        Button button = findViewById(R.id.send_br);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.test.broadcast");   //指定發送廣播
                sendBroadcast(intent);  //發送廣播
            }
        });
    }

    private void register() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.test.broadcast");    //聲明監聽廣播
        myReceiver = new MyReceiver();    //做邏輯處理
        registerReceiver(myReceiver, intentFilter);    //註冊廣播
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);    //取消註冊
    }
}

在這裏插入圖片描述

有序廣播

基本流程和標準廣播一致。有序廣播是一次將廣播發送到一個接收器,可以根據優先級來進行順序排列,接收器也可以進行中斷廣播發送。安全性更高。

我就寫不一樣的地方。

  1. 發送有序廣播

調用的是sendOrderedBroadcast()方法

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.test.broadcast");   //指定發送廣播
                sendOrderedBroadcast(intent, null);  //發送有序廣播
            }
        });
  1. 廣播接收到後,可以進行中斷廣播處理

調用abortBroadcast()方法

package com.example.testapplication;

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

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "廣播收到了", Toast.LENGTH_SHORT).show();
        abortBroadcast();
    }
}

本地廣播

前面的兩種廣播都屬於系統全局廣播,可以被別的程序接收到。如果我們只想在自己的app內使用廣播,可以使用本地廣播。

我就寫一下不一樣的地方。

  1. 需要註冊本地廣播
localBroadcastManager = LocalBroadcastManager.getInstance(this);    //獲取實例
IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.test.broadcast");    //聲明監聽廣播
        myReceiver = new MyReceiver();    //做邏輯處理
        localBroadcastManager.registerReceiver(myReceiver, intentFilter);    //註冊廣播
  1. 發送本地廣播
Intent intent = new Intent("com.test.broadcast");   //指定發送廣播
                localBroadcastManager.sendBroadcast(intent);  //發送本地有序廣播

整體代碼

package com.example.testapplication;

import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class FourthActivity extends AppCompatActivity {

    private MyReceiver myReceiver;
    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fourth);
        localBroadcastManager = LocalBroadcastManager.getInstance(this);    //獲取實例
        register();
        Button button = findViewById(R.id.send_br);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.test.broadcast");   //指定發送廣播
                localBroadcastManager.sendBroadcast(intent);  //發送本地有序廣播
            }
        });
    }

    private void register() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.test.broadcast");    //聲明監聽廣播
        myReceiver = new MyReceiver();    //做邏輯處理
        localBroadcastManager.registerReceiver(myReceiver, intentFilter);    //註冊廣播
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(myReceiver);    //取消註冊
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章