在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_STICKY
或START_REDELIVER
,这样即使应用被系统杀死,系统也会尝试重新启动服务,从而继续监听短信,需要在AndroidManifest.xml
中声明FOREGROUND_SERVICE
权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />