您的位置:首页 > 移动开发 > Android开发

Android两种方式监听短信内容---BroadcastReceiver和ContentObserver

2016-12-28 18:48 549 查看
监听短信:

ContentObserver:监听短信数据库的变化

BroadCastReceiver:通过广播接收器来实现监听

拦截垃圾短信:用广播,如果用ContentObserver,垃圾短信已经存到收件箱了      用广播要考虑优先级不如第三方软件会被拦截

监   听  短   信:用ContentObserver,用广播如果短信长会被切割成多条

第一种方式:广播

SMSBroadcastReceiver:

package com.ddgl.ddlx.BroadcastReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by 27c1 on 2016/12/27.
*/

public class SMSBroadcastReceiver extends BroadcastReceiver {

private static final String TAG = "smsreceiver";
private String ss;
private static MessageListener mMessageListener;

@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive: " + "收到短信广播");

Bundle bundle = intent.getExtras();
SmsMessage msg = null;
if (null != bundle) {
Object[] smsObj = (Object[]) bundle.get("pdus");
for (Object object : smsObj) {
msg = SmsMessage.createFromPdu((byte[]) object);
Date date = new Date(msg.getTimestampMillis());//时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String receiveTime = format.format(date);
Log.i(TAG, "onReceive:===="+"number:" + msg.getOriginatingAddress()
+ "   body:" + msg.getDisplayMessageBody() + "  time:"
+ msg.getTimestampMillis());

if (msg.getDisplayMessageBody().substring(0,9).equals("【丁丁旅行】验证码")){
ss = msg.getDisplayMessageBody().substring(9, 15);
Log.i(TAG, "onReceive: 截取的为==="+ ss);

if (ss.length()==6){
mMessageListener.onReceived(ss);
abortBroadcast();
}
}
}
}
}

//回调接口
public interface MessageListener {
public void onReceived(String message);
}

public void setOnReceivedMessageListener(MessageListener messageListener) {
this.mMessageListener = messageListener;
}
}
MainActiivty:动态注册广播并修改edittext内容

@Override
public void onStart() {
super.onStart();
receiver = new SMSBroadcastReceiver();
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(Integer.MAX_VALUE);
getActivity().registerReceiver(receiver, filter);
receiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.MessageListener() {
@Override
public void onReceived(String message) {
etLoginName.setText(message);
}
});
}

//注销短信监听广播
@Override
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(receiver);
}
短信权限:

<!--短信权限-->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_SMS" />
但是这个方法Android 5.1系统魅族手机可以   Android4.3系统oppo手机不可以
第二种方法:数据库读取短信记录:

MainActivity:  

private SMSObserver observer;

//点击完获取验证码就开始读取数据库
observer = new SMSObserver(getActivity(), smsHandler);
getActivity().getContentResolver().registerContentObserver(SMS_INBOX, true, observer);

//读取短信内容handler
private Handler smsHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "handleMessage: msg===" + msg.obj);
String autoCode = (String) msg.obj;
etLoginName.setText(autoCode);
}
};

@Override
public void onDestroy() {
super.onDestroy();
getActivity().getContentResolver().unregisterContentObserver(observer);
}
SMSObserver:

package com.ddgl.ddlx.ContentObserver;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.ddgl.ddlx.fragment.LoginNoPassFragment.getCodeTime;

/**
* Created by 27c1 on 2016/12/29.
*/

public class SMSObserver extends ContentObserver {

private static final String TAG = "smsobserver";
private Context context;
public static Uri SMS_INBOX = Uri.parse("content://sms/");
private Handler handler = new Handler();

/**
* Creates a content observer.
*
* @param handler The handler to run {@link #onChange} on, or null if none.
*/
public SMSObserver(Context context, Handler handler) {
super(handler);
this.context = context;
this.handler = handler;
}

@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//每当有新短信到来时,使用我们获取短消息的方法
getSmsFromPhone();
}

private void getSmsFromPhone() {
ContentResolver cr = context.getContentResolver();
String[] projection = new String[]{"body"};//"_id", "address", "person",, "date", "type
String where = "  date >  " + getCodeTime;
Cursor cursor = cr.query(SMS_INBOX, projection, where, null, "date desc");
if (cursor != null) {
if (cursor.moveToNext()) {
String body = cursor.getString(cursor.getColumnIndex("body"));
Log.i(TAG, "getSmsFromPhone:短信内容===" + body);
if (body.contains("XXX验证码")) {
//这里我是要获取自己短信服务号码中的验证码~~
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(body);
String num = m.replaceAll("").trim().toString();
Log.i(TAG, "getSmsFromPhone: num===" + num);
if (num != null) {
Message message = new Message();
message.obj = num;
handler.sendMessage(message);
}
} else {
Log.i(TAG, "getSmsFromPhone: " + "没有收到XXX的短信");
}
}
} else {
return;
}
}
}

动态注册广播:写一个SMSBroadcastReceiver类

SMSBroadcastReceiver receiver = new SMSBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(Integer.MAX_VALUE);
getActivity().registerReceiver(receiver, filter);
静态注册广播:
<receiver
android:name=".BroadcastReceiver.SMSBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
数据库读取短信:

用ManageQuery还是不行 Android5.1系统魅族手机通知类短信读不到验证码

Android  6.0小米系统所有通知类短信都读不到 
代码:

package com.miapsoft.intercept_mmsdemo.activity;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.example.intercept_mmsdemo.R;

import android.app.Activity;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.widget.EditText;

public class MainActivity extends Activity{

EditText ed_mmscode;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ed_mmscode=(EditText) findViewById(R.id.ed_mms);
SmsContent content = new SmsContent(new Handler());
//注册短信变化监听
this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, content);
}

/**
* 监听短信数据库
*/
class SmsContent extends ContentObserver {
private Cursor cursor = null;
public SmsContent(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
//读取收件箱中指定号码的短信
cursor = managedQuery(Uri.parse("content://sms/inbox"), new String[]{"_id", "address", "read", "body"}, " address=? and read=?", new String[]{"10658464", "0"}, "_id desc");//按id排序,如果按date排序的话,修改手机时间后,读取的短信就不准了
if (cursor != null && cursor.getCount() > 0) {
ContentValues values = new ContentValues();
values.put("read", "1"); //修改短信为已读模式
cursor.moveToNext();
int smsbodyColumn = cursor.getColumnIndex("body");
String smsBody = cursor.getString(smsbodyColumn);
ed_mmscode.setText(getDynamicPassword(smsBody));
}
//在用managedQu
aff8
ery的时候,不能主动调用close()方法, 否则在Android 4.0+的系统上, 会发生崩溃
if(Build.VERSION.SDK_INT < 14) {
cursor.close();
}
}
}

/**
* 从字符串中截取连续6位数字
* 用于从短信中获取动态密码
* @param str 短信内容
* @return 截取得到的6位动态密码
*/
public static String getDynamicPassword(String str) {
Pattern continuousNumberPattern = Pattern.compile("[0-9\\.]+");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while(m.find()){
if(m.group().length() == 6) {
System.out.print(m.group());
dynamicPassword = m.group();
}
}
return dynamicPassword;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: