Android接收短信-createFromPdu

简介: Android接收短信-createFromPdu

createFromPdu(byte[]) method was deprecated in API level 23. Use createFromPdu(byte[], String) instead.


Android收到短信的事件是由系统发一个有序广播的,所以这里需要一个BroadcastReceiver。receiver收到的Intent里面并不是直接存储的短信内容,而是短信的原始数据。所以我们需要自己解码。


获取短信的原始数据


获取短信的原始数据: 原始数据被叫做PDU,一个PDU就是一个数据段,如果短信比较长的话可能是由几个PDU组成的。


@Override
public void onReceive(Context context, Intent intent) {
    Bundle smsBundle = intent.getExtras();
    if (smsBundle != null) {
        Object[] pdus = (Object[]) smsBundle.get("pdus");
    }
}

上面的smsBundle.get("pdus")返回的实际类型是byte[][],二维数组的每一个子数组就是一个pdu。


解码短信内容


解码短信内容: 这里主要使用到的是SmsMessage.createFromPdu方法。


private String parseMessageFromRawData(Object[] pdus) {
    if (pdus == null) return null;
    try {
      StringBuilder message = new StringBuilder();
        for (Object pdu : pdus) {
            SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
            if (smsMessage == null) continue;
            message.append(smsMessage.getDisplayMessageBody());
        }
        return message.toString();
    } catch (Exception e) {
        Log.e(TAG, "SMSBroadcastReceiver read sms failed", e);
    } catch (OutOfMemoryError oom) {
        Log.e(TAG, "SMSBroadcastReceiver caused OOM =_=!", oom);
        //为了避免后续操作出现问题,gc一下
        System.gc();
        System.gc();
    }
    return null;
}

上面的重点就是SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);这一句了。需要注意的是这个操作容易导致OOM(已经有好多Crash上报了。。。),所以要特别处理一下。


另外: 上面的SmsMessage.createFromPdu方法已经被官方文档说明即将被废弃(deprecated)原因是为了同时支持3GPP和3GPP2,他们是移动系统通信标准的拟定组织分别拟定了GSM/UMTS/LTE标准和CDMA/LTE标准。因此推荐是用的方法是createFromPdu(byte[] pdu, String format)其中fotmat可以是SmsConstants.FORMAT_3GPP或者SmsConstants.FORMAT_3GPP2。


出于好奇我看了一眼SmsMessage.createFromPdu的代码实现,发现他本身就做了制式判断的(=_=!),代码写的还是不错的,粘出来。万一以后这个方法被废弃了,还有个参考。

public static SmsMessage createFromPdu(byte[] pdu) {
     SmsMessage message = null;
    // cdma(3gpp2) vs gsm(3gpp) format info was not given,
    // guess from active voice phone type
    int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
    String format = (PHONE_TYPE_CDMA == activePhone) ?
            SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
    message = createFromPdu(pdu, format);
    if (null == message || null == message.mWrappedSmsMessage) {
        // decoding pdu failed based on activePhone type, must be other format
        format = (PHONE_TYPE_CDMA == activePhone) ?
                SmsConstants.FORMAT_3GPP : SmsConstants.FORMAT_3GPP2;
        message = createFromPdu(pdu, format);
    }
    return message;
}


相关文章
|
7月前
|
Java API 调度
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
385 0
|
7月前
|
安全 Android开发
Android 预置可卸载分区接收不到任何广播问题分析和解决
Android 预置可卸载分区接收不到任何广播问题分析和解决
225 0
|
6月前
|
设计模式 Android开发
44. 【Android教程】广播接收器:Broadcast Receiver
44. 【Android教程】广播接收器:Broadcast Receiver
143 2
|
6月前
|
存储 Android开发 Kotlin
Kotlin开发安卓app,在使用 MediaPlayer 播放 res/raw 中的音乐时遇到突然中断的问题,而 onErrorListener 没有接收到任何报错
在使用 Android MediaPlayer 播放 res/raw 中的音乐时遇到中断问题,可能的原因包括资源问题、媒体文件编码格式、生命周期管理和设备资源配置。要排查问题,检查音频文件是否正确包含,格式编码是否支持,MediaPlayer 是否正确管理及释放,以及设备是否有足够存储和配置。通过设置 onErrorListener 日志和确保在 onDestroy 中释放资源来调试。如果文件过大,考虑使用 AssetManager。遵循这些步骤可帮助诊断并解决播放中断的问题。
|
Java API Android开发
Android 静态注册广播接收者和动态注册广播接收者(Android8.0之前和之后)
Android 静态注册广播接收者和动态注册广播接收者(Android8.0之前和之后)
391 0
|
7月前
|
XML Java Android开发
Android Studio App开发之监听系统广播Broadcast的讲解及实战(包括接收分钟到达广播、网络变更广播、定时管理器等 附源码)
Android Studio App开发之监听系统广播Broadcast的讲解及实战(包括接收分钟到达广播、网络变更广播、定时管理器等 附源码)
490 0
|
Android开发
Android 使用UDP进行通讯(发送数据和接收数据)
Android 使用UDP进行通讯(发送数据和接收数据)
1909 0
|
Java 开发工具 Android开发
RK3128 Android 7 BOX SDK 应用无法接收广播自启 + 眠休不黑屏问题
RK3128 Android 7 BOX SDK 应用无法接收广播自启 + 眠休不黑屏问题
474 0
|
Java Android开发
Android 7.1 多次重启后BOOT_COMPLETED广播接收变慢
Android 7.1 多次重启后BOOT_COMPLETED广播接收变慢
338 0
|
Android开发
安卓4.X系统 增加蓝牙接收文件类型
安卓4.X系统 增加蓝牙接收文件类型
145 0