Interested in getting few fields (msgCount, refNumber and seqNumber) from userDataHeader in android SmsMessage object. Does anyone know if it's possible?
Asked
Active
Viewed 153 times
1 Answers
0
Those fields are about three levels deep in private/hidden classes. You can get them with reflection, but do you really need to? msgCount
will be equal to the length of the PDU array. The PDUs are ordered, so figuring seqNumber
for each is trivial. And I can't think of any reason you'd need refNumber
, which is used by the internals and the backend to track submission success/failure and to issue status reports.
In any case, the following is a reflective method you can use to confirm this. Note that these values are only relevant to multipart messages. The data header will be null for single-part messages.
private void listMessageConcatRef(SmsMessage msg) {
try {
Field msgBaseField = SmsMessage.class.getDeclaredField("mWrappedSmsMessage");
Object msgBase = msgBaseField.get(msg);
Class<?> msgBaseCls = Class.forName(
"com.android.internal.telephony.SmsMessageBase");
Field dataHeaderField = msgBaseCls.getDeclaredField("mUserDataHeader");
dataHeaderField.setAccessible(true);
Object dataHeader = dataHeaderField.get(msgBase);
if (dataHeader == null) {
Log.d("SmsMessage", "null data header");
return;
}
Class<?> headerCls = Class.forName(
"com.android.internal.telephony.SmsHeader");
Field concatRefField = headerCls.getDeclaredField("concatRef");
Object concatRef = concatRefField.get(dataHeader);
Class<?> concatRefCls = Class.forName(
"com.android.internal.telephony.SmsHeader$ConcatRef");
Field msgCountField = concatRefCls.getDeclaredField("msgCount");
Field refNumberField = concatRefCls.getDeclaredField("refNumber");
Field seqNumberField = concatRefCls.getDeclaredField("seqNumber");
Field isEightBitsField = concatRefCls.getDeclaredField("isEightBits");
int msgCount = msgCountField.get(concatRef);
int refNumber = refNumberField.get(concatRef);
int seqNumber = seqNumberField.get(concatRef);
boolean isEightBits = isEightBitsField.get(concatRef);
Log.d("ConcatRef", "msgCount = " + msgCount);
Log.d("ConcatRef", "refNumber = " + refNumber);
Log.d("ConcatRef", "seqNumber = " + seqNumber);
Log.d("ConcatRef", "isEightBits = " + isEightBits);
}
catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}

Mike M.
- 38,532
- 8
- 99
- 95
-
Thanks for ur answer. It seems if it's possible only by reflection then I really don't need these fields. I would like to add extra checkings (and if it's required extra actions) for multipart messages in order to garantee that i received all parts and in correct order. It's becouse i have read in several articles, that PDU's might not be delivered in sequence (for example [here](http://stackoverflow.com/questions/4306020/android-receiving-long-sms-multipart)) – Mikhail Sidorov Feb 01 '16 at 08:17
-
It sounds like whoever wrote that question didn't implement their app correctly. I've never received parts of a multipart message out of order. I don't even think it's possible, unless something went really, really wrong in transmission, or somehow a device's system is corrupted. That's what `seqNumber` is for, and the internals handle sorting the parts before they're delivered to your `BroadcastReceiver`. You can use the posted method to run tests for that, if you like. – Mike M. Feb 01 '16 at 08:26
-
Is't possible to receive few messages from different senders or different messages from one sender (not parts) in one intent? For example if I turn on my phone? – Mikhail Sidorov Feb 01 '16 at 08:56
-
Nope, not really, unless, again, something went really wrong somewhere. – Mike M. Feb 01 '16 at 09:06
-
Incomplete concatenated messages are stored in the raw table until all parts arrive, after which they will be delivered in a single intent. There is a tiny risk that a concatenated message contains segments from different messages (see https://android.googlesource.com/platform/frameworks/opt/telephony/+/f39de086fddea9e9f6b8c56b04d8dd38a84237db/src/java/com/android/internal/telephony/InboundSmsHandler.java#602), if both messages are concatenated messages from the same sender, with the same segment count and refnumber. In a very poor network it could happen but it's not very likely.. – fejd Feb 05 '16 at 21:34
-
Yes, if multiple, sequential multipart messages have the same `refNumber`, that would be something going wrong. In any case, it's not something the receiving client can easily deduce, or do anything about, really. – Mike M. Feb 06 '16 at 01:39