1.接收系統(tǒng)廣播
1.1動(dòng)態(tài)注冊(cè)監(jiān)聽網(wǎng)絡(luò)變化
注冊(cè)的目的與意義
廣播接收器可以自由地對(duì)自己感興趣的廣播進(jìn)行注冊(cè),這樣有相應(yīng)的廣播發(fā)出的時(shí)候,廣播接收器就能夠接受到該廣播(注冊(cè)的目的與意義)
誰(shuí)來(lái)注冊(cè):廣播接收器
注冊(cè)的方式
動(dòng)態(tài)注冊(cè):在代碼中注冊(cè);
靜態(tài)注冊(cè):在清理文件(AndroidManifest.xml)中注冊(cè);
注意點(diǎn):動(dòng)態(tài)注冊(cè)的廣播接收器一定都要取消注冊(cè)才可,這里是在onDestroy()方法里面
調(diào)用unregisterReceiver()實(shí)現(xiàn)
如何創(chuàng)建一個(gè)廣播接收器
新建一個(gè)類,讓它繼承自BroadcastReceiver,同時(shí)重寫父類的OnReceiver()方法即可
這樣當(dāng)有廣播到來(lái)的時(shí)候,OnReceiver()方法就會(huì)得到執(zhí)行,下面通過(guò)動(dòng)態(tài)注冊(cè)的方式編寫一個(gè)能夠監(jiān)聽網(wǎng)絡(luò)變化的程序,源代碼如下:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network is unavailable",
Toast.LENGTH_SHORT).show();
}
}
}
內(nèi)部類NetworkChangeReceiver 繼承自BroadcastReceiver,并重寫了onReceive方法,網(wǎng)絡(luò)一旦發(fā)生變化,onReceive方法就會(huì)得到執(zhí)行;
onCreate方法中:
1)先創(chuàng)建了一個(gè)IntentFilter實(shí)例,并給其添加一個(gè)
android.net.conn.CONNECTIVITY_CHANGE的action,網(wǎng)絡(luò)狀態(tài)發(fā)生變化,系統(tǒng)發(fā)出的正是一條值為android.net.conn.CONNECTIVITY_CHANGE的廣播,也就是說(shuō)廣播接收器想要監(jiān)聽什么廣播,就在這里添加相應(yīng)的action(利用addAction);
2)接下來(lái)創(chuàng)建一個(gè)NetworkChangeReceiver的實(shí)例,然后調(diào)用registerReceiver()方法進(jìn)行注冊(cè),將networkChangeReceiver和intentFilter兩個(gè)實(shí)例都傳進(jìn)去了,這樣NetworkChangeReceiver就會(huì)收到所有值為android.net.conn.CONNECTIVITY_CHANGE的廣播(聯(lián)系上文),進(jìn)而實(shí)現(xiàn)監(jiān)聽網(wǎng)絡(luò)變化的功能;
注意點(diǎn):動(dòng)態(tài)注冊(cè)的廣播接收器一定都要取消注冊(cè)才可,這里是在onDestroy()方法里面
調(diào)用unregisterReceiver()實(shí)現(xiàn)
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectionManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(context, "network is available",
Toast.LENGTH_SHORT).show(); }
else {
Toast.makeText(context, "network is unavailable",
Toast.LENGTH_SHORT).show();
}
}
}
在OnReceive()方法中:
1.首先通過(guò)getSystemService得到connectionManager的實(shí)例,這是一個(gè)系統(tǒng)服務(wù)類,專門用于管理網(wǎng)絡(luò)連接的;
2.然后調(diào)用它的getActiveNetworkInfo()方法得到NetworkInfo的實(shí)例;
3.接著調(diào)用NetworkInfo的isAvailable()方法,就可以判斷出是否有網(wǎng)絡(luò)連接
注意:
如果程序需要進(jìn)行一些對(duì)用戶來(lái)說(shuō)比較敏感的操作,就必須在配置文件中聲明權(quán)限才可以,否則程序?qū)⒅苯颖罎?比如這里訪問(wèn)系統(tǒng)的網(wǎng)絡(luò)狀態(tài)就需要聲明權(quán)限,打開AndroidManifest.xml文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
...
1.2靜態(tài)注冊(cè)實(shí)現(xiàn)開機(jī)啟動(dòng)
動(dòng)態(tài)注冊(cè)有一個(gè)缺點(diǎn):必須要在開機(jī)之后才能接收廣播,因?yàn)樽?cè)的邏輯是寫在onCreate()方法中的;
靜態(tài)注冊(cè)的目的
為了讓程序在為啟動(dòng)的情況下接收到廣播,需要使用靜態(tài)注冊(cè)的方法

我們準(zhǔn)備讓程序收到一條開機(jī)廣播,當(dāng)收到這條廣播的時(shí)候可以在OnReceive()方法里面執(zhí)行相應(yīng)的邏輯,從而實(shí)現(xiàn)開機(jī)的功能;(過(guò)程見上面和下面的圖)


廣播接收器名默認(rèn)為:MyReceiver,改為:BootCompleteReceiver (這里沒有改)
Exported表示是否允許這個(gè)廣播接收器接受本程序以外的廣播;
Enabled屬性表示是否啟用這個(gè)廣播接收器
package com.example.broadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
靜態(tài)的廣播接收器一定要在清單文件中注冊(cè)才可以使用,不過(guò)由于我們是使用安卓的快捷方式創(chuàng)建的廣播接收器,注冊(cè)這一步被自動(dòng)完成了,

<application>標(biāo)簽內(nèi)出現(xiàn)了一個(gè)新的標(biāo)簽<receiver>,其用法和<activity>類似,通過(guò)android:name來(lái)指定具體注冊(cè)哪一個(gè)廣播接收器,Exported和Enabled屬性根據(jù)我們剛才勾選的自動(dòng)生成,不過(guò)目前此接收器還是不能接收到開機(jī)廣播,需要對(duì)清單文件(AndroidManifest.xml)進(jìn)行修改,

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
</application>
</manifest>
1.安卓系統(tǒng)啟動(dòng)完成之后會(huì)發(fā)出一條值為android.intent.action.BOOT_COMPLETED的廣播,因此在</intent-filter>標(biāo)簽里面添加了相應(yīng)的action(靠近最后的地方);
2.除此之外,監(jiān)聽系統(tǒng)開機(jī)廣播也是需要聲明權(quán)限的,故<uses-permission >標(biāo)簽加了
android:name="android.permission.RECEIVE_BOOT_COMPLETED權(quán)限
將模擬器關(guān)閉重新啟動(dòng)即可.
靜態(tài)注冊(cè)小結(jié):
1.右擊創(chuàng)建接收器,(清單文件中自動(dòng)完成注冊(cè))
2.在</intent-filter>標(biāo)簽(清單文件中)里面添加相應(yīng)的action
3.監(jiān)聽系統(tǒng)開機(jī)廣播需要聲明權(quán)限
注意點(diǎn):
接收器的OnReceive()方法中不要添加過(guò)多的邏輯,廣播接收器是不允許開啟線程,當(dāng)此方法運(yùn)行了較長(zhǎng)時(shí)間而沒有結(jié)束的時(shí)候,程序會(huì)報(bào)錯(cuò)!