Broadcast(廣播)
注:本章內容多數摘自郭霖大神的《第一行代碼-Android》,因為書上這一章寫的很完美了,我自己再另寫就有些多余了,但由于第二版《第一行代碼》書籍年代久遠,書上這一章有一小部分細節對于新版安卓系統有不適用、需要改動的地方,本文會將這些會踩的坑指出來
一、接收系統廣播
1、動態注冊監聽網路變化
接收系統廣播必須先創建廣播接收器,就是新建一個類,讓他繼承自BroadcastReceiver,并重寫父類的onReceiver()就行了,這樣當有廣播到來時,onReceiver()方法就會執行
新建一個BroadcastTest專案
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 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 chages",Toast.LENGTH_LONG).show();
}
}
}
系統網路狀態變化時,系統發出的就是android.net.conn.CONNECTIVITY_CHANGE這條廣播,因此intentFilter需要添加這個值,因此每次網路狀態變化時都會觸發廣播接收器的onReceive()方法
這樣的話,只能得到網路狀態改變的提示,但不知道具體是連接了網路還是斷開了網路,我們對NetworkChangeReceiver類的代碼改進一下
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 intentFilter=new IntentFilter();
//系統網路狀態變化時,系統發出的就是android.net.conn.CONNECTIVITY_CHANGE這條廣播
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) {
//收到廣播
ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
if(networkInfo!=null && networkInfo.isAvailable()){
Toast.makeText(context,"network is available",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(context,"network is unavailabe",Toast.LENGTH_LONG).show();
}
}
}
}
ConnectivityManager是一個系統服務類,專門管理網路連接的,然后呼叫getActivityNetworkInfo()方法就可以得到NetworkInfo的實體,接著呼叫NetworkInfo的isAvailable()方法,就可以判斷出是否有網路了
這里的訪問網路狀態是需要宣告權限的
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
這樣動態注冊就結束了,具體的效果可以自己測驗
2、靜態注冊實作開機注冊
先創建一個廣播接收器(package->New->Other->Broadcast Receiver),命名為BootCompleteReceiver,并修改BootCompleteReceiver中的代碼
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Boot Complete",Toast.LENGTH_LONG).show();
}
}
靜態注冊的廣播接收器一定要在AndroidManifest.xml檔案中注冊才可以使用,不過由于我們是使用AndroidStudio的快捷方式創建的廣播接收器,因此注冊這一步已經被自動完成了,
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true"></receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
可以看到,標簽內出現了一個新的標簽,所有靜態的廣播接收器都是在這里進行注冊的,它的用法其實和標簽非常相似,通過android:name來指定具體注冊哪一個廣播接收器
有了BootCompleteReceiver這個廣播接收器還是不能接收到開機廣播的,需要宣告監聽開機廣播權限,并且修改標簽
<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"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
這樣就實作了接收開機廣播了,將模擬器關閉并重新啟動,在啟動完成后就會接收到開機廣播
總結:在靜態注冊廣播中,需要將想要接收的廣播填寫到標簽下!相應的觸發事件寫在廣播接收器的onReceive()里面
提示:以上代碼在模擬器上測驗是有效的,但可能到了真機會失效,具體原因見鏈接開機廣播接收不到的原因 解決不了也不要緊,因為重點不在開機廣播,而在于靜態廣播的原理的學習
3、自定義廣播
(1)發送標準廣播
我們先新建一個廣播接收器來接收廣播
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_LONG).show();
}
}
然后在AndroidManifest.xml中對這個廣播接收器的標簽進行修改
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST"></action>
</intent-filter>
</receiver>
我們定義一個按鈕來發送廣播
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:text="Send Broadcast"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
接著撰寫按鈕事件
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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_BROADCAST");
//重點!必須設定包名!不然發送不出去
intent.setPackage(getPackageName());
sendBroadcast(intent);
}
});
}
}
發送廣播的時候一定要給intent設定包名,這是新版安卓的特性,不加不給用,老版本安卓可以不加
現在點擊按鈕后,就會觸發廣播了

(2)發送廣播給別的程式
步驟同(1),但要注意將setPackage()的引數填成要發送的程式的包名!!
4、使用本地廣播
本地廣播顧名思義,就是防止全域廣播引起的安全性問題,這種廣播只有自己的程式可以接收
這里直接修改JAVA原始碼,和普通的動態注冊差不多
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//獲取實體
localBroadcastManager=LocalBroadcastManager.getInstance(this);
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_BROADCAST");
//本地廣播可以不設定包名
//intent.setPackage(getPackageName());
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter=new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver=new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received local broadcast",Toast.LENGTH_SHORT).show();
}
}
}
到這里文章就結束了,寫了足足3個小時,期間吃了一桶泡面,2包干脆面,看了20分鐘電影,又聊了會QQ,在快樂的氛圍中我已經把廣播的內容從接近遺忘到爛熟于心,寫博客的用處真的非同凡響!一日一更,加油加油加油
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/225388.html
標籤:其他
上一篇:Android - 有趣的版本號
