1、接收系統的廣播----使用動態註冊監控網絡的變化
廣播接收器可以自由地對自己感興趣的廣播進行註冊,這樣當有相應的廣播發出時,廣播接收器就能夠收到該廣播,並在內部處理相應的邏輯。一般的註冊廣播有兩種形式1、動態註冊 (即在java代碼中註冊) 2、靜態註冊 (在AndroidManifest.xml 中註冊),這裏使用的是動態註冊的形式。
那麼該如何創建一個廣播接收器呢?其實只需要新建一個類, 讓它繼承自BroadcastReceiver,並重寫父類的 onReceive()方法就行了。 這樣當有廣播到來時, onReceive()方法就會得到執行,具體的邏輯就可以在這個方法中處理。
class NetworkChangeReceiver extends BroadcastReceiver {
// 重寫onReceive
@Override
public void onReceive(Context context, Intent intent) {
// 用getSystemService()得到系統服務類,專門用於管理網絡連接
ConnectivityManager connect = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// 調用getActiveNetworkInfo(),得到NetworkInfo實例
NetworkInfo networkinfo = connect.getActiveNetworkInfo();
// 調用NetworkInfo的isAvailable()方法,判斷是否有網絡連接
if (networkinfo != null && networkinfo.isAvailable()) {
Toast.makeText(MainActivity.this, "網絡可用!", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(MainActivity.this, "網絡不可用,請檢查您的網絡!",
Toast.LENGTH_SHORT).show();
}
}
}
看看MainActivity中的代碼,當然也可以把上面的類用內部類的形式寫到MainActivity中
public class MainActivity extends Activity {
private Button btn1;
private IntentFilter intentFilter;
private NetworkChangeReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = (Button) findViewById(R.id.btn_01);
// 使用Button的單擊事件,來開啓動態註冊,監聽網絡的改變
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
// 創建NetworkChangeReceiver實例
receiver = new NetworkChangeReceiver();
// 創建一個InIntentFilter的實例
intentFilter = new IntentFilter();
// 添加一個名爲android.net.conn.CONNECTIVITY_CHANGE的action,表示我們的接收器要監聽的廣播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
// 註冊,NetworkChangeReceiver就會收到所有值爲
// android.net.conn.CONNECTIVITY_CHANGE的廣播
registerReceiver(receiver, intentFilter);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
}
添加權限,來查詢系統網絡狀態
<!-- 添加系統網絡狀態訪問的權限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
2、接收系統廣播----使用靜態註冊實現開機自啓接收廣播
動態註冊的廣播接收器可以自由地控制註冊與註銷,在靈活性方面有很大的優勢,但是它也存在着一個缺點,即必須要在程序啓動之後才能接收到廣播,因爲註冊的邏輯是寫在onCreate()方法中的。那麼有沒有什麼辦法可以讓程序在未啓動的情況下就能接收到廣播呢?這就需要使用靜態註冊的方式了。
這裏我們準備讓程序接收一條開機廣播, 當收到這條廣播時就可以在 onReceive()方法裏執行相應的邏輯,從而實現開機啓動的功能。新建一個 BootCompleteReceiver 繼承自BroadcastReceiver,不能再使用內部類的形式寫在MainActivity中。
//定義一個類BootCompleteReceiver,繼承BroadcastReceiver,來實現靜態註冊,開機自啓的廣播的接收
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "靜態註冊,開機自啓,成功!", Toast.LENGTH_SHORT).show();
}
}
看看MainActivity中的代碼public class MainActivity extends Activity {
private Button btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);}
}
可以看到,這裏不再使用內部類的方式來定義廣播接收器,因爲稍後我們需要在AndroidManifest.xml 中將這個廣播接收器的類名註冊進去。終於,<application>標籤內出現了一個新的標籤<receiver>,所有靜態註冊的廣播接收器都是在這裏進行註冊的。它的用法其實和<activity>標籤非常相似,首先通過 android:name來指定具體註冊哪一個廣播接收器, 然後在<intent-filter>標籤里加入想要接收的廣播就行了,由於Android系統啓動完成後會發出一條值爲android.intent.action.BOOT_COMPLETED的廣播,因此我們在這裏添加了相應的 action。
<!-- 註冊一個廣播接收器,將廣播接收器的類名註冊進去,開機自啓的接收器 -->
<receiver android:name="com.example.tset.demon06.BootCompleteReceiver">
<intent-filter >
<!-- 加入想要接收 的廣播 -->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
添加開機自啓的權限
<!--添加程序開機自啓的權限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
3、發送自定義的標準廣播在發送廣播之前,我們還是需要先定義一個廣播接收器來準備接收此廣播才行,不然發出去也是白髮。因此新建一個 MyBroadcastReceiver繼承自 BroadcastReceiver
//定義一個類MyBroadcastReceiver,繼承BroadcastReceiver,來實現標準廣播的接收
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到自定義標準廣播", Toast.LENGTH_SHORT).show();
}
}
這裏當 MyBroadcastReceiver收到自定義的廣播時,就會彈出"收到自定義標準廣播"的提示,然後在 AndroidManifest.xml 中對這個廣播接收器進行註冊。可 以 看 到 , 這 裏 讓 MyBroadcastReceiver 接 收 一 條 值 爲“com.example.test.demon6.myBroadcast”的廣播,因此待會兒在發送廣播的時候,我們就需要發出這樣的一條廣播。
<!-- 註冊一個廣播接收器,將廣播接收器的類名註冊進去,自定義標準廣播的接收器 -->
<receiver android:name="com.example.tset.demon06.MyBroadcastReceiver">
<intent-filter >
<!-- 加入想要接收 的廣播,讓他接收到一條值爲com.example.tset.demon06.myBroadcast的廣播 -->
<action android:name="com.example.tset.demon06.myBroadcast"/>
</intent-filter>
</receiver>
看看activity中的代碼
public class MainActivity extends Activity {
private Button btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn2 = (Button) findViewById(R.id.btn_02);
// 使用Button的單擊事件,來發送標準廣播
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent("com.example.tset.demon06.myBroadcast");
// 也可以在這裏使用Intent傳值給廣播接收器
// 發送廣播,這條廣播的值爲com.example.tset.demon06.myBroadcast
sendBroadcast(intent);
}
});
}
}
4、發送自定義有序廣播廣播主要分爲兩種類型,標準廣播和有序廣播。有序廣播(Ordered broadcasts)則是一種同步執行的廣播,在廣播發出之後,同一時刻只會有一個廣播接收器能夠收到這條廣播消息,當這個廣播接收器中的邏輯執行完畢後,廣播纔會繼續傳遞。所以此時的廣播接收器是有先後順序的,優先級高的廣播接收器就可以先收到廣播消息,並且前面的廣播接收器還可以截斷正在傳遞的廣播,這樣後面的廣播接收器就無法收到廣播消息了。標準廣播(Normal broadcasts)是一種完全異步執行的廣播,在廣播發出之後,所有的廣播接收器幾乎都會在同一時刻接收到這條廣播消息,因此它們之間沒有任何先後順序可言。這種廣播的效率會比較高,但同時也意味着它是無法被截斷的。
在發送廣播之前,我們還是需要先定義一個廣播接收器來準備接收此廣播才行,不然發出去也是白髮。因此新建一個 OrderBroadcastReceiver繼承自 BroadcastReceiver
public class OrderBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到自定義有序廣播", Toast.LENGTH_SHORT).show();
//截斷廣播,後面的程序就不能收到這條有序廣播了
abortBroadcast();
}
}
<!-- 註冊一個廣播接收器,將廣播接收器的類名註冊進去,自定義有序廣播的接收器 -->
<receiver android:name="com.example.tset.demon06.OrderBroadcastReceiver">
<!-- 設置優先級爲100 -->
<intent-filter android:priority="100">
<!-- 加入想要接收 的廣播,讓他接收到一條值爲com.example.tset.demon06.myBroadcast的廣播 -->
<action android:name="com.example.tset.demon06.orderBroadcast"/>
</intent-filter>
</receiver>
<span style="white-space:pre"> </span>public class MainActivity extends Activity {
<span style="white-space:pre"> </span>private Button btn3;
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>protected void onCreate(Bundle savedInstanceState) {
<span style="white-space:pre"> </span>super.onCreate(savedInstanceState);
<span style="white-space:pre"> </span>setContentView(R.layout.activity_main);
<span style="white-space:pre"> </span>btn3 = (Button) findViewById(R.id.btn_03);
<span style="white-space:pre"> </span>// 使用Button的單擊事件,來發送有序廣播
<span style="white-space:pre"> </span>btn3.setOnClickListener(new OnClickListener() {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void onClick(View v) {
<span style="white-space:pre"> </span>// TODO Auto-generated method stub
<span style="white-space:pre"> </span>Intent intent = new Intent("com.example.tset.demon06.orderBroadcast");
<span style="white-space:pre"> </span>// 發送廣播,這條廣播的值爲com.example.tset.demon06.myBroadcast
<span style="white-space:pre"> </span>sendOrderedBroadcast(intent,null);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>}
}
可以看到有序廣播的發送和標準廣播差不多,就是我們通過 android:priority 屬性給廣播接收器設置了優先級,優先級比較高的廣播接收器就可以先收到廣播。 這裏將 MyBroadcastReceiver的優先級設成了 100。和發送的方法不一樣。其中還在接收廣播的時候把廣播截斷了 ,其他地方就不能接收了 。
5、使用本地廣播
前面我們發送和接收的廣播全部都是屬於系統全局廣播, 即發出的廣播可以被其他任何的任何應用程序接收到,並且我們也可以接收來自於其他任何應用程序的廣播。這樣就很容易會引起安全性的問題, 比如說我們發送的一些攜帶關鍵性數據的廣播有可能被其他的應用程序截獲,或者其他的程序不停地向我們的廣播接收器裏發送各種垃圾廣播。爲了能夠簡單地解決廣播的安全性問題,Android 引入了一套本地廣播機制,使用這個機制發出的廣播只能夠在應用程序的內部進行傳遞,
並且廣播接收器也只能接收來自本應用程序發出的廣播,這樣所有的安全性問題就都不存在了。本地廣播的用法並不複雜,主要就是使用了一個 LocalBroadcastManager 來對廣播進行
管理,並提供了發送廣播和註冊廣播接收器的方法。
public class MainActivity extends Activity {
private Button btn4;
private IntentFilter intentFilter1;
private LocalBroadcastManager manager;
private LocalReceiver localReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn4 = (Button) findViewById(R.id.btn_04);
manager = LocalBroadcastManager.getInstance(MainActivity.this);
btn4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
manager.sendBroadcast(intent);
}
});
//創建IntentFilter實例
intentFilter1 = new IntentFilter();
//添加一個名爲com.example.broadcasttest.LOCAL_BROADCAST的action,表示我們的接收器要監聽的廣播
intentFilter1.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
//創建LocalReceiver實例
localReceiver = new LocalReceiver();
//使用LocalBroadcastManager來註冊廣播
manager.registerReceiver(localReceiver, intentFilter1);
}
// 定義一個內部類LocalReceiver,繼承BroadcastReceiver,來實現動態註冊本地廣播接收器
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "接收到本地廣播",Toast.LENGTH_SHORT).show();
}
}
}
有沒有感覺這些代碼很熟悉?沒錯,其實這基本上就和我們前面所學的動態註冊廣播接收器以及發送廣播的代碼是一樣。只不過現在首先是通過 LocalBroadcastManager的 getInstance()方法得到了它的一個實例,然後在註冊廣播接收器的時候調用的是 LocalBroadcastManager的 registerReceiver()方法,在發送廣播的時候調用的是LocalBroadcastManager的 sendBroadcast()方法,僅此而已。以上代碼的UI都非常簡單,只有幾個Button,就不給出具體的佈局
這些筆記乃是作者讀《第一行代碼》整理所得。