android为什么在SIM卡中存中文联系人,重启之后,中文联系人名字会消失?
但是存的号码还保留!
有遇到类似现象的吗?
ContentValues cv = new ContentValues();
cv.put("tag", "");
cv.put("number", "");
cv.put("newTag", "中文");
cv.put("newNumber", "12345678");
getContentResolver().insert(SIM_CONTACTS_URI, cv);
重启之后,“中文”这2个字就没了,但是12345678这个号码还会保留!
网友ljp1205的回复起到了关键性的作用:
这是android源码中的一个问题,很早之前就有了,我接触到是从1.6开始,现在还有?
这个问题的原因是在往sim卡写联系人的时候会首先判断是不是标准的ascii码,不是的话会把这个名字用空格代替,代码如下:
在AdnRecord.java中
if (!TextUtils.isEmpty(alphaTag)) {
byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
}
至于sim卡中存储中文的80格式介绍请参考下面的链接
http://blog.youkuaiyun.com/jennyvenus/archive/2008/04/20/2309701.aspx
后来经过无数次的尝试(3天编译烧机试验不下50次),终于找到了问题点,现在把关键代码分享出来,只供学习之用!
以下代码只提供关键部分,自己可以加进相关文件中,肯定能编译通过,上层UI调用部分省略。
在frameworks/base/telephony/java/com/android/internal/telephony/AdnRecord.java
/**
* Build adn hex byte array based on record size
* The format of byte array is defined in 51.011 10.5.1
*
* @param recordSize is the size X of EF record
* @return hex byte[recordSize] to be written to EF record
* return nulll for wrong format of dialing nubmer or tag
*/
public byte[] buildAdnString(int recordSize) {
byte[] bcdNumber;
byte[] byteTag = null;
byte[] byteTagTemp = new byte[15];
byte[] adnString = null;
int footerOffset = recordSize - FOOTER_SIZE_BYTES;
if (number == null || number.equals("") ||
alphaTag == null || alphaTag.equals("")) {
Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number");
adnString = new byte[recordSize];
for (int i = 0; i < recordSize; i++) {
adnString[i] = (byte) 0xFF;
}
} else if (number.length()
> (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) {
Log.w(LOG_TAG,
"[buildAdnString] Max length of dailing number is 20");
} else if (alphaTag.length() > footerOffset) {
Log.w(LOG_TAG,
"[buildAdnString] Max length of tag is " + footerOffset);
} else {
adnString = new byte[recordSize];
for (int i = 0; i < recordSize; i++) {
adnString[i] = (byte) 0xFF;
}
bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number);
System.arraycopy(bcdNumber, 0, adnString,
footerOffset + ADN_TON_AND_NPI, bcdNumber.length);
adnString[footerOffset + ADN_BCD_NUMBER_LENGTH]
= (byte) (bcdNumber.length);
adnString[footerOffset + ADN_CAPABILITY_ID]
= (byte) 0xFF; // Capacility Id
adnString[footerOffset + ADN_EXTENSION_ID]
= (byte) 0xFF; // Extension Record Id
//处理中文的关键部分,只能存取6位
if (alphaTag.getBytes().length != alphaTag.length()) {//Including Chinese
try {
//做的第一个尝试,失败
// byteTag = EncodeUCS2(alphaTag).getBytes("ISO-10646-UCS-2");
//做的第二个尝试,失败
// byteTag = alphaTag.getBytes("ISO-10646-UCS-2");
//最终试验结论Android只能使用“utf-16BE”
byteTag = alphaTag.getBytes("utf-16BE");
//根据那篇ucs2编码文档实现的字节解析
//第一位添加0x80,之后的位以次向右移
//可能实现的比较垃圾,各位高手就包涵了
for(int i = 0; i < byteTag.length; i++)
{
byteTagTemp[i+1] = (byte) (byteTag[i] & 0xff);
}
for(int j = byteTag.length + 1; j < byteTagTemp.length; j++)
{
byteTagTemp[j] = (byte)0xff;
}
byteTagTemp[0] = (byte)0x80;
String d = new String(byteTagTemp);
} catch (java.io.UnsupportedEncodingException ex) {
Log.e("AdnRecord", "alphaTag convert byte exception");
}
System.arraycopy(byteTagTemp, 0, adnString, 0, byteTag.length + 1);
}else{//Not Including Chinese/*如果不包含中文字符的话就按原来的解码方式处理*/
byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
}
}
String dd = new String(adnString);
return adnString;
}
//为了打印相关字节的log方便编写的解析函数
private String bytesToHexStr(byte[] b)
{
if (b == null) return "";
StringBuffer strBuffer = new StringBuffer(b.length * 3);
for(int i = 0; i < b.length; i++)
{
strBuffer.append(Integer.toHexString(b[i] & 0xff));
strBuffer.append(" ");
}
return strBuffer.toString();
}