Android: problemas de Unicode / Charset al enviar un SMS (sendTextMessage)

Básicamente tengo una aplicación en funcionamiento que envía un SMS después de recibir un SMS.

Todo funciona bien , excepto cuando el texto del SMS para enviar tiene “caracteres especiales“, es decir, “é, à, í, ç”, etc.

He intentado muchas cosas, incluida la conversión del conjunto de caracteres, pero simplemente no puedo hacer que funcione … el msgText siempre regresa con problemas de encoding del conjunto de caracteres.

Aquí está la parte donde se envía el mensaje:

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(); } } 

Aquí está la función de conversión de juego de caracteres que probé (pero no ayudó), que apliqué en 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; } 

Cerca de la desesperación, incluso probé la solución para mensajes Unicode aquí (tampoco ayudó):

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

De todos modos, aquí está el (limpiado – el paquete es com.THE.APPLICATION, la actividad principal es MAINACT) LogCat para cuando se cuelga (cuando se trata de enviar el mensaje, después de recibir uno):

  WARN / dalvikvm (28218): threadid = 1: el hilo sale con la excepción no detectada (group = 0x4001d7f0)
 ERROR / AndroidRuntime (28218): EXCEPCIÓN FATAL: principal
 ERROR / AndroidRuntime (28218): java.lang.RuntimeException: Error al recibir la difusión Intención {act = android.provider.Telephony.SMS_RECEIVED (tiene extras)} en com.THE.APPLICATION.SMSReceiver@44acd880
 ERROR / AndroidRuntime (28218): en android.app.ActivityThread $ PackageInfo $ ReceiverDispatcher $ Args.run (ActivityThread.java:905)
 ERROR / AndroidRuntime (28218): en android.os.Handler.handleCallback (Handler.java:587)
 ERROR / AndroidRuntime (28218): en android.os.Handler.dispatchMessage (Handler.java:92)
 ERROR / AndroidRuntime (28218): en android.os.Looper.loop (Looper.java:123)
 ERROR / AndroidRuntime (28218): en android.app.ActivityThread.main (ActivityThread.java:4627)
 ERROR / AndroidRuntime (28218): en java.lang.reflect.Method.invokeNative (método nativo)
 ERROR / AndroidRuntime (28218): en java.lang.reflect.Method.invoke (Method.java:521)
 ERROR / AndroidRuntime (28218): en com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:868)
 ERROR / AndroidRuntime (28218): en com.android.internal.os.ZygoteInit.main (ZygoteInit.java:626)
 ERROR / AndroidRuntime (28218): en dalvik.system.NativeStart.main (método nativo)
 ERROR / AndroidRuntime (28218): Causado por: java.lang.NullPointerException
 ERROR / AndroidRuntime (28218): en android.os.Parcel.readException (Parcel.java:1253)
 ERROR / AndroidRuntime (28218): en android.os.Parcel.readException (Parcel.java:1235)
 ERROR / AndroidRuntime (28218): en com.android.internal.telephony.ISms $ Stub $ Proxy.sendText (ISms.java:369)
 ERROR / AndroidRuntime (28218): en android.telephony.SmsManager.sendTextMessage (SmsManager.java:87)
 ERROR / AndroidRuntime (28218): en com.THE.APPLICATION.MAINACT.sendMessage (MAINACT.java:214)
 ERROR / AndroidRuntime (28218): en com.THE.APPLICATION.SMSReceiver.onReceive (SMSReceiver.java:24)
 ERROR / AndroidRuntime (28218): en android.app.ActivityThread $ PackageInfo $ ReceiverDispatcher $ Args.run (ActivityThread.java:892)
 ERROR / AndroidRuntime (28218): ... 9 más

Muestra del texto del mensaje para enviar con problemas:

  VERBOSE / debug_tag (28218): msgText es: possÃvel. 

Por lo tanto, dice posible cuando debería ser posible

Por favor, algún alma iluminada me ayude. ¡Él / Ella tendrá un lugar especial en mi corazón! 🙂

Editar: Si el lugar especial en mi corazón no lo corta, estoy dispuesto a pagar unos pocos dólares por una solución funcional …

Ok, parece que esto se resolvió simplemente usando sendMultipartTextMessage lugar de sendTextMessage para los mensajes.

Quién hubiera pensado … tiene sentido porque los caracteres Unicode usan más “espacio” que los “normales”.

He usado este código para convertir caracteres UTF-8 en ASCII. Luego, el envío de SMS funciona y puedo usar 160 caracteres:

 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(); } 

Estoy usando esta línea de comando:

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

y mi mensaje SMS se ve perfecto.

Solo puedes usar 160 caracteres si se trata de encoding de 7 bits. Si usa 140 caracteres, debería funcionar sin sendMultipartTextMessage porque está utilizando caracteres de 8 bits (UTF-8).

Tengo el mismo problema con los personajes especiales. Cuando cambio el mensaje MAX_SMS_MESSAGE_LENGTH a 70, todo funciona bien. Mira ese enlace:

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

Este es mi código:

  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 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); } } 

Por supuesto, puede insertar un controlador que verifique si el mensaje contiene algún carácter especial y luego cambie MAX_SMS_MESSAGE_LENGTH de 160 a 70. Siempre tengo caracteres especiales en mi aplicación.