1. 系統廣播 1.1 動態註冊 (1)創建自定義接收器類繼承自BroadcaseReceiver,實現onReceive()方法,對接收到的廣播的邏輯處理就是寫在這個函數中的。 (2)實例化IntentFilter對象,並通過addAction()方 ...
1. 系統廣播
1.1 動態註冊
(1)創建自定義接收器類繼承自BroadcaseReceiver,實現onReceive()方法,對接收到的廣播的邏輯處理就是寫在這個函數中的。
(2)實例化IntentFilter對象,並通過addAction()方法加入需要接收的廣播值。使用系統廣播時可查閱官方文檔,找到需要的Action。
(3)實例化自定義接收器類的對象,並通過registerReceiver()方法註冊接收器對象。
(4)在AndroidManifest.xml文件中,通過uses=permission標簽進行許可權聲明。若非系統的關鍵性信息,則無需這一步。
(5)使用完後,動態註冊的廣播接收器一定要通過unregisterReceiver()方法取消註冊。
範例: 監測當前網路狀態,若斷網,則提示用戶當前網路不可用。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.studying.myapplication">
<!--聲明許可權-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".BroadcaseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
活動類:
public class BroadcaseActivity extends Activity {
private IntentFilter mFilter;
private NetworkChangeReceiver mReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcase);
//實例化IntentFilter對象,並加入Action
mFilter = new IntentFilter();
mFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
mReceiver = new NetworkChangeReceiver();
//註冊接收器
registerReceiver(mReceiver, mFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//動態註冊的廣播接收器一定要取消註冊
unregisterReceiver(mReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//獲取網路狀態信息
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//當網路信息對象為空或者網路不可用時,提示用戶
if (networkInfo == null || !networkInfo.isAvailable()) {
Toast.makeText(context, "Network is unavailable.", Toast.LENGTH_SHORT).show();
}
}
}
}
1.2 靜態註冊
相對動態註冊而言,靜態註冊接收器非常簡單,只需要自定義一個接收器類,而後實現onReceive()方法,在裡面實現對廣播的處理,然後在AndroidManifest.xml文件中通過receiver標簽進行註冊即可。需要註意,無論是靜態註冊還是動態註冊,如果需要訪問系統的關鍵性信息,都必須在配置文件中聲明許可權。
範例: 靜態註冊實現開機自啟。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.studying.myapplication">
<!--聲明許可權-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--通過receiver標簽靜態註冊-->
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity android:name=".BroadcaseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
自定義接收器類:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete..", Toast.LENGTH_SHORT).show();
}
}
2. 自定義廣播
2.1 標準廣播
自定義廣播的接收方法與系統廣播的一樣,也有靜態註冊和動態註冊兩種方法,這裡就不再贅述。
自定義廣播的不同之處在於,它是手動發送的,方法是新建一個Intent對象並加入自定義的廣播值,而後通過sendBroadcase()方法發送,此時發送出去的就是一條標準廣播。
範例: 發送一條自定義標準廣播並接收。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.studying.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--通過receiver標簽靜態註冊-->
<receiver android:name=".MyReceiver" >
<intent-filter>
<action android:name="com.studying.MyBroadcast" />
</intent-filter>
</receiver>
<activity android:name=".BroadcaseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
自定義接收器類:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received.", Toast.LENGTH_SHORT).show();
}
}
佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.studying.myapplication.BroadcaseActivity">
<Button
android:id="@+id/send"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Send MyBroadcase" />
</LinearLayout>
活動類:
public class BroadcaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcase);
Button send = (Button) findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//實例化一個Intent對象,併發送廣播
Intent intent = new Intent("com.studying.MyBroadcast");
sendBroadcast(intent);
}
});
}
}
2.2 有序廣播
與標準廣播不同之處在於,標準廣播是非同步執行的,所有廣播接收器會在同一時刻接收到;而有序廣播是同步執行的,同一時刻只會有一個接收器收到,當這個接收器裡面的邏輯執行完畢後,廣播才會繼續傳播。
因此,有序廣播有兩個要點,第一,優先順序高的接收器可以先收到廣播,優先順序高低通過priority給定;第二,前面的接收器可以截斷,讓後面的接收器無法收到廣播,這個則是通過abortBroadcase()方法實現。
此外,有序廣播是通過sendOrderedBroadcase()方法進行發送的。
範例: 創建兩個自定義廣播類,並且讓MyReceiver1的優先順序高於MyReceiver2,而後在MyReceiver1中調用abortBroadcase()方法截斷廣播的傳遞。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.studying.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--使MyReceiver1的優先順序高於MyReceiver2的-->
<receiver android:name=".MyReceiver1" >
<intent-filter android:priority="100">
<action android:name="com.studying.MyBroadcast" />
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver2" >
<intent-filter android:priority="50">
<action android:name="com.studying.MyBroadcast" />
</intent-filter>
</receiver>
<activity android:name=".BroadcaseActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
佈局文件與標準廣播的範例一樣:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.studying.myapplication.BroadcaseActivity">
<Button
android:id="@+id/send"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Send MyBroadcase" />
</LinearLayout>
活動類:
public class BroadcaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcase);
Button send = (Button) findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//發送有序廣播
Intent intent = new Intent("com.studying.MyBroadcast");
sendOrderedBroadcast(intent, null);
}
});
}
}
MyReceiver1:
public class MyReceiver1 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received in MyReceiver1.", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
MyReceiver2:
public class MyReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received in MyReceiver2.", Toast.LENGTH_SHORT).show();
}
}
若把MyReceiver1中的abortBroadcase();這一句註釋掉,點擊發送則可一次看到兩個接收器的提示。
3. 本地廣播
本地廣播只能夠在應用程式內部進行傳遞,廣播接收器也只能接收本程式發出的廣播,這樣的機制解決了全局廣播可能出現的安全問題。
使用本地廣播非常簡單,與全局廣播不一樣的地方在於,使用了一個LocalBroadcastManager對廣播進行管理,使用這個管理器發送的廣播以及註冊的接收器,即為本地廣播和本地廣播接收器。
另外,由於發送本地廣播時,程式必定處於啟動狀態,因而不需要並且也沒有靜態註冊。
範例: 發送一條本地廣播並接收。
活動類:
public class BroadcaseActivity extends Activity {
private MyReceiver mReceiver;
private LocalBroadcastManager mManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcase);
//獲取本地廣播管理器
mManager = LocalBroadcastManager.getInstance(this);
Button send = (Button) findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通過本地廣播管理器發送廣播
Intent intent = new Intent("com.studying.MyLocalBroadcast");
mManager.sendBroadcast(intent);
}
});
//通過本地廣播管理器進行動態註冊
IntentFilter mFilter = new IntentFilter();
mFilter.addAction("com.studying.MyLocalBroadcast");
mReceiver = new MyReceiver();
mManager.registerReceiver(mReceiver, mFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//通過本地廣播管理器取消註冊
mManager.unregisterReceiver(mReceiver);
}
//自定義接收器類
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received.", Toast.LENGTH_SHORT).show();
}
}
}
最後,在使用廣播接收器時要註意,不要在onReceive()方法中加任何耗時操作,廣播接收器更多的是接收某些廣播訊息,從而開啟其它組件。在廣播接收器中是不允許開啟線程的,當onReceive()方法運行了長時間仍未結束時,程式就會報錯。