1. 程式人生 > >(第一行程式碼筆記系列-廣播1)android 廣播動態註冊和靜態註冊有什麼區別及基本用法

(第一行程式碼筆記系列-廣播1)android 廣播動態註冊和靜態註冊有什麼區別及基本用法

新建一個BroadcastTest專案,然後修改MainActivity中的程式碼,如下所示:

public class MainActivity extends Activity {
	
	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 changes", Toast.LENGTH_SHORT).show();
		}

	}

}

可以看到,我們在MainActivity中定義了一個內部類NetworkChangeReceiver,這個類是繼承自BroadcastReceiver的,並重寫了父類的onReceive()方法。這樣每當網路狀態發生變化時,onReceive()方法就會得到執行,這裡只是簡單地使用Toast提示了一段文字資訊。

然後觀察onCreate()方法,首先我們建立了一個IntentFilter的例項,並給它添加了一個值為android.net.conn.CONNECTIVITY_CHANGE的action,為什麼要新增這個值呢?因為當網路狀態發生變化時,系統發出的正是一條值為android.net.conn.CONNECTIVITY_ CHANGE的廣播,也就是說我們的廣播接收器想要監聽什麼廣播,就在這裡新增相應的action就行了。接下來建立了一個NetworkChangeReceiver的例項,然後呼叫registerReceiver()方法進行註冊,將NetworkChangeReceiver的例項和IntentFilter的例項都傳了進去,這樣NetworkChangeReceiver就會收到所有值為android.net.conn.CONNECTIVITY_CHANGE的廣播,也就實現了監聽網路變化的功能。

最後要記得,動態註冊的廣播接收器一定都要取消註冊才行,這裡我們是在onDestroy()方法中通過呼叫unregisterReceiver()方法來實現的。

整體來說,程式碼還是非常簡單的,現在執行一下程式。首先你會在註冊完成的時候收到一條廣播,然後按下Home鍵回到主介面(注意不能按Back鍵,否則onDestroy()方法會執行),接著按下Menu鍵→System settings→Data usage進入到資料使用詳情介面,然後嘗試著開關Mobile Data來啟動和禁用網路,你就會看到有Toast提醒你網路發生了變化。

不過只是提醒網路發生了變化還不夠人性化,最好是能準確地告訴使用者當前是有網路還是沒有網路,因此我們還需要對上面的程式碼進行進一步的優化。修改MainActivity中的程式碼,如下所示:

public class MainActivity extends Activity {
	……
	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()方法中,首先通過getSystemService()方法得到了ConnectivityManager的例項,這是一個系統服務類,專門用於管理網路連線的。然後呼叫它的getActiveNetworkInfo()方法可以得到NetworkInfo的例項,接著呼叫NetworkInfo的isAvailable()方法,就可以判斷出當前是否有網路了,最後我們還是通過Toast的方式對使用者進行提示。

另外,這裡有非常重要的一點需要說明,Android系統為了保證應用程式的安全性做了規定,如果程式需要訪問一些系統的關鍵性資訊,必須在配置檔案中宣告許可權才可以,否則程式將會直接崩潰,比如這裡查詢系統的網路狀態就是需要宣告許可權的。開啟AndroidManifest.xml檔案,在裡面加入如下許可權就可以查詢系統網路狀態了:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcasttest"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    ……
</manifest>

靜態廣播的基本用法實現開機監聽

這裡我們準備讓程式接收一條開機廣播,當收到這條廣播時就可以在onReceive()方法裡執行相應的邏輯,從而實現開機啟動的功能。新建一個BootCompleteReceiver繼承自BroadcastReceiver,程式碼如下所示:

public class BootCompleteReceiver extends BroadcastReceiver {
	
	@Override
	public void onReceive(Context context, Intent intent) {
		Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
	}

}

可以看到,這裡不再使用內部類的方式來定義廣播接收器,因為稍後我們需要在AndroidManifest.xml中將這個廣播接收器的類名註冊進去。在onReceive()方法中,還是簡單地使用Toast彈出一段提示資訊。

然後修改AndroidManifest.xml檔案,程式碼如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcasttest"
    android:versionCode="1"
    android:versionName="1.0" >
    ……
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
		……
        <receiver android:name=".BootCompleteReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

終於,<application>標籤內出現了一個新的標籤<receiver>,所有靜態註冊的廣播接收器都是在這裡進行註冊的。它的用法其實和<activity>標籤非常相似,首先通過android:name來指定具體註冊哪一個廣播接收器,然後在<intent-filter>標籤里加入想要接收的廣播就行了,由於Android系統啟動完成後會發出一條值為android.intent.action.BOOT_COMPLETED的廣播,因此我們在這裡添加了相應的action。

另外,監聽系統開機廣播也是需要宣告許可權的,可以看到,我們使用<uses-permission>標籤又加入了一條android.permission.RECEIVE_BOOT_COMPLETED許可權。

然後將模擬器關閉並重新啟動,在啟動完成之後就會收到開機廣播了。

需要注意的是,不要在onReceive()方法中新增過多的邏輯或者進行任何的耗時操作,因為在廣播接收器中是不允許開啟執行緒的,當onReceive()方法運行了較長時間而沒有結束時,程式就會報錯。因此廣播接收器更多的是扮演一種開啟程式其他元件的角色,比如建立一條狀態列通知,或者啟動一個服務等。