本文介绍了Android监听手机短信的示例代码,分享给大家,具体如下:
以下情况可能会导致短信拦截失败:
- 小米,360等品牌手机拦截短信,短信的优先级给了系统
- 用户禁用短信权限
- 手机连接电脑,被电脑端的手机助手类软件截获
- 手机内装有QQ通讯录之类的管理联系人,短信的应用,被截获.
前提–权限:
代码语言:javascript复制<uses-permission android:name="android.permission.RECEIVE_SMS"
</uses-permission
<uses-permission android:name="android.permission.READ_SMS"
</uses-permission
定义短信广播接收者
代码语言:javascript复制public class SMSBroadcastReceiverextends BroadcastReceiver{
private static OnReceivedMessageListener mOnReceivedMessageListener;
public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
public SMSBroadcastReceiver(){
super();
}
@Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
for(Object pdu:pdus) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte [])pdu);
String sender = smsMessage.getDisplayOriginatingAddress();
String content = smsMessage.getDisplayMessageBody();
long date = smsMessage.getTimestampMillis();
Date tiemDate = new Date(date);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = simpleDateFormat.format(tiemDate);
//过滤不需要读取的短信的发送号码
if ("106902780116481".equals(sender)) {
mOnReceivedMessageListener.onReceived(getDynamicPassword(content));
abortBroadcast();
}
}
}
}
public interface OnReceivedMessageListener{
void onReceived(String message);
}
public void setOnReceivedMessageListener(OnReceivedMessageListener onReceivedMessageListener){
this.mOnReceivedMessageListener = onReceivedMessageListener;
}
/**
* 从字符串中截取连续6位数字组合 ([0-9]{" 6 "})截取六位数字 进行前后断言不能出现数字 用于从短信中获取动态密码
* @param str 短信内容
* @return 截取得到的6位动态密码
*/
public String getDynamicPassword(String str){
// 6是验证码的位数,一般为六位
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{" 6 "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
dynamicPassword = m.group();
}
return dynamicPassword;
}
}
注册广播
代码语言:javascript复制SMSBroadcastReceiver = mSMSBroadcastReceiver = new SMSBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(SMSBroadcastReceiver.SMS_RECEIVED_ACTION);
intentFilter.setPriority(Integer.MAX_VALUE);
this.registerReceiver(mSMSBroadcastReceiver, intentFilter);
ToastManager.getInstance().showLongToast("注册短信监听");
mSMSBroadcastReceiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.OnReceivedMessageListener() {
@Override
public void onReceived(String message){
//do something
}
});
方式二:监听短信数据库
内容提供者中对外通信方式有3种:
方式1:定义为Activity的内部类,直接在onChang()方法中处理业务逻辑,比如收到短信之后设置给EditText
- 优点:方便
- 缺点:耦合度高,复用性差
方式2:定义接口,Activity实现这个接口,拿到回调,处理业务逻辑
- 优点:耦合度低,复用性高
- 缺点没用充分利用Handler资源
代码如下:
代码语言:javascript复制/**
* Created by wxw on 2016/9/24 10:34
* function: 监听短信数据库
* e-mail:wangxw725@163.com
*/
public class SmsContentObserverextends ContentObserver{
private Cursor cursor = null;
private Context mContext;
private String[] projection = new String[]{"_id","body"};
private OnMessageObservedListener mOnMessageObservedListener;
public SmsContentObserver(Context context,Handler handler){
super(handler);
this.mContext = context;
}
public interface OnMessageObservedListener{
void onObservedMessage(String message);
}
public void setOnMessageObservedListener(OnMessageObservedListener onMessageObservedListener){
this.mOnMessageObservedListener = onMessageObservedListener;
}
@Override
public void onChange(boolean selfChange){
super.onChange(selfChange);
cursor = mContext.getContentResolver().query(Uri.parse("content://sms/inbox"), projection,null, null, "_id desc");
if (cursor != null && cursor.getCount() 0) {
cursor.moveToNext();
int smsbodyColumn = cursor.getColumnIndex("body");
String smsBody = cursor.getString(smsbodyColumn);
mOnMessageObservedListener.onObservedMessage(getDynamicPassword(smsBody));
}
cursor.close();
}
private String getDynamicPassword(String str){
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{" 6 "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
dynamicPassword = m.group();
}
return dynamicPassword;
}
}
方式3:通过Handler发送消息,在Activity中进行业务逻辑处理
代码如下:
代码语言:javascript复制/**
* Created by wxw on 2016/9/24 10:34
* function: 监听短信数据库
* e-mail:wangxw725@163.com
*/
public class SmsContentObserverextends ContentObserver{
private Cursor cursor = null;
private Context mContext;
private Handler mHandler;
private String[] projection = new String[]{"_id","body"};
public SmsContentObserver(Context context,Handler handler){
super(handler);
this.mContext = context;
this.mHandler = handler;
}
@Override
public void onChange(boolean selfChange){
super.onChange(selfChange);
cursor = mContext.getContentResolver().query(Uri.parse("content://sms/inbox"), projection,null, null, "_id desc");
if (cursor != null && cursor.getCount() 0) {
cursor.moveToNext();
int smsbodyColumn = cursor.getColumnIndex("body");
String smsBody = cursor.getString(smsbodyColumn);
mHandler.obtainMessage(1,getDynamicPassword(smsBody)).sendToTarget();
}
cursor.close();
}
private String getDynamicPassword(String str){
Pattern continuousNumberPattern = Pattern.compile("(?<![0-9])([0-9]{" 6 "})(?![0-9])");
Matcher m = continuousNumberPattern.matcher(str);
String dynamicPassword = "";
while (m.find()) {
dynamicPassword = m.group();
}
return dynamicPassword;
}
}
注册观察者
代码语言:javascript复制smsContentObserver = new SmsContentObserver(this, smsHandler);
getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, smsContentObserver);
handler中处理消息
代码语言:javascript复制private Handler smsHandler = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what){
case 0:
......
break;
case 1:
LogUtils.x("Activity收到了短息码:" (String)msg.obj);
lf.mEtPassword.setText((String)msg.obj);
break;
}
}
};
注销观察者
代码语言:javascript复制@Override
protected void onDestroy(){
super.onDestroy();
......
if(smsContentObserver!=null){
getContentResolver().unregisterContentObserver(smsContentObserver);
smsContentObserver = null;
}
}
遗留问题
观察者会多次回调onChang方法()
以上就是本文的全部内容,希望对大家的学习有所帮助。