導讀:本文敘述如何先於某些僞殺毒軟件、病毒、常規軟件獲取到短信
注意:如果你想搶先接收到短信,請務必閱讀我上一篇文章,先要保證你的應用最先開機啓動
衆所周知,android系統在收到短信息的時候會發送廣播,但是此廣播是有序廣播,也就是說:先接收到廣播的人,如果心情不好,它就不會向後傳遞此廣播,後面的人就不會知道有短信到來
這與無序廣播不同,無序廣播並不是真的沒有順序(只是似乎大家習慣這麼叫而已),無序廣播的接收者也是排隊等待廣播的,只不過是在傳遞過程中,大家必須遵守規則,一直把消息傳遞給最後一個人纔可以
關於無序廣播與靜態接收器搭配的接收順序,上一篇文章已經說的很清楚了
由於開機之後程序都沒有開始運行,所以想自動運行必須要接收
現在我們看看程序啓動之後的情況,我以大家關心的接收短消息爲例
想要在程序中接收短信,就要接收如下廣播
android.provider.Telephony.SMS_RECEIVED
系統把它作爲有序廣播進行發送,那麼,誰第一個接收到短信將變得至關重要,無論你是殺毒軟件、僞殺毒軟件、病毒還是普通程序
之前說過靜態接收器的接收順序
那麼動態接收器和靜態接收器相比呢?
如果是接收靜態廣播
答案是靜態接收器優先級低於動態接收器,也就是說,無論多麼高級別的靜態接收器和多麼低級別的動態接收器都接收同一廣播,永遠都是動態接收器先接收到!
動態接收器是在代碼中設置的,所以,我們需要先啓動程序,才能接收廣播,這也是我們無法用它接收開機廣播的原因
如果是接收動態廣播
同優先級的,動態接收器先接收到廣播,靜態後接收到
同樣的,動態接收器也可以設置優先級,高優先級的接收器會在低優先級的接收器之前接收到廣播
那麼,同樣優先級的動態接收器,接收廣播的順序是怎樣的呢?
幸好,他們的規則與靜態接收器的規則不同
同樣優先級的動態接收器,誰先註冊到系統,誰就搶先接收到廣播
上面雖然完全只是文字敘述,但我相信,大家也是看明白了的
下面總結一下,如何能保證自己的程序搶先於其他程序接收到短信
1.根據上一篇文章的做法,保證自己先於其他程序啓動
2.啓動第一個事情就要開啓服務,動態註冊廣播,並把優先級設置爲最高
代碼實現也非常簡單
一個接收器
- private DynamicReceiver dynamicReceiver = new DynamicReceiver();
- public class DynamicReceiver extends BroadcastReceiver {
- public void onReceive(Context context, Intent intent) {
- Log.e(SmsUtil.TAG, "dynamic receiver");
- String action = intent.getAction();
- if(SmsUtil.SMS_ACTION.equals(action)){
- context.startService(SmsUtil.getIntent(context, MainService.class, intent, "dynamic receiver"));
- }
- }
- }
動態註冊
- public static final String SMS_ACTION = "android.provider.Telephony.SMS_RECEIVED";
- IntentFilter intentFilter = new IntentFilter(SMS_ACTION);
- intentFilter.setPriority(Integer.MAX_VALUE);
- registerReceiver(dynamicReceiver, intentFilter);
最後總結一下,接收器接收廣播的順序
普適原則
同等優先級的動態接收器,先註冊的先接收
同等優先級的靜態接收器,接收廣播的順序與String[] java.io.File.list()順序一致
ordered廣播
假設有如下優先級的5個接收器
1.動態A(優先級=1)
2.動態B(優先級=2)
3.動態C(優先級=2)
4.靜態D(優先級=1)
5.靜態E(優先級=2)
並且B先於C註冊
那麼實際接收順序應爲
B C E A D
也就是說,如果靜態接收器的優先級高於動態接收器的優先級,那麼還是靜態接收器先接收到廣播(比如接收短信)
非ordered廣播
動態接收器高優先級 > 動態接收器低優先級 > 靜態接收器高優先級 > 靜態接收器低優先級
結束之前說點題外話
有些廣播,我們無法用靜態接收器接收
比如ACTION_SCREEN_ON,當屏幕被點亮的時候系統發送此廣播
如果你嘗試在manifest中註冊receiver來接收,那麼會失敗,這是爲什麼呢
我們來看看系統是如何發送此廣播的
void com.android.server.PowerManagerService.initInThread()
- void initInThread() {
- ……
- mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
- mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
- mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- ……
- }
ACTION_SCREEN_OFF也是如此
(這段說明應該放的之前的android安全問題(三) 釣魚程序中,現在補上)
關於FLAG_RECEIVER_REGISTERED_ONLY的說明
public static final int FLAG_RECEIVER_REGISTERED_ONLY
If set, when sending a broadcast only registered receivers will be called -- no BroadcastReceiver components will be launched.
在來看一個廣播,ACTION_BATTERY_CHANGED
電池電量發生變化的時候,系統發送此廣播
void com.android.server.BatteryService.sendIntent()
- private final void sendIntent() {
- // Pack up the values and broadcast them to everyone
- Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_REPLACE_PENDING);
- ……
- }
所以我們必須動態接收
請大家不要用root的手機隨意下載軟件,更不要以任何藉口製造任何病毒!
轉貼請保留以下鏈接
本人blog地址