Android监听手机短信

Android监听手机短信的方法有两种,分别为:

1、接受系统的短信广播:当手机收到新消息时,会发送一条广播,通过该广播就可以获取短信内容;

2、监听短信数据库:利用观察者模式监听短信数据库,当短信数据库改变时就可以触发观察者模式的onChange()方法,但是onChang回调或获取短信不是最新,以及获取重复短信问题。


sms主要结构:

  _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


第一种方式接收系统的短信广播: A、这种方式只对新收到的短消息有效,运行代码,并不会读取收件箱中已读或未读的消息,只有当收到新来的短消息时,才会执行onReceive()方法。

B、并且这个广播是有序广播,如果当别的程序先读取到了这个广播,然后拦截掉了个这个广播,你将接收不到。当然我们可以通过设置priority的数值,其实有时是不管用的,现在在一些定制的系统或是有安全软件的情况下,往往短消息都被截取到,并被干掉。

<uses-permission android:name="android.permission.RECEIVE_SMS" /> <!-- 接收短信权限 -->
<uses-permission android:name="android.permission.READ_SMS" /> <!-- 读取短信权限 -->

<receiver android:name="com.example.smslistenerdemo.SmsReceiver" >
            <intent-filter android:priority="2147483647" >
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
 </receiver>
public class SmsReceiver extends BroadcastReceiver {
//    private static MessageListener mMessageListener;

    private Context mContext;
    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
    public static final String SMS_DELIVER_ACTION = "android.provider.Telephony.SMS_DELIVER";

    @Override
    public void onReceive(Context context, Intent intent) {
        this.mContext = context;
     
        Toast.makeText(context, "接收短信执行了.....", Toast.LENGTH_LONG).show();
        Log.e("日志:广播::onReceive", isOrderedBroadcast() + "");
        Log.e("日志:onReceive...", "-接收短信执行了......"+intent.getStringExtra("sele"));
        String action = intent.getAction();
        if (SMS_RECEIVED_ACTION.equals(action) || SMS_DELIVER_ACTION.equals(action) ) {
           
            Log.e("日志:onReceive。。。", "开始接收短信.....");
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                Object[] pdus = (Object[]) bundle.get("pdus");
                if (pdus != null && pdus.length > 0) {
                    SmsMessage[] messages = new SmsMessage[pdus.length];
                    for (int i = 0; i < pdus.length; i++) {
                        byte[] pdu = (byte[]) pdus[i];
                        messages[i] = SmsMessage.createFromPdu(pdu);
                    }
                    for (SmsMessage message : messages) {
                        String content = message.getMessageBody();// 得到短信内容
                        String sender = message.getOriginatingAddress();// 得到发信息的号码
                        Date date = new Date(message.getTimestampMillis());
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        format.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
                        String dateContent = format.format(date);

                    if ((sender.equals("8610086") || sender.equals(Constant.phone))){
                        Log.e("日志:短信时间::: ", format.format(date) + " ");
                        Log.e("日志:发信息的号码 ", sender + " ");
                        Log.e("日志:得到短信内容 ", content + " ");
                        this.abortBroadcast();// 中止
                    }

                    }
                }

            }
        }
    }
}

开启Service实现锁屏监听

在Activity中监听短信,当应用被放入后台或者屏幕锁定一段时间后就无法继续将短信内容上传服务器,所以需要启动一个Service,在Service中监听短信,就可以在锁屏后继续监听短信

要启动Service,首先需要在申请android.permission.FOREGROUND_SERVICE权限,该权限为普通权限,所以只要在AndroidManifest.xml中声明即可

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

之后还需要在AndroidManifest.xml中添加Service类对应的<service>标签,其中三条属性值的含义分别为:

android:name为pakagename+Service类名,pakagename可以省略;

android:enabled表示是否可以被系统实例化;

android:exported表示其它应用的组件是否可以唤醒service或者和这个service进行交互;

<service
  android:name=".MyService"
  android:enabled="true"
  android:exported="true"\>
public class SmsObserver extends ContentObserver {

    public Context mContext;
    public SmsHandler smsHandler;
    private static int id=0; //这里必须用静态的,防止程序多次意外初始化情况
    String _id;
    public SmsObserver(Context context, SmsHandler handler) {
        super(handler);
        this.mContext = context;
        this.smsHandler = handler;
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        Log.i("日志:SmsObserver", "SmsObserver ------短信有改变------");
//        Cursor mCursor = mResolver.query(Uri.parse("content://sms/inbox"),
//                null, null, null, "date desc");
        Cursor mCursor = mContext.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, "date desc");

        if (mCursor == null) {
            return;
        } else {
            if (mCursor.moveToFirst()){
                SmsInfo _smsInfo = new SmsInfo();
                int _inIndex = mCursor.getColumnIndex("_id");
                if (_inIndex != -1) {
                     _id = mCursor.getString(_inIndex);
                    _smsInfo._id=_id;
                }
                Log.e("日志:SmsObserver ...", "id:::"+id);
                //比较id 解决重复问题
                if (id < Integer.parseInt(_id)) {
                    id = Integer.parseInt(_id);

                    int thread_idIndex = mCursor.getColumnIndex("thread_id");

                    _smsInfo.thread_id = mCursor.getString(thread_idIndex);

                    int bodyIndex = mCursor.getColumnIndex("body");
                    _smsInfo.smsBody = mCursor.getString(bodyIndex);
                    int dateIndex = mCursor.getColumnIndex("date");
                    String date = mCursor.getString(dateIndex);
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                    _smsInfo.date = dateFormat.format(new Date(Long.parseLong(date)));
                    int addressIndex = mCursor.getColumnIndex("address");
                    String address=   mCursor.getString(addressIndex);

                    if (address.contains("10086")) {
                        id = Integer.parseInt(_id);
                        Log.e("日志:SmsObserver ...", "10086::"+address);
                        Message msg = smsHandler.obtainMessage();
                        _smsInfo.action = 0;// 0不对短信进行操作;1将短信设置为已读;2将短信删除
                        msg.obj = _smsInfo;
                        smsHandler.sendMessage(msg);

                        //发广播
                        Intent intent = new Intent("com.zl.zl_sms_monitor_DBiErICZ");
                        intent.putExtra("hello", address);         //向广播接收器传递数据
                        mContext.sendBroadcast(intent);
                        return;
                      }
                    Log.e("日志:SmsObserver ...", "获取的短信内容::"+_smsInfo.toString());

                }
            }
           // getHttp();

        }

        if (mCursor != null) {
            mCursor.close();
            mCursor = null;
        }
    }
}
public class SmsService  extends Service {

    private  SmsObserver mObserver = new SmsObserver(this, new SmsHandler(this));
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        Toast.makeText(this,"SmsService服务器启动了。。。",  Toast.LENGTH_LONG).show();
        //所有短信  注册
        getContentResolver().registerContentObserver(Uri.parse("content://sms"),true, mObserver);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        this.getContentResolver().unregisterContentObserver(mObserver);
        Process.killProcess(Process.myPid());
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37599041/article/details/129319220