現實中:電臺要發佈消息,通過廣播把消息廣播出去,使用收音機,就可以收聽廣播,得知這條消息。Android中:系統在運行過程中,會產生許多事件,那麼某些事件產生時,比如:電量改變、收發簡訊、撥打電話、屏幕解鎖、開機,系統會發送廣播。 只要應用程式接收到這條廣播,就知道系統發生了相應的事件,從而執行相應 ...
現實中:電臺要發佈消息,通過廣播把消息廣播出去,使用收音機,就可以收聽廣播,得知這條消息。
Android中:系統在運行過程中,會產生許多事件,那麼某些事件產生時,比如:電量改變、收發簡訊、撥打電話、屏幕解鎖、開機,系統會發送廣播。
只要應用程式接收到這條廣播,就知道系統發生了相應的事件,從而執行相應的代碼。使用廣播接收者,就可以收聽廣播。
系統中任何應用只要註冊了對應了Receiver,就會接收到此Broadcast。
###創建廣播接收者
1. 定義java類繼承BroadcastReceiver
2. 在清單文件中定義receiver節點,定義name屬性,指定廣播接收者java類的全類名
3. 在intent-filter的節點中,指定action子節點,action的值必須跟要接受的廣播中的action匹配,比如,如果要接受打電話廣播,
那麼action的值必須指定為
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
* 因為打電話廣播中所包含的action,就是"android.intent.action.NEW_OUTGOING_CALL",所以我們定義廣播接收者時,
action必須與其匹配,才能收到這條廣播
* 即便廣播接收者所在進程已經被關閉,當系統發出的廣播中的action跟該廣播接收者的action匹配時,系統會啟動該廣播接收者所在的進程,
並把廣播發給該廣播接收者。
使用服務註冊廣播接收者
* Android四大組件都要在清單文件中註冊
* 廣播接收者比較特殊,既可以在清單文件中註冊,也可以直接使用代碼註冊
* 有的廣播接收者,必須代碼註冊
* 電量改變
* 屏幕鎖屏和解鎖
* 註冊廣播接收者
//創建廣播接收者對象
receiver = new ScreenOnOffReceiver();
//通過IntentFilter對象指定廣播接收者接收什麼類型的廣播
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
//註冊廣播接收者
registerReceiver(receiver, filter);
* 解除註冊廣播接收者
unregisterReceiver(receiver);
* 解除註冊之後,廣播接收者將失去作用
小案例:
#IP撥號器
> 原理:接收撥打電話的廣播,修改廣播內攜帶的電話號碼
* 定義廣播接收者接收打電話廣播
public class CallReceiver extends BroadcastReceiver {
//當廣播接收者接收到廣播時,此方法會調用
@Override
public void onReceive(Context context, Intent intent) {
//拿到用戶撥打的號碼
String number = getResultData();
//修改廣播內的號碼
setResultData("17951" + number);
}
}
* 在清單文件中定義該廣播接收者接收的廣播類型
<receiver android:name="com.itheima.ipdialer.CallReceiver">
<intent-filter >
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
* 接收打電話廣播需要許可權
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
* 即使廣播接收者的進程沒有啟動,當系統發送的廣播可以被該接收者接收時,系統會自動啟動該接收者所在的進程。
#簡訊攔截器
>系統收到簡訊時會產生一條廣播,廣播中包含了簡訊的號碼和內容
* 系統發送簡訊廣播時,是怎麼把簡訊內容存入廣播的,我們就只能怎麼取出來
* 如果簡訊過長,那麼發送時會拆分成多條簡訊發送,那麼簡訊廣播中就會包含多條簡訊
* 定義廣播接收者接收簡訊廣播
public void onReceive(Context context, Intent intent) {
//拿到廣播里攜帶的簡訊內容
Bundle bundle = intent.getExtras();
Object[] objects = (Object[]) bundle.get("pdus");
for(Object ob : objects ){
//通過object對象創建一個簡訊對象
SmsMessage sms = SmsMessage.createFromPdu((byte[])ob);
System.out.println(sms.getMessageBody());
System.out.println(sms.getOriginatingAddress());
}
}
* 系統創建廣播時,把簡訊存放到一個數組,然後把數據以pdus為key存入bundle,再把bundle存入intent
* 清單文件中配置廣播接收者接收的廣播類型,註意要設置優先順序屬性,要保證優先順序高於簡訊應用,才可以實現攔截
<receiver android:name="com.itheima.smslistener.SmsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
* 添加許可權
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
* 4.0以後廣播接收者安裝以後必須手動啟動一次,否則不生效
* 4.0以後廣播接收者如果被手動關閉,就不會再啟動了
#監聽SD卡狀態
* 清單文件中定義廣播接收者接收的類型,監聽SD卡常見的三種狀態,所以廣播接收者需要接收三種廣播
<receiver android:name="com.itheima.sdcradlistener.SDCardReceiver">
<intent-filter >
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<action android:name="android.intent.action.MEDIA_REMOVED"/>
<data android:scheme="file"/>
</intent-filter>
</receiver>
* 廣播接收者的定義
public class SDCardReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 區分接收到的是哪個廣播
String action = intent.getAction();
if(action.equals("android.intent.action.MEDIA_MOUNTED")){
System.out.println("sd卡就緒");
}
else if(action.equals("android.intent.action.MEDIA_UNMOUNTED")){
System.out.println("sd卡被移除");
}
else if(action.equals("android.intent.action.MEDIA_REMOVED")){
System.out.println("sd卡被拔出");
}
}
}
#勒索軟體
* 接收開機廣播,在廣播接收者中啟動勒索的Activity
* 清單文件中配置接收開機廣播
<receiver android:name="com.itheima.lesuo.BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
* 許可權
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
* 定義廣播接收者
@Override
public void onReceive(Context context, Intent intent) {
//開機的時候就啟動勒索軟體
Intent it = new Intent(context, MainActivity.class);
context.startActivity(it);
}
* 以上代碼還不能啟動MainActivity,因為廣播接收者的啟動,並不會創建任務棧,那麼沒有任務棧,就無法啟動activity
* 手動設置創建新任務棧的flag
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
#監聽應用的安裝、卸載、更新
> 原理:應用在安裝卸載更新時,系統會發送廣播,廣播里會攜帶應用的包名
* 清單文件定義廣播接收者接收的類型,因為要監聽應用的三個動作,所以需要接收三種廣播
<receiver android:name="com.itheima.app.AppReceiver">
<intent-filter >
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
* 廣播接收者的定義
public void onReceive(Context context, Intent intent) {
//區分接收到的是哪種廣播
String action = intent.getAction();
//獲取廣播中包含的應用包名
Uri uri = intent.getData();
if(action.equals("android.intent.action.PACKAGE_ADDED")){
System.out.println(uri + "被安裝了");
}
else if(action.equals("android.intent.action.PACKAGE_REPLACED")){
System.out.println(uri + "被更新了");
}
else if(action.equals("android.intent.action.PACKAGE_REMOVED")){
System.out.println(uri + "被卸載了");
}
}
#廣播的兩種類型
* 無序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播,並且是沒有先後順序(同時收到)
* 有序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播,但是會按照廣播接收者的優先順序來決定接收的先後順序
* 優先順序的定義:-1000~1000
* 最終接收者:所有廣播接收者都接收到廣播之後,它才接收,並且一定會接收
* abortBroadCast:阻止其他接收者接收這條廣播,類似攔截,只有有序廣播可以被攔截