insert Vodafone sim card,open the mms read report,when receive the read report,cann't download the message
Test steps:
1.insert Vodafone sim card
2.open the mms read report
3.send the mms successfully
4.when receive the read report
这里的环境需要描述一下:在国内不会出现这个问题,该问题在土耳其测试发现,经过分析主要因国内外网络差异导致。
问题大概意思是在国外发送一条彩信,对方成功接收,发送方测试会接收一条阅读报告。该阅读报告是以彩信的方式接收。这个时候问题来了,彩信无法自动下载,点击下载按钮也无法完成下载(这里从界面时的确可以这么理解,分析代码之后才发现彩信数据已经下载成功,只是在解析的时候格式不兼容导致解析发生异常,返回null。)
因此经过分析打开NotificationTransaction.java中的log,从log中得到已经下载好的彩信数据,然后在国内用此模拟数据来解决问题。
//if (Log.isLoggable(LogTag.TRANSACTION, Log.DEBUG)) {
Log.v(TAG, "NotificationTransaction: retrieve data=" +
HexDump.dumpHexString(retrieveConfData));//HexDump这个工具类很重要,如果有时间大家仔细阅读一下源码(可以将16进制字符串和字节数组进行转换)
//}
当然,最终修改解决问题的实在解析pdu和持久化保存的PduParser.java类。
case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
if (LOCAL_LOGV) {
Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF");
}
RetrieveConf retrieveConf =
new RetrieveConf(mHeaders, mBody);
byte[] contentType = retrieveConf.getContentType();
if (null == contentType) {
if (LOCAL_LOGV)
Log.v(LOG_TAG, "contentType is null");
return null;
}
String ctTypeStr = new String(contentType);
if (LOCAL_LOGV)
Log.v(LOG_TAG, "ctTypeStr is l"+ctTypeStr);
if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
|| ctTypeStr.equals(ContentType.MULTIPART_RELATED)
|| ctTypeStr.equals(ContentType.TEXT_PLAIN)//这里是添加对“text/plain”格式彩信的兼容
|| ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
// The MMS content type must be "application/vnd.wap.multipart.mixed"
// or "application/vnd.wap.multipart.related"
// or "application/vnd.wap.multipart.alternative"
return retrieveConf;
} else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
// "application/vnd.wap.multipart.alternative"
// should take only the first part.
PduPart firstPart = mBody.getPart(0);
mBody.removeAll();
mBody.addPart(0, firstPart);
return retrieveConf;
}
return null;
下面这发现异常的时候忽视异常:
protected static PduBody parseParts(ByteArrayInputStream pduDataStream) {
if (pduDataStream == null) {
if (LOCAL_LOGV)
Log.v(LOG_TAG, "pduDataStream is null");
return null;
}
int count = parseUnsignedInt(pduDataStream); // get the number of parts
PduBody body = new PduBody();
for (int i = 0 ; i < count ; i++) {
int headerLength = parseUnsignedInt(pduDataStream);
int dataLength = parseUnsignedInt(pduDataStream);
PduPart part = new PduPart();
int startPos = pduDataStream.available();
if (startPos <= 0) {
// Invalid part.
return body;//这里原本是返回null
}
/* parse part's content-type */
HashMap<Integer, Object> map = new HashMap<Integer, Object>();
byte[] contentType = parseContentType(pduDataStream, map);
if (null != contentType) {
part.setContentType(contentType);
} else {
if (LOCAL_LOGV)
Log.v(LOG_TAG, "contentType isn't null");
part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
}
/* get name parameter */
byte[] name = (byte[]) map.get(PduPart.P_NAME);
if (null != name) {
part.setName(name);
}
else{
if (LOCAL_LOGV)
Log.v(LOG_TAG, "name isn't null");
}
/* get charset parameter */
Integer charset = (Integer) map.get(PduPart.P_CHARSET);
if (null != charset) {
part.setCharset(charset);
}
else{
if (LOCAL_LOGV)
Log.v(LOG_TAG, "charset isn't null");
}
/* parse part's headers */
int endPos = pduDataStream.available();
int partHeaderLen = headerLength - (startPos - endPos);
if (partHeaderLen > 0) {
if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
// Parse part header faild.
if (LOCAL_LOGV)
Log.v(LOG_TAG, "Parse part header faild.");
//return null;
}
} else if (partHeaderLen < 0) {
// Invalid length of content-type.
if (LOCAL_LOGV)
Log.v(LOG_TAG, "Invalid length of content-type.");
//return null;
}
/* FIXME: check content-id, name, filename and content location,
* if not set anyone of them, generate a default content-location
*/
if ((null == part.getContentLocation())
&& (null == part.getName())
&& (null == part.getFilename())
&& (null == part.getContentId())) {
part.setContentLocation(Long.toOctalString(
System.currentTimeMillis()).getBytes());
}
/* get part's data */
if (dataLength > 0) {
byte[] partData = new byte[dataLength];
String partContentType = new String(part.getContentType());
pduDataStream.read(partData, 0, dataLength);
if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
// parse "multipart/vnd.wap.multipart.alternative".
PduBody childBody = parseParts(new ByteArrayInputStream(partData));
// take the first part of children.
part = childBody.getPart(0);
} else {
// Check Content-Transfer-Encoding.
byte[] partDataEncoding = part.getContentTransferEncoding();
if (null != partDataEncoding) {
String encoding = new String(partDataEncoding);
if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
// Decode "base64" into "binary".
partData = Base64.decodeBase64(partData);
} else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
// Decode "quoted-printable" into "binary".
partData = QuotedPrintable.decodeQuotedPrintable(partData);
} else {
// "binary" is the default encoding.
}
}
else{
if (LOCAL_LOGV)
Log.v(LOG_TAG, "partDataEncoding isn't null");
}
if (null == partData) {
log("Decode part data error!");
return null;
}
else{
if (LOCAL_LOGV)
Log.v(LOG_TAG, "partData isn't null");
}
part.setData(partData);
}
}
if(LOCAL_LOGV)
Log.v(LOG_TAG,"checkPartPosition is "+checkPartPosition(part));
/* add this part to body */
if (THE_FIRST_PART == checkPartPosition(part)) {
/* this is the first part */
body.addPart(0, part);
} else {
/* add the part to the end */
body.addPart(part);
}
}
return body;
}