2010-11-20 46 views
8

基本上我有一個工作的應用程序,收到短信後發送短信。Android:發送短信時的Unicode /字符集問題(sendTextMessage)

一切正常,除了當SMS文本有「特殊字符」,即「E,A,I,C」等

我試過很多東西,包括字符集轉換,但我根本無法使它工作... msgText總是帶着字符集編碼問題回來。

這裏就是發送郵件的一部分:

if (msgText.length() > 160) { 
    ArrayList msgTexts = sm.divideMessage(msgText); 
    sm.sendMultipartTextMessage(PhoneNumber, null, msgTexts, null, null); 
} else { 
    try { 
     sm.sendTextMessage(PhoneNumber, null, msgText, null, null); 
    } catch (IllegalArgumentException e) { 
     e.printStackTrace(); 
    } 
}

這裏的字符集轉換功能我試圖(但沒有幫助),我申請上MSGTEXT:

public static String formatCharset(String txtInicial) { 
    //-- Please notice this is just for reference, I tried every charset from/to conversion possibility. Even stupid ones and nothing helped. 

    /*try {//-- Seems simpler, it should do the same as below, but didn't help 
     msgText = new String(msgText.getBytes("UTF-8"), "ISO-8859-1"); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
    }*/ 

    Charset charsetOrigem = Charset.forName("UTF-8"); 
    CharsetEncoder encoderOrigem = charsetOrigem.newEncoder(); 
    Charset charsetDestino = Charset.forName("ISO-8859-1"); 
    CharsetDecoder decoderDestino = charsetDestino.newDecoder(); 

    String txtFinal = ""; 

    try { 
     ByteBuffer bbuf = encoderOrigem.encode(CharBuffer.wrap(txtInicial)); 
     CharBuffer cbuf = decoderDestino.decode(bbuf); 
     txtFinal = cbuf.toString(); 
    } catch (CharacterCodingException e) { 
     e.printStackTrace(); 
    } 

    if (txtFinal.length() == 0) txtFinal = txtInicial; 

    return txtFinal; 
}

近絕望我甚至在這裏嘗試了unicode消息的解決方案(並沒有幫助):

http://since2006.com/blog/android-send-unicode-message/

總之,這裏的(清理 - 包是com.THE.APPLICATION,主要活動是MAINACT)爲logcat中崩潰時(試圖發送消息時,接收到一個後):

WARN/dalvikvm(28218): threadid=1: thread exiting with uncaught exception (group=0x4001d7f0) 
ERROR/AndroidRuntime(28218): FATAL EXCEPTION: main 
ERROR/AndroidRuntime(28218): java.lang.RuntimeException: Error receiving broadcast Intent { act=android.provider.Telephony.SMS_RECEIVED (has extras) } in [email protected] 
ERROR/AndroidRuntime(28218):  at android.app.ActivityThread$PackageInfo$ReceiverDispatcher$Args.run(ActivityThread.java:905) 
ERROR/AndroidRuntime(28218):  at android.os.Handler.handleCallback(Handler.java:587) 
ERROR/AndroidRuntime(28218):  at android.os.Handler.dispatchMessage(Handler.java:92) 
ERROR/AndroidRuntime(28218):  at android.os.Looper.loop(Looper.java:123) 
ERROR/AndroidRuntime(28218):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
ERROR/AndroidRuntime(28218):  at java.lang.reflect.Method.invokeNative(Native Method) 
ERROR/AndroidRuntime(28218):  at java.lang.reflect.Method.invoke(Method.java:521) 
ERROR/AndroidRuntime(28218):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
ERROR/AndroidRuntime(28218):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
ERROR/AndroidRuntime(28218):  at dalvik.system.NativeStart.main(Native Method) 
ERROR/AndroidRuntime(28218): Caused by: java.lang.NullPointerException 
ERROR/AndroidRuntime(28218):  at android.os.Parcel.readException(Parcel.java:1253) 
ERROR/AndroidRuntime(28218):  at android.os.Parcel.readException(Parcel.java:1235) 
ERROR/AndroidRuntime(28218):  at com.android.internal.telephony.ISms$Stub$Proxy.sendText(ISms.java:369) 
ERROR/AndroidRuntime(28218):  at android.telephony.SmsManager.sendTextMessage(SmsManager.java:87) 
ERROR/AndroidRuntime(28218):  at com.THE.APPLICATION.MAINACT.sendMessage(MAINACT.java:214) 
ERROR/AndroidRuntime(28218):  at com.THE.APPLICATION.SMSReceiver.onReceive(SMSReceiver.java:24) 
ERROR/AndroidRuntime(28218):  at android.app.ActivityThread$PackageInfo$ReceiverDispatcher$Args.run(ActivityThread.java:892) 
ERROR/AndroidRuntime(28218):  ... 9 more 

樣品消息文本與問題派:

VERBOSE/debug_tag(28218): msgText is: possível.

所以,讀取possÃvel當它應該possível

請一些開悟的靈魂幫助我。他/她在我心中會有一個特別的地方! :)

編輯:如果在我的心臟的特殊地位不剪,我願意付幾塊錢一個工作解決方案...

回答

8

好吧,這似乎已經解決了只需使用sendMultipartTextMessage而不是sendTextMessage作爲消息。

誰會想到......它有道理,因爲unicode字符比「普通」字符使用更多的「空間」。

0

如果是7位編碼,則只能使用160個字符。如果你使用140個字符,它應該沒有sendMultipartTextMessage,因爲你使用的是8位字符(UTF-8)。

+1

有道理,對不對?但是,如果沒有帶8位字符的sendMultipartTextMessage,它就無法工作(顯然它適用於沒有它的7位字符)。我覺得有些事情在那裏不太合適。 – 2011-01-10 10:30:40

2

我已經使用此代碼將UTF-8字符轉換爲ASCII。然後發送短信的作品,我可以用160個字符:

private static final String PLAIN_ASCII = "AaEeIiOoUu" // grave 
     + "AaEeIiOoUuYy" // acute 
     + "AaEeIiOoUuYy" // circumflex 
     + "AaOoNn" // tilde 
     + "AaEeIiOoUuYy" // umlaut 
     + "Aa" // ring 
     + "Cc" // cedilla 
     + "OoUu" // double acute 
; 

private static final String UNICODE = "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9" 
     + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
     + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
     + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1" 
     + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
     + "\u00C5\u00E5" + "\u00C7\u00E7" + "\u0150\u0151\u0170\u0171"; 

// remove accentued from a string and replace with ascii equivalent 
public static String convertNonAscii(String s) { 
    if (s == null) 
     return null; 
    StringBuilder sb = new StringBuilder(); 
    int n = s.length(); 
    for (int i = 0; i < n; i++) { 
     char c = s.charAt(i); 
     int pos = UNICODE.indexOf(c); 
     if (pos > -1) { 
      sb.append(PLAIN_ASCII.charAt(pos)); 
     } else { 
      sb.append(c); 
     } 
    } 
    return sb.toString(); 
} 
+0

感謝非常好的幫助文章 – 2015-02-28 10:50:33

1

我使用此命令行:

Html.fromHtml(new String(myString.getBytes("UTF-8"))).toString(); 

和我的短信看起來很完美。

+0

嗨,基督徒。 我好幾年沒有在本地編碼Android,但似乎這是一個更清潔的解決方案,可能當時並不存在。 – 2015-12-21 12:34:37

0

我有與特殊字符相同的問題。當我將消息MAX_SMS_MESSAGE_LENGTH更改爲70時,一切正常。看看這個鏈接:

https://forums.macrumors.com/threads/special-characters-in-sms-turn-them-shorter-70-characters-old-issue-never-solved.1030577/

這是我的代碼:

public static void sendSMS(String phoneNumber, String message, Context context) { 

    String SENT = "SMS_SENT"; 
    int MAX_SMS_MESSAGE_LENGTH = 70; 

    SmsManager smsManager = SmsManager.getDefault(); 
    PendingIntent sentPI; 
    sentPI = PendingIntent.getBroadcast(context, 0,new Intent(SENT), 0); 

    try { 
     if(message.length() > MAX_SMS_MESSAGE_LENGTH) { 
      ArrayList<String> messageList = SmsManager.getDefault().divideMessage(message); 
      smsManager.sendMultipartTextMessage(phoneNumber, null, messageList, null, null); 
     } else { 
      smsManager.sendTextMessage(phoneNumber, null, message, sentPI, null); 
     } 
    } catch (Exception e) { 
     Log.e("SmsProvider", "" + e); 
    } 
} 

當然,你可以插入一個控制器,如果郵件中包含一些特殊的字符,將檢查,然後從160改變MAX_SMS_MESSAGE_LENGTH 70.我的應用程序中總是有特殊字符。