垃圾短信攔截
在Android4.4之前,對於垃圾短信的攔截,可以通過自定義短信廣播接收器,對系統的短信廣播(屬於有序廣播)android.provider.Telephony.SMS_RECEIVED
進行接聽,並將其設置爲最高接聽優先級(1000),然後對在黑名單中的用戶發送過來的短信進行攔截(利用 abortBroadcast()函數截斷廣播)。具體實現方式如下:
1、AndroidManifest.xml的代碼:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.study.sms"
android:versionCode="1"
android:versionName="1.0">
<!--聲明讀取短信的權限-->
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<!--靜態註冊自定義的接收短信的廣播接收器,並設置其接收系統短信廣播的優先級爲最高級-1000-->
<receiver android:name=".smsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
2、smsReceiver的代碼:
public class smsReceiver extends BroadcastReceiver {
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (SMS_RECEIVED_ACTION.equals(action)){
Bundle bundle = intent.getExtras();
if (bundle != null){
// 獲取短信的內容和發送短信的地址
Object[] pdus = (Object[])bundle.get("pdus");
for (Object pdu : pdus){
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu);
String sender = message.getOriginatingAddress();
if ("5556".equals(sender)){
//阻斷廣播傳遞,屏蔽手機號爲5556的短信。
abortBroadcast();
}
}
}
}
短信機制變更
在google查閱後得知:Android爲了防止第三方軟件攔截短信和偷發短信吸費,在android4.4之後,只有默認的短信應用纔有權限操作短信數據庫。
Android4.4 之前
- 新接收短信廣播 SMS_RECEIVED_ACTION爲有序廣播。任意應用可接到該廣播並中止其繼續傳播。中止後優先級低的短信應用和系統短信服務將不知道新短信到達,從而不寫進數據庫。這樣就做到了攔截(其實很多惡意應用也這麼幹)。
- 任意應用都可以操作短信數據庫,包括新建(含僞造收件箱和發件箱短信)、修改(含篡改歷史短信)、刪除。
- 任意應用都可以發送短信和彩信,但默認不寫進短信數據庫,除非應用手動存入,否則用戶是看不到的(配合攔截就可以安靜地吸費了)。
Android4.4 及之後
-
設立默認短信應用機制,成爲默認短信後的應用將全面接管(替代)系統短信服務。與設置默認瀏覽器類似,成爲默認短信應用需要向用戶申請。
-
新接收短信廣播 SMS_RECEIVED_ACTION 更改爲無序廣播,增加只有默認短信應用能夠接收的廣播SMS_DELIVER_ACTION和WAP_PUSH_DELIVER_ACTION 。二者的不同在於,當默認短信應用收到SMS_DELIVER_ACTION 時它要負責將其存入數據庫。任意應用仍然可以接收到 SMS_RECEIVED_ACTION廣播但不能將其中止。因此所有的應用和系統短信服務都可以接收到新短信,沒有應用能夠再用中止廣播的方式攔截短信。
-
只有默認短信應用可以操作短信數據庫,包括新建(含僞造收件箱和發件箱短信)、修改(含篡改歷史短信)和刪除。其它應用只能讀取短信數據庫。默認短信應用需要在發送短信、收到新短信之後手動寫入系統短信數據庫,否則其它應用將讀取不到該條短信。默認短信應用可以通過控制不寫入數據庫的方式攔截短信。
-
任意應用仍然都可以發送短信,但默認短信應用以外的應用發短信的接口底層改爲調用系統短信服務,而不再直接調用驅動通信,因此其所發短信會被系統短信服務自動轉存數據庫。此外,只有默認短信應用可以發送彩信。
簡單來說,第三方非默認短信應用:
- 可以收短信、發短信並接收短信回執,但是不能刪除短信
- 可以查詢短信數據庫,但是不能新增、刪除、修改短信數據庫
- 無法攔截短信
短信攔截的解決方案
提示用戶設置自己的app爲default SMS app!!!
爲了使我們的應用出現在系統設置的Default SMS app中,我們需要在Manifest中做一些聲明,獲取對應的權限:
- 聲明一個 broadcast receiver控件,對SMS_DELIVER_ACTION廣播進行監聽,當然這個receiver也要聲明BROADCAST_SMS權限。
- 聲明一個 broadcast receiver控件,對WAP_PUSH_DELIVER_ACTION廣播進行監聽,當然這個receiver也要聲明BROADCAST_WAP_PUSH權限。
- 在短信發送界面,需要監聽 ACTION_SENDTO,同時配置上sms:, smsto:, mms:, and mmsto這四個概要,這樣別的應用如果想發送短信,你的這個activity就能知道。
- 需要有一個service,能夠監聽ACTION_RESPONSE_VIA_MESSAGE,同時也要配置上sms:, smsto:, mms:, and mmsto這四個概要,並且要聲明SEND_RESPOND_VIA_MESSAGE權限。這樣用戶就能在來電的時候,用你的應用來發送拒絕短信。
<manifest>
...
<application>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=“.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>
通過 Telephony.Sms.getDefaultSmsPackage()方法來判斷自己的應用是否爲Default SMS app。如果不是,可以通過startActivity() 方法啓動類似如下的Dialog。
public class MainActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
// App is not default.
// Show the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.ll_not_default_app);
viewGroup.setVisibility(View.VISIBLE);
// Set up a button that allows the user to change the default SMS app
View button = findViewById(R.id.btn_change_default_app);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
startActivity(intent);
}
});
} else {
// App is the default.
// Hide the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.ll_not_default_app);
viewGroup.setVisibility(View.GONE);
}
}
以上源碼下載地址:https://github.com/wenzhiming/520sms