廣播
這個機制使得Android開發更加靈活,方便。類似於發佈—訂閱設計模式。不僅系統提供了豐富的廣播供我們監聽,還可以自定義廣播進行使用。
廣播隨Android版本帶來的變動
廣播經常隨着Android版本的發佈而發生改變,儘量在使用前關注一下每個版本的廣播變動。詳細官方描述。簡單列舉一下:
- Android 9.0
從Android 9(API級別28)開始, NETWORK_STATE_CHANGED_ACTION 廣播不會接收有關用戶位置或個人身份數據的信息。
此外,如果您的應用安裝在運行Android 9或更高版本的設備上,則來自Wi-Fi的系統廣播不包含SSID,BSSID,連接信息或掃描結果。要獲取此信息,請使用getConnectionInfo()方法 。
- Android 8.0
從Android 8.0(API級別26)開始,系統對清單聲明的接收者施加了其他限制。
如果您的應用程序針對Android 8.0或更高版本,則不能使用清單爲大多數隱式廣播(不專門針對您的應用程序的廣播)聲明接收方。
- 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以上,不支持靜態註冊,無法監聽到廣播。
- 創建一個廣播接收器
在onReceive()方法內編寫邏輯。
- 在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註冊廣播接收者。可以節省資源、使廣播可控。這也是官方推薦的用法。但必須要程序運行到註冊廣播的代碼纔可以監聽廣播。還需要自己手動取消註冊,否則容易造成內存泄漏。
- 創建一個類繼承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();
}
}
- 註冊廣播。在不需要廣播時,取消註冊廣播。
注意,網絡變化廣播,需要申請權限
<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); //取消註冊
}
}
發送廣播
發送廣播的方式分爲三種標準廣播,有序廣播和本地廣播。
標準廣播
廣播以不確定順序向所有監聽廣播者發送,效率高。但安全性低,且無法中斷廣播。
發送廣播之前,需要選創建廣播接收器。
- 創建廣播接收器
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();
}
}
- 代碼動態註冊廣播,最後調用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); //取消註冊
}
}
有序廣播
基本流程和標準廣播一致。有序廣播是一次將廣播發送到一個接收器,可以根據優先級來進行順序排列,接收器也可以進行中斷廣播發送。安全性更高。
我就寫不一樣的地方。
- 發送有序廣播
調用的是sendOrderedBroadcast()方法
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.test.broadcast"); //指定發送廣播
sendOrderedBroadcast(intent, null); //發送有序廣播
}
});
- 廣播接收到後,可以進行中斷廣播處理
調用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內使用廣播,可以使用本地廣播。
我就寫一下不一樣的地方。
- 需要註冊本地廣播
localBroadcastManager = LocalBroadcastManager.getInstance(this); //獲取實例
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.test.broadcast"); //聲明監聽廣播
myReceiver = new MyReceiver(); //做邏輯處理
localBroadcastManager.registerReceiver(myReceiver, intentFilter); //註冊廣播
- 發送本地廣播
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); //取消註冊
}
}