createFromPdu(byte[]) method was deprecated in API level 23. Use createFromPdu(byte[], String) instead.
Android收到短信的事件是由系统发一个有序广播的,所以这里需要一个BroadcastReceiver。receiver收到的Intent里面并不是直接存储的短信内容,而是短信的原始数据。所以我们需要自己解码。
获取短信的原始数据
获取短信的原始数据: 原始数据被叫做PDU,一个PDU就是一个数据段,如果短信比较长的话可能是由几个PDU组成的。
代码语言:javascript复制@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方法。
代码语言:javascript复制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的代码实现,发现他本身就做了制式判断的(=_=!),代码写的还是不错的,粘出来。万一以后这个方法被废弃了,还有个参考。
代码语言:javascript复制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;
}