Android短信監聽實現,及Android4.4之後短信機制變更
前陣子公司有一個項目,簡單的監聽短信應用,功能只有如下兩個:
1.監聽數據庫變化方式監聽短信內容
_id: 短信序號,如100
thread_id:對話的序號,如100,與同一個手機號互發的短信,其序號是相同的
address: 發件人地址,即手機號,如+86138138000
person: 發件人,如果發件人在通訊錄中則爲具體姓名,陌生人爲null
date: 日期,long型,如1346988516,可以對日期顯示格式進行設置
protocol: 協議0SMS_RPOTO短信,1MMS_PROTO彩信
read: 是否閱讀0未讀,1已讀
status: 短信狀態-1接收,0complete,64pending,128failed
type: 短信類型1是接收到的,2是已發出
body: 短信具體內容
service_center:短信服務中心號碼編號,如+8613800755500
private Uri SMS_INBOX = Uri.parse("content://sms/inbox"); public void getSmsFromPhone() { ContentResolver cr = getContentResolver(); String[] projection = new String[] { "body","address" };//"_id", "address", "person",, "date", "type String where = " date > " + (System.currentTimeMillis() - 10 * 60 * 1000); Cursor cur = cr.query(SMS_INBOX, projection, where, null, "date desc"); if (null == cur) return; if (cur.moveToFirst()) { String number = cur.getString(cur.getColumnIndex("address"));//手機號 String body = cur.getString(cur.getColumnIndex("body")); //TODO 這裏是具體處理邏輯 } }
在這裏我們只是寫了一個方法查詢數據庫,但是還有一個問題就是我們應該在什麼時候去查數據庫,總不能起個線程去輪訓,這樣太耗費資源了,這裏我們可以是用觀察者模式;
private SmsObserver smsObserver; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.app_login); smsObserver = new SmsObserver(this, smsHandler); getContentResolver().registerContentObserver(SMS_INBOX, true, smsObserver); } public Handler smsHandler = new Handler() { //這裏可以進行回調的操作 //TODO }; class SmsObserver extends ContentObserver { public SmsObserver(Context context, Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); //每當有新短信到來時,使用我們獲取短消息的方法 getSmsFromPhone(); } }
2.通過廣播監聽短信內容
public class SmsReceiver extends BroadcastReceiver { public static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; private static final String TAG = "yjj"; public SmsReceiver() { Log.i("yjj", "new SmsReceiver"); } @Override public void onReceive(final Context context, Intent intent) { Log.i(TAG, "jie shou dao"); Cursor cursor = null; try { if (SMS_RECEIVED.equals(intent.getAction())) { Log.d(TAG, "sms received!"); Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); final SmsMessage[] messages = new SmsMessage[pdus.length]; for (int i = 0; i < pdus.length; i++) { messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); } if (messages.length > 0) { String content = messages[0].getMessageBody(); String sender = messages[0].getOriginatingAddress(); long msgDate = messages[0].getTimestampMillis(); String smsToast = "New SMS received from : " + sender + "\n'" + content + "'"; Toast.makeText(context, smsToast, Toast.LENGTH_LONG) .show(); Log.d(TAG, "message from: " + sender + ", message body: " + content + ", message date: " + msgDate); //自己的邏輯 } } cursor = context.getContentResolver().query(Uri.parse("content://sms"), new String[] { "_id", "address", "read", "body", "date" }, "read = ? ", new String[] { "0" }, "date desc"); if (null == cursor){ return; } Log.i(TAG,"m cursor count is "+cursor.getCount()); Log.i(TAG,"m first is "+cursor.moveToFirst()); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "Exception : " + e); } finally { if (cursor != null) { cursor.close(); cursor = null; } } } }
這個很簡單就是定義一個廣播接收者,並且在清單文件中註冊(註冊有兩種方式,這裏就不展開了)
<receiver android:name=".message.SmsReceiver" android:permission="android.permission.BROADCAST_SMS"> <intent-filter android:priority="2147483647"> <action android:name="android.provider.Telephony.SMS_DELIVER" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
3.Android 4.4以上版本短信權限問題
4.Android4.4版本以上設置默認短信應用
<!-- BroadcastReceiver that listens for incoming MMS messages --> <receiver android:name=".message.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=".message.ComposeSmsActivity" > <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=".message.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>
public class MmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { } }
ComposeSmsActivity.java
public class ComposeSmsActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); } }
HeadlessSmsSendService.java
public class HeadlessSmsSendService extends Service { @Override public IBinder onBind(Intent intent) { return null; } }
通過以上步驟,我們所寫的應用就可以被設置爲默認短信應用了
最後別忘了添加相應的權限:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
這裏貼出的是我整個項目的權限,世紀應該只需要SMS相關的權限,這裏就不做區分了