第一行代碼學習筆記第五章——詳解廣播機制

知識點目錄

知識點回顧

在網絡通信裏,在一個IP網絡範圍中,最大的IP地址是被保留作爲廣播地址來使用的。例如:某個網絡的IP範圍是192.168.0.XXX,子網掩碼是255.255.255.0,那麼這個網絡的廣播地址就是192.168.0.255。廣播數據包會被髮送到同一網絡上的所有端口,在該網絡中的每臺主機都會接收到這個廣播。

爲了方便進行系統級別的消息通知,Android也引入了一套類似的廣播消息機制。

5.1 廣播機制

Android中的廣播主要分爲兩種類型:標準廣播和有序廣播。

標準廣播

完全異步執行!!!在廣播發出後,所有的廣播接收器幾乎在同一時刻接受到這條廣播信息。

特點:廣播效率高、沒有任何先後順序、無法被攔截

有序廣播

同步執行!!!廣播發出後,同一時刻只會有一個廣播接收器收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞。

特點:廣播接收器有先後順序,優先級高的廣播接收器先收到廣播消息,可以被優先級高的廣播接收器攔截。

5.2 接收系統廣播

Android內置了很多系統級別的廣播:

  • 開機廣播

  • 電池電量發生變化廣播

  • 時間或時區發生改變廣播

  • 等等。。。

5.2.1 動態註冊監聽網絡變化

廣播接收器可以自由註冊自己感興趣的廣播進行註冊。註冊的方式有兩種:

  • 代碼中註冊(也稱爲動態註冊)

  • AndroidManifest.xml中註冊(也稱爲靜態註冊)

動態註冊監聽網絡變化的步驟如下:

  • 創建一個廣播接收器,繼承BroadcastReceiver,重寫onReceive()方法

      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 availabe", Toast.LENGTH_SHORT).show();
              } else {
                  Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
              }
          }
      }
    

當接收到廣播時,onReceive()方法就會執行,所以具體的邏輯就是在這個方法裏處理。

  • 在代碼中動態註冊(一般是在Activity的onCreate方法中註冊)

      IntentFilter intentFilter = new IntentFilter();
      intentFilter.addAction("android.net.com.CONNECTIVITY_CHANGE");
      mNetworkChangeReceiver = new NetworkChangeReceiver();
      registerReceiver(mNetworkChangeReceiver, intentFilter);
    

備註:訪問系統的網絡狀態需要聲明權限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  • 取消註冊

動態註冊的廣播接收器需要取消註冊,一般是在onDestroy()中取消

protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mNetworkChangeReceiver);
}

效果圖:

通過命令發送網絡改變的廣播:

am broadcast -a android.net.com.CONNECTIVITY_CHANGE

在有網和沒有網絡時的效果如下圖所示:

5.2.2 靜態註冊實現開機廣播

動態註冊的廣播接收器可以自由的註冊和註銷,但有個缺點:必須在程序啓動後才能接收到廣播,因爲註冊的邏輯是寫在onCreate()方法中。

靜態廣播可以在程序未啓動的時候就能接收到廣播。

Android Studio提供了快捷方式來創建一個廣播接收器:右擊com.example.broadcasttest包—>New—>Other—>Broadcast Receiver,

Exported屬性表示是否允許這個廣播器接收本程序之外的廣播。

Enabled屬性表示是否啓用這個廣播接收器。

Source Language可以選擇用Java或Kotlin。

靜態註冊監聽開機廣播的步驟如下:

  • 通過Android Studio快捷創建廣播接收器,並修改onReceive()中的邏輯

      public class BootCompleteReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
          }
      }
    
  • 在AndroidManifest.xml中註冊

      <receiver
          android:name=".BootCompleteReceiver"
          android:enabled="true"
          android:exported="true">
          <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED"/>
          </intent-filter>
      </receiver>
    
  • 添加監聽系統開機廣播的權限

      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    

效果圖:

通過命令發送開機廣播:

am broadcast -a android.intent.action.BOOT_COMPLETED

命令發送出去後的效果如下圖所示:

注意:
不要在onReceive()方法中添加過多的邏輯或者進行任何耗時操作,因爲廣播接收器中不允許開啓線程,當onReceive()方法運行了較長的時間而沒有結束時,程序就會報錯。

5.3 發送自定義廣播

廣播主要分爲標準廣播和有序廣播,下面分別來實踐下具體實現。

5.3.1 發送標準廣播

發送標準廣播的一般步驟如下:

  • 定義個廣播接收器

      public class MyBroadcastReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
          }
      }
    
  • 到AndroidManifest.xml中定義廣播接收器接收的action

      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="example.broadcasttest">
      	<application
    
      		......
    
              <receiver
                  android:name=".MyBroadcastReceiver"
                  android:enabled="true"
                  android:exported="true">
                  <intent-filter>
                      <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
                  </intent-filter>
              </receiver>
    
      		......
    
          </application>
      
      </manifest>
    
  • 定義一個發送廣播的觸發點,並調用sendBroadcast()發送廣播

      Button button = (Button) findViewById(R.id.button);
      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              Intent intent = new Intent("com.example.broadcasttest.MY_BROADCASTT");
              sendBroadcast(intent);
          }
      });
    

效果圖:

備註:由於廣播是使用Intent進行傳遞的,所以還可以在Intent中攜帶一些數據傳遞給廣播接收器。

5.3.2 發送有序廣播

發送有序廣播的步驟跟上面發送標準廣播的步驟一樣,只是調用的方法不一樣。

  • 使用sendOrderedBroadcast(intent,null)方法發送有序廣播

參數一:intent的對象

參數二:與權限相關的字符串,一般傳入null就行

  • 通過android.priority設置廣播接收器的優先級

      <receiver
          android:name=".MyBroadcastReceiver"
          android:enabled="true"
          android:exported="true">
          <intent-filter android:priority="100">
              <action android:name="com.example.broadcasttest.MY_BROADCASTT"/>
          </intent-filter>
      </receiver>
    
  • 可以調用abortBroadcast()方法截斷廣播

5.4 使用本地廣播

廣播是可以跨進程通信的,那麼攜帶的數據就有可能被其他程序截獲,存在一定的安全性問題。因此Android引入了一套本地廣播機制。主要是使用一個LocalBroadcastManager來對廣播進行管理。

主要用法如下:

public class MainActivity extends AppCompatActivity {


    private LocalBroadcastManager mLocalBroadcastManager;
    private LocalReceiver mLocalReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);//獲取實例
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCASTT");
                mLocalBroadcastManager.sendBroadcast(intent);//發送本地廣播
            }
        });
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCASTT");
        mLocalReceiver = new LocalReceiver();
        mLocalBroadcastManager.registerReceiver(mLocalReceiver,intentFilter);//註冊本地廣播監聽器
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocalBroadcastManager.unregisterReceiver(mLocalReceiver);//註銷本地廣播監聽器
    }

    class LocalReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "received local broadcast", Toast.LENGTH_SHORT).show();
        }
    }
}

本地廣播的使用其實跟動態註冊廣播是一樣的,只是多了一個LocalBroadcastManager對廣播的發送、註冊、註銷進行了管理。

本地廣播無法通過靜態註冊的方式來接收的,因爲靜態註冊主要就是在程序未啓動時也能接收到廣播,而發送本地廣播時,程序肯定已經啓動了。

本地廣播的優勢

  • 發送的廣播不會離開自己的程序,所以數據不會泄露

  • 其它程序無法將廣播發送到我們程序的內部,所以不會有安全漏洞隱患

  • 發送本地廣播比發送系統全局廣播更加高效

5.5 廣播的最佳實踐——實現強制下線功能

強制下線功能需求:先關閉所有的活動,然後回到登錄界面。

代碼已上傳到我的github上,需要的朋友可以點擊如下鏈接查看:

廣播的最佳實踐——實現強制下線功能

運行效果圖:

5.6 Git時間——初識版本控制工具

Git是一個開源的分佈式版本控制工具,開發者是Linux操作系統的作者Linus Torvalds。

5.6.1 安裝Git

Ubuntu系統

安裝命令如下:

sudo apt-get install git-core

Windows系統

下載地址:

點擊進入Git下載地址

點擊Download按鈕可以開始下載,下載完成後雙擊安裝包進行安裝,之後一直點擊“下一步”就可以完成安裝了。

5.6.2 創建代碼倉庫

Git可以在圖形上進行操作,但我們應該掌握Git的各種命令,因爲Git命令在不同的操作系統上都是通用的。

Linux系統是打開shell界面,Windows是打開Git Bash。

配置身份

首先應該配置身份,這樣在提交代碼的時候Git就可以知道誰提交的,具體命令如下

git config --global user.name salmonzhang

git config --global user.email [email protected]

這樣名字和郵箱就已經配置好了。

查看git用戶名和郵箱的命令是

git config --global user.name

git config --global user.email

創建代碼倉庫的命令是:

git init

在項目的根目錄下執行git init命令後會生成一個隱藏的.git文件夾,該文件夾主要用來記錄本地所有的Git操作。如果要刪除本地倉庫,也只需要刪除這個文件夾就行了。

5.6.3 提交本地代碼

主要用到的是:

git add 和 git commit

add後面可以是文件名或者目錄,commit後面通過-m參數來加上提交的描述信息。

5.7 小結與點評

本章主要學習了Android的廣播機制,掌握了接收廣播、發送自定義廣播和本地廣播的使用方法。還學習了一點Git的基本知識。

非常感謝您的耐心閱讀,希望我的文章對您有幫助。歡迎點評、轉發或分享給您的朋友或技術羣。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章