当前位置:首页 > 行业动态 > 正文

Android短信监听机制,如何实现与注意事项?

Android 短信监听可通过注册广播接收器实现,需在代码中设置权限并 监听特定 短信内容。

在Android开发中,短信监听是一个常见的需求,它允许应用程序实时获取设备接收到的短信内容,以下是对Android短信监听的详细解析:

1、短信监听方式

接受系统的短信广播

原理:当手机收到新消息时,系统会发送一条广播,通过注册广播接收器并过滤短信相关动作(如android.provider.Telephony.SMS_RECEIVED),可以获取短信内容。

优点:实现相对简单,适合只需要处理新收到短信的情况。

缺点:是有序广播,如果其他应用先接收并拦截了广播,当前应用可能无法收到;在一些定制系统或有安全软件的情况下,短信可能会被截取或干掉。

监听短信数据库

原理:利用观察者模式监听短信数据库的变化,当短信数据库发生改变时,触发观察者的onChange()方法。

优点:不受其他程序干扰,可以获取手机上收件箱、已发送、草稿箱等数据库的变化。

缺点:实现相对复杂一些;onChange()回调可能会因短信显示而被调用两次。

2、实现步骤

权限配置

AndroidManifest.xml文件中添加读取短信和接收短信的权限:

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

由于读取短信属于危险权限,还需要在代码中动态请求用户授权:

        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_SMS}, 1);
        }

接受系统的短信广播

AndroidManifest.xml中注册广播接收器:

        <receiver android:name="com.example.smslistenerdemo.SmsReceiver">
            <intent-filter android:priority="2147483647">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

创建广播接收器类并重写onReceive()方法:

        public class SmsReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                Bundle bundle = intent.getExtras();
                Object[] pdus = (Object[]) bundle.get("pdus");
                SmsMessage[] messages = new SmsMessage[pdus.length];
                for (int i = 0; i < pdus.length; i++) {
                    messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                }
                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");
                    String receiveTime = format.format(date);
                    Log.i("fuyanan", "address:" + sender + "   body:" + content + "  time:" + receiveTime);
                }
            }
        }

监听短信数据库

创建继承自ContentObserver的类并重写onChange()方法:

        public class SMSObserver extends ContentObserver {
            public SMSObserver(Handler handler) {
                super(handler);
            }
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                // 在这里处理短信数据库变化的逻辑,例如读取新短信
            }
        }

在需要监听的地方注册ContentObserver

        Uri uri = Uri.parse("content://sms/inbox");
        getContentResolver().registerContentObserver(uri, true, new SMSObserver(new Handler()));

3、相关问题与解答

问题1:如果只想监听特定号码的短信,该如何实现?

解答:可以在onReceive()方法或onChange()方法中,获取短信的发送号码后进行判断,如果不是特定号码则直接返回,不进行处理。

        if (!sender.equals(specificNumber)) {
            return;
        }
        // 处理特定号码的短信逻辑

问题2:在监听短信时,如何避免应用被系统杀死而导致无法继续监听?

解答:可以使用Service来保持后台运行,在Service中注册广播接收器或ContentObserver,并在onStartCommand()方法中返回START_STICKYSTART_REDELIVER,这样即使应用被系统杀死,系统也会尝试重新启动服务,从而继续监听短信,需要在AndroidManifest.xml中声明FOREGROUND_SERVICE权限:

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