第一行代碼-廣播(2)

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_CHANGEaction,網(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è),將networkChangeReceiverintentFilter兩個(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è)的方法

image.png

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


image.png

image.png

廣播接收器名默認(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)完成了,

image.png

<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)行修改,

image.png
<?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ò)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容