Posts Categorized: Android

BikeShare! para Android

¡Hola!

He estado últimamente ocupado en mi tiempo libre desarrollando una nueva app para Android. Se trata de BikeShare!, una aplicación que presenta información de los servicios públicos de bicis de 45 ciudades de todo el mundo. En España tiene las de Valenbisi (Valencia), Sevici (Sevilla), Bizi (Zaragoza), Bicing (Barcelona), Tusbic (Santander), Girocleta (Girona), Bicipalma (Palma de Mallorca), Bicileon (León), además de Ecobici de México DF y en Argentina el servicio de Buenos Aires, entre muchos otros.

Te muestra información de todas las estaciones, te indica las que tienes más cerca, y te permite guardar como favoritas las que elijas. Además autodetecta el proveedor más cercano a ti.

Si sois como yo usuarios de bicis públicas, os será de gran ayuda.

Y bueno, ya si le dais a la publi o pasáis la app a premium, ya la triunfáis conmigo.

Podéis pedirme funcionalidades o darme ideas :)


Get it on Google Play
Read more

Configurar el Swype en roms MIUI

Como muchos otros, disfruto de una ROM MIUI para mi Desire HD, concretamente la hecha por los geniales cocineros de MIUI.es. Pero la conjunción con el mejor teclado para Android, el Swype, es bastante puta.

Resulta que para licenciar tu copia de Swype se necesita poder desactivar el teclado, y eso MIUI no lo permite. Se supone que tendríamos que tener una checkbox para hacerlo pero no la hay.

Pero no desesperéis, sí hay una manera. Necesitaremos dos cosas:

  1. El instalador de un Swype nuestro, que podéis conseguir gratuitamente en la página de la beta.
  2. La aplicación Titanium Backup.

Una vez tengamos ambas cosas, tenemos que seguir unos pocos pasos al pie de la letra (funcionando a día de 9 de Junio del 2011):

  1. Si tenemos instalado el Swype con anterioridad, desinstalarlo. También desinstalar el Swype Installer.
  2. Bajar el instalador del Swype.
  3. Llegar a cuando se te activa el botón de Generate License.
  4. Cuando dice que seleccionemos otro teclado, seleccionamos uno cualquiera que no sea Swype.
  5. Llegaremos al punto que dice que desactivemos el Swype, cosa que es lo que no podemos hacer. Aquí dejamos apretada la tecla HOME hasta que salga la lista de tareas ejecutándose en ese momento.
  6. Pasamos al Titanium Backup. Allí buscamos en la segunda pestaña de Copiar/Restaurar, buscamos el Swype, clickeamos sobre su nombre, y se nos abrirá una ventana modal. En ella, seleccionamos Copiar. Una vez realizada la copia, nos dirá que se tiene que cerrar la aplicación. Después seleccionamos Desinstalar, en el propio Titanium Backup.
  7. Dejando apretada la tecla HOME, volvemos al instalador de Swype.
  8. Nos dirá que tiene que volver a bajar el Swype (debe ser la misma versión que antes). Lo hacemos. Llegaremos de nuevo al paso 6, pero esta vez nos saltamos el paso de Copiar, y vamos directamente a Desinstalar.
  9. Dejando apretada la tecla HOMEvolvemos al instalador de Swype.
  10. Nos pedirá el instalador nuestro login, aceptamos, y bajamos de nuevo el Swype (el mismo que todas las anteriores veces).
  11. Esta vez NO INSTALAMOS LA APLICACIÓN. Cuando nos salga la notificación de instalar, apretamos la tecla HOME y vamos al Titanium Backup.
  12. Buscamos el Swype, que nos saldrá como desinstalado pero con 1 copia de seguridad -la que hicimos antes-, lo seleccionamos y le damos a Restaurar.
  13. Dejamos pulsada la tecla HOME, volvemos al instalador del Swype, cancelamos la instalación y presionamos la tecla de Atrás hasta salir completamente del instalador, ignorando totalmente cuando ponga “Generating License…”.
  14. Vamos a cualquier aplicación con una cajita de texto, hasta que salga el selector de métodos de entrada. Seleccionamos cualquier teclado que no sea el Swype.
  15. Repetimos este paso, y seleccionamos el Swype esta vez.
  16. PROFIT.

Es un rollazo que te cagas, pero funciona. Espero que os sea útil :)

Read more

Implementar soporte a Emoji en aplicaciones Android

Creo que voy a comenzar explicando primero qué es esto de Emoji a los que no lo sepan, y dar un poco de antecedentes al respecto.

Originario de los keitai japoneses, los caracteres emoji vendrían a ser una variante muy arraigada de lo que conocemos por emoticonos. Vaya, sólo hay que fijarse en que los propios emoji han conseguido tener una serie de caracteres propios en el espacio unicode.

Si bien en un principio había varias variantes según el fabricante de móviles/operador japos, ahora está bastante estandarizado, al haberse metido por medio nada menos que gigantes como Apple o Google, y la revisión 6 de Unicode los aúna a todos.

Para ver una curiosa comparativa entre Emoji y la conocida Dingbats, podéis echar un vistazo a este artículo.

Pero vamos al lío. Los emoji se han popularizado en occidente por ser una manera de mostrar emoticonos en iOS (iPhone/iPad) de forma fácil, aprovechándose de las características de internacionalización del móvil, y proporcionando un interfaz común a todas las aplicaciones para ello. Por cuestiones de trabajo (…and again) he tenido que tomar decisiones al respecto de implementar un soporte a emoticonos, y me he decidido por utilizar lo más estándar que hay al respecto, que es emoji. Pero su utilización en Android de la misma manera que en iPhone no es válida, así que me ha tocado ponerme el traje de trabajo y programar una clase que me permita intercalar el texto con las imágenes.

Para empezar, hace falta el pack de imágenes que deberemos meter en /res/drawable-mdpi/ de nuestro proyecto. Os lo pongo para descargar aquí.
Pack de imágenes Emoji 1.0 - 1239 hits

Para mapear las imágenes a caracteres utilizo una clase estática que he llamado EmoticonUtils.java, y cuyo código os voy a poner aquí. Es sencilla, lo que pasa es que es un poco coñazo porque es meter muchos datos a pelo, ya que la solución elegante (usando reflection) es inviable por lentísima (y ya sabemos que a mayor gasto de CPU en un móvil, mucho mayor consumo de batería).

package com.mrm.emoji;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import com.mrm.emoji.R;
public class EmoticonUtils {
	public enum Tipo { Smiley, Place, Nature, Event, Symbol };
	private final static HashMap<String, Integer> emoticons = new HashMap<String, Integer>();
	private final static HashMap<String, String&#91;&#93;> categories = new HashMap<String, String&#91;&#93;>();
	 // Vectores de caracteres unicode en formato hex (necesitan conversión)
	private final static int[] smileys = new int[] { 0xe415, 0xe056, 0xe057, 0xe414, 0xe405, 0xe106, 0xe418, 0xe417, 0xe40d, 0xe40a, 0xe404, 0xe105, 0xe409, 0xe40e, 0xe402,
		0xe108, 0xe403, 0xe058, 0xe407, 0xe401, 0xe40f, 0xe40b, 0xe406, 0xe413, 0xe411, 0xe412, 0xe410, 0xe107, 0xe059, 0xe416, 0xe408, 0xe40c, 0xe11a,
		0xe10c, 0xe32c, 0xe32a, 0xe32d, 0xe328, 0xe32b, 0xe022, 0xe023, 0xe327, 0xe329, 0xe32e, 0xe335, 0xe334, 0xe337, 0xe336, 0xe13c, 0xe330, 0xe331,
		0xe326, 0xe03e, 0xe11d, 0xe05a, 0xe00e, 0xe421, 0xe420, 0xe00d, 0xe010, 0xe011, 0xe41e, 0xe012, 0xe422, 0xe22e, 0xe22f, 0xe231, 0xe230, 0xe427,
		0xe41d, 0xe00f, 0xe41f, 0xe14c, 0xe201, 0xe115, 0xe428, 0xe51f, 0xe429, 0xe424, 0xe423, 0xe253, 0xe426, 0xe111, 0xe425, 0xe31e, 0xe31f, 0xe31d,
		0xe001, 0xe002, 0xe005, 0xe004, 0xe51a, 0xe519, 0xe518, 0xe515, 0xe516, 0xe517, 0xe51b, 0xe152, 0xe04e, 0xe51c, 0xe51e, 0xe11c, 0xe536, 0xe003,
		0xe41c, 0xe41b, 0xe419, 0xe41a, 0xe32f, 0xe10d };
	private final static int[] places = new int[] { 0xe036, 0xe157, 0xe038, 0xe153, 0xe155, 0xe14d, 0xe156, 0xe501, 0xe158, 0xe43d, 0xe037, 0xe504, 0xe44a, 0xe146, 0xe50a, 0xe505,
		0xe506, 0xe122, 0xe508, 0xe509, 0xe03b, 0xe04d, 0xe449, 0xe44b, 0xe51d, 0xe44c, 0xe124, 0xe121, 0xe433, 0xe202, 0xe135, 0xe01c, 0xe01d, 0xe010,
		0xe136, 0xe42e, 0xe01b, 0xe15a, 0xe159, 0xe432, 0xe430, 0xe431, 0xe42f, 0xe01e, 0xe039, 0xe435, 0xe01f, 0xe125, 0xe03a, 0xe14e, 0xe252, 0xe137,
		0xe209, 0xe154, 0xe133, 0xe150, 0xe320, 0xe123, 0xe132, 0xe143, 0xe50b, 0xe514, 0xe513, 0xe50c, 0xe50d, 0xe511, 0xe50f, 0xe512, 0xe510, 0xe50e };
	private final static int[] nature = new int[] { 0xe04a, 0xe04b, 0xe049, 0xe048, 0xe04c, 0xe13d, 0xe443, 0xe43e, 0xe04f, 0xe052, 0xe053, 0xe524, 0xe52c, 0xe52a, 0xe531, 0xe050,
		0xe527, 0xe051, 0xe10b, 0xe52b, 0xe52f, 0xe109, 0xe528, 0xe01a, 0xe134, 0xe530, 0xe529, 0xe526, 0xe52d, 0xe521, 0xe523, 0xe52e, 0xe055, 0xe525,
		0xe10a, 0xe522, 0xe019, 0xe054, 0xe520, 0xe306, 0xe030, 0xe304, 0xe110, 0xe032, 0xe305, 0xe303, 0xe118, 0xe447, 0xe119, 0xe307, 0xe308, 0xe444,
		0xe441, 0xe436 };
	private final static int[] events = new int[] { 0xe437, 0xe438, 0xe43a, 0xe439, 0xe43b, 0xe117, 0xe440, 0xe442, 0xe446, 0xe445, 0xe11b, 0xe448, 0xe033, 0xe112, 0xe325, 0xe312,
		0xe310, 0xe126, 0xe127, 0xe008, 0xe03d, 0xe00c, 0xe12a, 0xe00a, 0xe00b, 0xe009, 0xe316, 0xe129, 0xe141, 0xe142, 0xe317, 0xe128, 0xe14b, 0xe211,
		0xe114, 0xe145, 0xe144, 0xe03f, 0xe313, 0xe116, 0xe10f };
	private final static int[] symbols = new int[] { 0xe21c, 0xe21d, 0xe21e, 0xe21f, 0xe220, 0xe221, 0xe222, 0xe223, 0xe224, 0xe225, 0xe210, 0xe232, 0xe233, 0xe235, 0xe234, 0xe236,
		0xe237, 0xe238, 0xe239, 0xe23b, 0xe23a, 0xe23d, 0xe23c, 0xe24d, 0xe212, 0xe24c, 0xe213, 0xe214, 0xe507, 0xe203, 0xe20b, 0xe22a, 0xe22b, 0xe226,
		0xe227, 0xe22c, 0xe22d, 0xe215, 0xe216, 0xe217, 0xe218, 0xe228, 0xe151, 0xe138, 0xe139, 0xe13a, 0xe208, 0xe14f, 0xe20a, 0xe434, 0xe309, 0xe315,
		0xe30d, 0xe207, 0xe229, 0xe206, 0xe205, 0xe204, 0xe12e, 0xe250, 0xe251, 0xe14a, 0xe149, 0xe104, 0xe103, 0xe101, 0xe102, 0xe13f, 0xe140, 0xe11f,
		0xe12f, 0xe031, 0xe30e, 0xe311, 0xe113, 0xe30f, 0xe13b, 0xe42b, 0xe42a, 0xe018, 0xe016, 0xe015, 0xe014, 0xe42c, 0xe42d, 0xe017, 0xe013, 0xe20e,
		0xe20c, 0xe20f, 0xe20d, 0xe131, 0xe12b, 0xe130, 0xe12d, 0xe324, 0xe301, 0xe148, 0xe502, 0xe03c, 0xe30a, 0xe042, 0xe040, 0xe041, 0xe12c, 0xe007,
		0xe31a, 0xe31b, 0xe13e, 0xe13b, 0xe006, 0xe302, 0xe319, 0xe321, 0xe322, 0xe314, 0xe503, 0xe10e, 0xe318, 0xe43c, 0xe11e, 0xe323, 0xe31c, 0xe034, 0xe035,
		0xe045, 0xe338, 0xe047, 0xe30c, 0xe044, 0xe30b, 0xe043, 0xe120, 0xe33b, 0xe33f, 0xe341, 0xe34c, 0xe344, 0xe342, 0xe33d, 0xe33e, 0xe340, 0xe34d,
		0xe339, 0xe147, 0xe343, 0xe33c, 0xe33a, 0xe43f, 0xe34b, 0xe046, 0xe345, 0xe346, 0xe348, 0xe347, 0xe34a, 0xe349, 0xe23f, 0xe240, 0xe241, 0xe242,
		0xe243, 0xe244, 0xe245, 0xe246, 0xe247, 0xe248, 0xe249, 0xe24a, 0xe24b, 0xe23e, 0xe532, 0xe533, 0xe534, 0xe535, 0xe21a, 0xe219, 0xe21b, 0xe02f,
		0xe024, 0xe025, 0xe026, 0xe027, 0xe028, 0xe029, 0xe02a, 0xe02b, 0xe02c, 0xe02d, 0xe02e, 0xe332, 0xe333, 0xe24e, 0xe24f, 0xe537 };
	/**
	 * Inicialización estática de los emoji
	 */
	static {
		// añadimos uno a uno los Drawable de todos los emoticonos
		// añadir los drawable usando reflection es demasiado costoso
		emoticons.put(String.format("%C",0xe001),R.drawable.emoji_e001);
		emoticons.put(String.format("%C",0xe002),R.drawable.emoji_e002);
		emoticons.put(String.format("%C",0xe003),R.drawable.emoji_e003);
		emoticons.put(String.format("%C",0xe004),R.drawable.emoji_e004);
		emoticons.put(String.format("%C",0xe005),R.drawable.emoji_e005);
		emoticons.put(String.format("%C",0xe006),R.drawable.emoji_e006);
		emoticons.put(String.format("%C",0xe007),R.drawable.emoji_e007);
		emoticons.put(String.format("%C",0xe008),R.drawable.emoji_e008);
		emoticons.put(String.format("%C",0xe009),R.drawable.emoji_e009);
		emoticons.put(String.format("%C",0xe00a),R.drawable.emoji_e00a);
		emoticons.put(String.format("%C",0xe00b),R.drawable.emoji_e00b);
		emoticons.put(String.format("%C",0xe00c),R.drawable.emoji_e00c);
		emoticons.put(String.format("%C",0xe00d),R.drawable.emoji_e00d);
		emoticons.put(String.format("%C",0xe00e),R.drawable.emoji_e00e);
		emoticons.put(String.format("%C",0xe00f),R.drawable.emoji_e00f);
		emoticons.put(String.format("%C",0xe010),R.drawable.emoji_e010);
		emoticons.put(String.format("%C",0xe011),R.drawable.emoji_e011);
		emoticons.put(String.format("%C",0xe012),R.drawable.emoji_e012);
		emoticons.put(String.format("%C",0xe013),R.drawable.emoji_e013);
		emoticons.put(String.format("%C",0xe014),R.drawable.emoji_e014);
		emoticons.put(String.format("%C",0xe015),R.drawable.emoji_e015);
		emoticons.put(String.format("%C",0xe016),R.drawable.emoji_e016);
		emoticons.put(String.format("%C",0xe017),R.drawable.emoji_e017);
		emoticons.put(String.format("%C",0xe018),R.drawable.emoji_e018);
		emoticons.put(String.format("%C",0xe019),R.drawable.emoji_e019);
		emoticons.put(String.format("%C",0xe01a),R.drawable.emoji_e01a);
		emoticons.put(String.format("%C",0xe01b),R.drawable.emoji_e01b);
		emoticons.put(String.format("%C",0xe01c),R.drawable.emoji_e01c);
		emoticons.put(String.format("%C",0xe01d),R.drawable.emoji_e01d);
		emoticons.put(String.format("%C",0xe01e),R.drawable.emoji_e01e);
		emoticons.put(String.format("%C",0xe01f),R.drawable.emoji_e01f);
		emoticons.put(String.format("%C",0xe020),R.drawable.emoji_e020);
		emoticons.put(String.format("%C",0xe021),R.drawable.emoji_e021);
		emoticons.put(String.format("%C",0xe022),R.drawable.emoji_e022);
		emoticons.put(String.format("%C",0xe023),R.drawable.emoji_e023);
		emoticons.put(String.format("%C",0xe024),R.drawable.emoji_e024);
		emoticons.put(String.format("%C",0xe025),R.drawable.emoji_e025);
		emoticons.put(String.format("%C",0xe026),R.drawable.emoji_e026);
		emoticons.put(String.format("%C",0xe027),R.drawable.emoji_e027);
		emoticons.put(String.format("%C",0xe028),R.drawable.emoji_e028);
		emoticons.put(String.format("%C",0xe029),R.drawable.emoji_e029);
		emoticons.put(String.format("%C",0xe02a),R.drawable.emoji_e02a);
		emoticons.put(String.format("%C",0xe02b),R.drawable.emoji_e02b);
		emoticons.put(String.format("%C",0xe02c),R.drawable.emoji_e02c);
		emoticons.put(String.format("%C",0xe02d),R.drawable.emoji_e02d);
		emoticons.put(String.format("%C",0xe02e),R.drawable.emoji_e02e);
		emoticons.put(String.format("%C",0xe02f),R.drawable.emoji_e02f);
		emoticons.put(String.format("%C",0xe030),R.drawable.emoji_e030);
		emoticons.put(String.format("%C",0xe031),R.drawable.emoji_e031);
		emoticons.put(String.format("%C",0xe032),R.drawable.emoji_e032);
		emoticons.put(String.format("%C",0xe033),R.drawable.emoji_e033);
		emoticons.put(String.format("%C",0xe034),R.drawable.emoji_e034);
		emoticons.put(String.format("%C",0xe035),R.drawable.emoji_e035);
		emoticons.put(String.format("%C",0xe036),R.drawable.emoji_e036);
		emoticons.put(String.format("%C",0xe037),R.drawable.emoji_e037);
		emoticons.put(String.format("%C",0xe038),R.drawable.emoji_e038);
		emoticons.put(String.format("%C",0xe039),R.drawable.emoji_e039);
		emoticons.put(String.format("%C",0xe03a),R.drawable.emoji_e03a);
		emoticons.put(String.format("%C",0xe03b),R.drawable.emoji_e03b);
		emoticons.put(String.format("%C",0xe03c),R.drawable.emoji_e03c);
		emoticons.put(String.format("%C",0xe03d),R.drawable.emoji_e03d);
		emoticons.put(String.format("%C",0xe03e),R.drawable.emoji_e03e);
		emoticons.put(String.format("%C",0xe03f),R.drawable.emoji_e03f);
		emoticons.put(String.format("%C",0xe040),R.drawable.emoji_e040);
		emoticons.put(String.format("%C",0xe041),R.drawable.emoji_e041);
		emoticons.put(String.format("%C",0xe042),R.drawable.emoji_e042);
		emoticons.put(String.format("%C",0xe043),R.drawable.emoji_e043);
		emoticons.put(String.format("%C",0xe044),R.drawable.emoji_e044);
		emoticons.put(String.format("%C",0xe045),R.drawable.emoji_e045);
		emoticons.put(String.format("%C",0xe046),R.drawable.emoji_e046);
		emoticons.put(String.format("%C",0xe047),R.drawable.emoji_e047);
		emoticons.put(String.format("%C",0xe048),R.drawable.emoji_e048);
		emoticons.put(String.format("%C",0xe049),R.drawable.emoji_e049);
		emoticons.put(String.format("%C",0xe04a),R.drawable.emoji_e04a);
		emoticons.put(String.format("%C",0xe04b),R.drawable.emoji_e04b);
		emoticons.put(String.format("%C",0xe04c),R.drawable.emoji_e04c);
		emoticons.put(String.format("%C",0xe04d),R.drawable.emoji_e04d);
		emoticons.put(String.format("%C",0xe04e),R.drawable.emoji_e04e);
		emoticons.put(String.format("%C",0xe04f),R.drawable.emoji_e04f);
		emoticons.put(String.format("%C",0xe050),R.drawable.emoji_e050);
		emoticons.put(String.format("%C",0xe051),R.drawable.emoji_e051);
		emoticons.put(String.format("%C",0xe052),R.drawable.emoji_e052);
		emoticons.put(String.format("%C",0xe053),R.drawable.emoji_e053);
		emoticons.put(String.format("%C",0xe054),R.drawable.emoji_e054);
		emoticons.put(String.format("%C",0xe055),R.drawable.emoji_e055);
		emoticons.put(String.format("%C",0xe056),R.drawable.emoji_e056);
		emoticons.put(String.format("%C",0xe057),R.drawable.emoji_e057);
		emoticons.put(String.format("%C",0xe058),R.drawable.emoji_e058);
		emoticons.put(String.format("%C",0xe059),R.drawable.emoji_e059);
		emoticons.put(String.format("%C",0xe05a),R.drawable.emoji_e05a);
		emoticons.put(String.format("%C",0xe101),R.drawable.emoji_e101);
		emoticons.put(String.format("%C",0xe102),R.drawable.emoji_e102);
		emoticons.put(String.format("%C",0xe103),R.drawable.emoji_e103);
		emoticons.put(String.format("%C",0xe104),R.drawable.emoji_e104);
		emoticons.put(String.format("%C",0xe105),R.drawable.emoji_e105);
		emoticons.put(String.format("%C",0xe106),R.drawable.emoji_e106);
		emoticons.put(String.format("%C",0xe107),R.drawable.emoji_e107);
		emoticons.put(String.format("%C",0xe108),R.drawable.emoji_e108);
		emoticons.put(String.format("%C",0xe109),R.drawable.emoji_e109);
		emoticons.put(String.format("%C",0xe10a),R.drawable.emoji_e10a);
		emoticons.put(String.format("%C",0xe10b),R.drawable.emoji_e10b);
		emoticons.put(String.format("%C",0xe10c),R.drawable.emoji_e10c);
		emoticons.put(String.format("%C",0xe10d),R.drawable.emoji_e10d);
		emoticons.put(String.format("%C",0xe10e),R.drawable.emoji_e10e);
		emoticons.put(String.format("%C",0xe10f),R.drawable.emoji_e10f);
		emoticons.put(String.format("%C",0xe110),R.drawable.emoji_e110);
		emoticons.put(String.format("%C",0xe111),R.drawable.emoji_e111);
		emoticons.put(String.format("%C",0xe112),R.drawable.emoji_e112);
		emoticons.put(String.format("%C",0xe113),R.drawable.emoji_e113);
		emoticons.put(String.format("%C",0xe114),R.drawable.emoji_e114);
		emoticons.put(String.format("%C",0xe115),R.drawable.emoji_e115);
		emoticons.put(String.format("%C",0xe116),R.drawable.emoji_e116);
		emoticons.put(String.format("%C",0xe117),R.drawable.emoji_e117);
		emoticons.put(String.format("%C",0xe118),R.drawable.emoji_e118);
		emoticons.put(String.format("%C",0xe119),R.drawable.emoji_e119);
		emoticons.put(String.format("%C",0xe11a),R.drawable.emoji_e11a);
		emoticons.put(String.format("%C",0xe11b),R.drawable.emoji_e11b);
		emoticons.put(String.format("%C",0xe11c),R.drawable.emoji_e11c);
		emoticons.put(String.format("%C",0xe11d),R.drawable.emoji_e11d);
		emoticons.put(String.format("%C",0xe11e),R.drawable.emoji_e11e);
		emoticons.put(String.format("%C",0xe11f),R.drawable.emoji_e11f);
		emoticons.put(String.format("%C",0xe120),R.drawable.emoji_e120);
		emoticons.put(String.format("%C",0xe121),R.drawable.emoji_e121);
		emoticons.put(String.format("%C",0xe122),R.drawable.emoji_e122);
		emoticons.put(String.format("%C",0xe123),R.drawable.emoji_e123);
		emoticons.put(String.format("%C",0xe124),R.drawable.emoji_e124);
		emoticons.put(String.format("%C",0xe125),R.drawable.emoji_e125);
		emoticons.put(String.format("%C",0xe126),R.drawable.emoji_e126);
		emoticons.put(String.format("%C",0xe127),R.drawable.emoji_e127);
		emoticons.put(String.format("%C",0xe128),R.drawable.emoji_e128);
		emoticons.put(String.format("%C",0xe129),R.drawable.emoji_e129);
		emoticons.put(String.format("%C",0xe12a),R.drawable.emoji_e12a);
		emoticons.put(String.format("%C",0xe12b),R.drawable.emoji_e12b);
		emoticons.put(String.format("%C",0xe12c),R.drawable.emoji_e12c);
		emoticons.put(String.format("%C",0xe12d),R.drawable.emoji_e12d);
		emoticons.put(String.format("%C",0xe12e),R.drawable.emoji_e12e);
		emoticons.put(String.format("%C",0xe12f),R.drawable.emoji_e12f);
		emoticons.put(String.format("%C",0xe130),R.drawable.emoji_e130);
		emoticons.put(String.format("%C",0xe131),R.drawable.emoji_e131);
		emoticons.put(String.format("%C",0xe132),R.drawable.emoji_e132);
		emoticons.put(String.format("%C",0xe133),R.drawable.emoji_e133);
		emoticons.put(String.format("%C",0xe134),R.drawable.emoji_e134);
		emoticons.put(String.format("%C",0xe135),R.drawable.emoji_e135);
		emoticons.put(String.format("%C",0xe136),R.drawable.emoji_e136);
		emoticons.put(String.format("%C",0xe137),R.drawable.emoji_e137);
		emoticons.put(String.format("%C",0xe138),R.drawable.emoji_e138);
		emoticons.put(String.format("%C",0xe139),R.drawable.emoji_e139);
		emoticons.put(String.format("%C",0xe13a),R.drawable.emoji_e13a);
		emoticons.put(String.format("%C",0xe13b),R.drawable.emoji_e13b);
		emoticons.put(String.format("%C",0xe13c),R.drawable.emoji_e13c);
		emoticons.put(String.format("%C",0xe13d),R.drawable.emoji_e13d);
		emoticons.put(String.format("%C",0xe13e),R.drawable.emoji_e13e);
		emoticons.put(String.format("%C",0xe13f),R.drawable.emoji_e13f);
		emoticons.put(String.format("%C",0xe140),R.drawable.emoji_e140);
		emoticons.put(String.format("%C",0xe141),R.drawable.emoji_e141);
		emoticons.put(String.format("%C",0xe142),R.drawable.emoji_e142);
		emoticons.put(String.format("%C",0xe143),R.drawable.emoji_e143);
		emoticons.put(String.format("%C",0xe144),R.drawable.emoji_e144);
		emoticons.put(String.format("%C",0xe145),R.drawable.emoji_e145);
		emoticons.put(String.format("%C",0xe146),R.drawable.emoji_e146);
		emoticons.put(String.format("%C",0xe147),R.drawable.emoji_e147);
		emoticons.put(String.format("%C",0xe148),R.drawable.emoji_e148);
		emoticons.put(String.format("%C",0xe149),R.drawable.emoji_e149);
		emoticons.put(String.format("%C",0xe14a),R.drawable.emoji_e14a);
		emoticons.put(String.format("%C",0xe14b),R.drawable.emoji_e14b);
		emoticons.put(String.format("%C",0xe14c),R.drawable.emoji_e14c);
		emoticons.put(String.format("%C",0xe14d),R.drawable.emoji_e14d);
		emoticons.put(String.format("%C",0xe14e),R.drawable.emoji_e14e);
		emoticons.put(String.format("%C",0xe14f),R.drawable.emoji_e14f);
		emoticons.put(String.format("%C",0xe150),R.drawable.emoji_e150);
		emoticons.put(String.format("%C",0xe151),R.drawable.emoji_e151);
		emoticons.put(String.format("%C",0xe152),R.drawable.emoji_e152);
		emoticons.put(String.format("%C",0xe153),R.drawable.emoji_e153);
		emoticons.put(String.format("%C",0xe154),R.drawable.emoji_e154);
		emoticons.put(String.format("%C",0xe155),R.drawable.emoji_e155);
		emoticons.put(String.format("%C",0xe156),R.drawable.emoji_e156);
		emoticons.put(String.format("%C",0xe157),R.drawable.emoji_e157);
		emoticons.put(String.format("%C",0xe158),R.drawable.emoji_e158);
		emoticons.put(String.format("%C",0xe159),R.drawable.emoji_e159);
		emoticons.put(String.format("%C",0xe15a),R.drawable.emoji_e15a);
		emoticons.put(String.format("%C",0xe201),R.drawable.emoji_e201);
		emoticons.put(String.format("%C",0xe202),R.drawable.emoji_e202);
		emoticons.put(String.format("%C",0xe203),R.drawable.emoji_e203);
		emoticons.put(String.format("%C",0xe204),R.drawable.emoji_e204);
		emoticons.put(String.format("%C",0xe205),R.drawable.emoji_e205);
		emoticons.put(String.format("%C",0xe206),R.drawable.emoji_e206);
		emoticons.put(String.format("%C",0xe207),R.drawable.emoji_e207);
		emoticons.put(String.format("%C",0xe208),R.drawable.emoji_e208);
		emoticons.put(String.format("%C",0xe209),R.drawable.emoji_e209);
		emoticons.put(String.format("%C",0xe20a),R.drawable.emoji_e20a);
		emoticons.put(String.format("%C",0xe20b),R.drawable.emoji_e20b);
		emoticons.put(String.format("%C",0xe20c),R.drawable.emoji_e20c);
		emoticons.put(String.format("%C",0xe20d),R.drawable.emoji_e20d);
		emoticons.put(String.format("%C",0xe20e),R.drawable.emoji_e20e);
		emoticons.put(String.format("%C",0xe20f),R.drawable.emoji_e20f);
		emoticons.put(String.format("%C",0xe210),R.drawable.emoji_e210);
		emoticons.put(String.format("%C",0xe211),R.drawable.emoji_e211);
		emoticons.put(String.format("%C",0xe212),R.drawable.emoji_e212);
		emoticons.put(String.format("%C",0xe213),R.drawable.emoji_e213);
		emoticons.put(String.format("%C",0xe214),R.drawable.emoji_e214);
		emoticons.put(String.format("%C",0xe215),R.drawable.emoji_e215);
		emoticons.put(String.format("%C",0xe216),R.drawable.emoji_e216);
		emoticons.put(String.format("%C",0xe217),R.drawable.emoji_e217);
		emoticons.put(String.format("%C",0xe218),R.drawable.emoji_e218);
		emoticons.put(String.format("%C",0xe219),R.drawable.emoji_e219);
		emoticons.put(String.format("%C",0xe21a),R.drawable.emoji_e21a);
		emoticons.put(String.format("%C",0xe21b),R.drawable.emoji_e21b);
		emoticons.put(String.format("%C",0xe21c),R.drawable.emoji_e21c);
		emoticons.put(String.format("%C",0xe21d),R.drawable.emoji_e21d);
		emoticons.put(String.format("%C",0xe21e),R.drawable.emoji_e21e);
		emoticons.put(String.format("%C",0xe21f),R.drawable.emoji_e21f);
		emoticons.put(String.format("%C",0xe220),R.drawable.emoji_e220);
		emoticons.put(String.format("%C",0xe221),R.drawable.emoji_e221);
		emoticons.put(String.format("%C",0xe222),R.drawable.emoji_e222);
		emoticons.put(String.format("%C",0xe223),R.drawable.emoji_e223);
		emoticons.put(String.format("%C",0xe224),R.drawable.emoji_e224);
		emoticons.put(String.format("%C",0xe225),R.drawable.emoji_e225);
		emoticons.put(String.format("%C",0xe226),R.drawable.emoji_e226);
		emoticons.put(String.format("%C",0xe227),R.drawable.emoji_e227);
		emoticons.put(String.format("%C",0xe228),R.drawable.emoji_e228);
		emoticons.put(String.format("%C",0xe229),R.drawable.emoji_e229);
		emoticons.put(String.format("%C",0xe22a),R.drawable.emoji_e22a);
		emoticons.put(String.format("%C",0xe22b),R.drawable.emoji_e22b);
		emoticons.put(String.format("%C",0xe22c),R.drawable.emoji_e22c);
		emoticons.put(String.format("%C",0xe22d),R.drawable.emoji_e22d);
		emoticons.put(String.format("%C",0xe22e),R.drawable.emoji_e22e);
		emoticons.put(String.format("%C",0xe22f),R.drawable.emoji_e22f);
		emoticons.put(String.format("%C",0xe230),R.drawable.emoji_e230);
		emoticons.put(String.format("%C",0xe231),R.drawable.emoji_e231);
		emoticons.put(String.format("%C",0xe232),R.drawable.emoji_e232);
		emoticons.put(String.format("%C",0xe233),R.drawable.emoji_e233);
		emoticons.put(String.format("%C",0xe234),R.drawable.emoji_e234);
		emoticons.put(String.format("%C",0xe235),R.drawable.emoji_e235);
		emoticons.put(String.format("%C",0xe236),R.drawable.emoji_e236);
		emoticons.put(String.format("%C",0xe237),R.drawable.emoji_e237);
		emoticons.put(String.format("%C",0xe238),R.drawable.emoji_e238);
		emoticons.put(String.format("%C",0xe239),R.drawable.emoji_e239);
		emoticons.put(String.format("%C",0xe23a),R.drawable.emoji_e23a);
		emoticons.put(String.format("%C",0xe23b),R.drawable.emoji_e23b);
		emoticons.put(String.format("%C",0xe23c),R.drawable.emoji_e23c);
		emoticons.put(String.format("%C",0xe23d),R.drawable.emoji_e23d);
		emoticons.put(String.format("%C",0xe23e),R.drawable.emoji_e23e);
		emoticons.put(String.format("%C",0xe23f),R.drawable.emoji_e23f);
		emoticons.put(String.format("%C",0xe240),R.drawable.emoji_e240);
		emoticons.put(String.format("%C",0xe241),R.drawable.emoji_e241);
		emoticons.put(String.format("%C",0xe242),R.drawable.emoji_e242);
		emoticons.put(String.format("%C",0xe243),R.drawable.emoji_e243);
		emoticons.put(String.format("%C",0xe244),R.drawable.emoji_e244);
		emoticons.put(String.format("%C",0xe245),R.drawable.emoji_e245);
		emoticons.put(String.format("%C",0xe246),R.drawable.emoji_e246);
		emoticons.put(String.format("%C",0xe247),R.drawable.emoji_e247);
		emoticons.put(String.format("%C",0xe248),R.drawable.emoji_e248);
		emoticons.put(String.format("%C",0xe249),R.drawable.emoji_e249);
		emoticons.put(String.format("%C",0xe24a),R.drawable.emoji_e24a);
		emoticons.put(String.format("%C",0xe24b),R.drawable.emoji_e24b);
		emoticons.put(String.format("%C",0xe24c),R.drawable.emoji_e24c);
		emoticons.put(String.format("%C",0xe24d),R.drawable.emoji_e24d);
		emoticons.put(String.format("%C",0xe24e),R.drawable.emoji_e24e);
		emoticons.put(String.format("%C",0xe24f),R.drawable.emoji_e24f);
		emoticons.put(String.format("%C",0xe250),R.drawable.emoji_e250);
		emoticons.put(String.format("%C",0xe251),R.drawable.emoji_e251);
		emoticons.put(String.format("%C",0xe252),R.drawable.emoji_e252);
		emoticons.put(String.format("%C",0xe253),R.drawable.emoji_e253);
		emoticons.put(String.format("%C",0xe301),R.drawable.emoji_e301);
		emoticons.put(String.format("%C",0xe302),R.drawable.emoji_e302);
		emoticons.put(String.format("%C",0xe303),R.drawable.emoji_e303);
		emoticons.put(String.format("%C",0xe304),R.drawable.emoji_e304);
		emoticons.put(String.format("%C",0xe305),R.drawable.emoji_e305);
		emoticons.put(String.format("%C",0xe306),R.drawable.emoji_e306);
		emoticons.put(String.format("%C",0xe307),R.drawable.emoji_e307);
		emoticons.put(String.format("%C",0xe308),R.drawable.emoji_e308);
		emoticons.put(String.format("%C",0xe309),R.drawable.emoji_e309);
		emoticons.put(String.format("%C",0xe30a),R.drawable.emoji_e30a);
		emoticons.put(String.format("%C",0xe30b),R.drawable.emoji_e30b);
		emoticons.put(String.format("%C",0xe30c),R.drawable.emoji_e30c);
		emoticons.put(String.format("%C",0xe30d),R.drawable.emoji_e30d);
		emoticons.put(String.format("%C",0xe30e),R.drawable.emoji_e30e);
		emoticons.put(String.format("%C",0xe30f),R.drawable.emoji_e30f);
		emoticons.put(String.format("%C",0xe310),R.drawable.emoji_e310);
		emoticons.put(String.format("%C",0xe311),R.drawable.emoji_e311);
		emoticons.put(String.format("%C",0xe312),R.drawable.emoji_e312);
		emoticons.put(String.format("%C",0xe313),R.drawable.emoji_e313);
		emoticons.put(String.format("%C",0xe314),R.drawable.emoji_e314);
		emoticons.put(String.format("%C",0xe315),R.drawable.emoji_e315);
		emoticons.put(String.format("%C",0xe316),R.drawable.emoji_e316);
		emoticons.put(String.format("%C",0xe317),R.drawable.emoji_e317);
		emoticons.put(String.format("%C",0xe318),R.drawable.emoji_e318);
		emoticons.put(String.format("%C",0xe319),R.drawable.emoji_e319);
		emoticons.put(String.format("%C",0xe31a),R.drawable.emoji_e31a);
		emoticons.put(String.format("%C",0xe31b),R.drawable.emoji_e31b);
		emoticons.put(String.format("%C",0xe31c),R.drawable.emoji_e31c);
		emoticons.put(String.format("%C",0xe31d),R.drawable.emoji_e31d);
		emoticons.put(String.format("%C",0xe31e),R.drawable.emoji_e31e);
		emoticons.put(String.format("%C",0xe31f),R.drawable.emoji_e31f);
		emoticons.put(String.format("%C",0xe320),R.drawable.emoji_e320);
		emoticons.put(String.format("%C",0xe321),R.drawable.emoji_e321);
		emoticons.put(String.format("%C",0xe322),R.drawable.emoji_e322);
		emoticons.put(String.format("%C",0xe323),R.drawable.emoji_e323);
		emoticons.put(String.format("%C",0xe324),R.drawable.emoji_e324);
		emoticons.put(String.format("%C",0xe325),R.drawable.emoji_e325);
		emoticons.put(String.format("%C",0xe326),R.drawable.emoji_e326);
		emoticons.put(String.format("%C",0xe327),R.drawable.emoji_e327);
		emoticons.put(String.format("%C",0xe328),R.drawable.emoji_e328);
		emoticons.put(String.format("%C",0xe329),R.drawable.emoji_e329);
		emoticons.put(String.format("%C",0xe32a),R.drawable.emoji_e32a);
		emoticons.put(String.format("%C",0xe32b),R.drawable.emoji_e32b);
		emoticons.put(String.format("%C",0xe32c),R.drawable.emoji_e32c);
		emoticons.put(String.format("%C",0xe32d),R.drawable.emoji_e32d);
		emoticons.put(String.format("%C",0xe32e),R.drawable.emoji_e32e);
		emoticons.put(String.format("%C",0xe32f),R.drawable.emoji_e32f);
		emoticons.put(String.format("%C",0xe330),R.drawable.emoji_e330);
		emoticons.put(String.format("%C",0xe331),R.drawable.emoji_e331);
		emoticons.put(String.format("%C",0xe332),R.drawable.emoji_e332);
		emoticons.put(String.format("%C",0xe333),R.drawable.emoji_e333);
		emoticons.put(String.format("%C",0xe334),R.drawable.emoji_e334);
		emoticons.put(String.format("%C",0xe335),R.drawable.emoji_e335);
		emoticons.put(String.format("%C",0xe336),R.drawable.emoji_e336);
		emoticons.put(String.format("%C",0xe337),R.drawable.emoji_e337);
		emoticons.put(String.format("%C",0xe338),R.drawable.emoji_e338);
		emoticons.put(String.format("%C",0xe339),R.drawable.emoji_e339);
		emoticons.put(String.format("%C",0xe33a),R.drawable.emoji_e33a);
		emoticons.put(String.format("%C",0xe33b),R.drawable.emoji_e33b);
		emoticons.put(String.format("%C",0xe33c),R.drawable.emoji_e33c);
		emoticons.put(String.format("%C",0xe33d),R.drawable.emoji_e33d);
		emoticons.put(String.format("%C",0xe33e),R.drawable.emoji_e33e);
		emoticons.put(String.format("%C",0xe33f),R.drawable.emoji_e33f);
		emoticons.put(String.format("%C",0xe340),R.drawable.emoji_e340);
		emoticons.put(String.format("%C",0xe341),R.drawable.emoji_e341);
		emoticons.put(String.format("%C",0xe342),R.drawable.emoji_e342);
		emoticons.put(String.format("%C",0xe343),R.drawable.emoji_e343);
		emoticons.put(String.format("%C",0xe344),R.drawable.emoji_e344);
		emoticons.put(String.format("%C",0xe345),R.drawable.emoji_e345);
		emoticons.put(String.format("%C",0xe346),R.drawable.emoji_e346);
		emoticons.put(String.format("%C",0xe347),R.drawable.emoji_e347);
		emoticons.put(String.format("%C",0xe348),R.drawable.emoji_e348);
		emoticons.put(String.format("%C",0xe349),R.drawable.emoji_e349);
		emoticons.put(String.format("%C",0xe34a),R.drawable.emoji_e34a);
		emoticons.put(String.format("%C",0xe34b),R.drawable.emoji_e34b);
		emoticons.put(String.format("%C",0xe34c),R.drawable.emoji_e34c);
		emoticons.put(String.format("%C",0xe34d),R.drawable.emoji_e34d);
		emoticons.put(String.format("%C",0xe401),R.drawable.emoji_e401);
		emoticons.put(String.format("%C",0xe402),R.drawable.emoji_e402);
		emoticons.put(String.format("%C",0xe403),R.drawable.emoji_e403);
		emoticons.put(String.format("%C",0xe404),R.drawable.emoji_e404);
		emoticons.put(String.format("%C",0xe405),R.drawable.emoji_e405);
		emoticons.put(String.format("%C",0xe406),R.drawable.emoji_e406);
		emoticons.put(String.format("%C",0xe407),R.drawable.emoji_e407);
		emoticons.put(String.format("%C",0xe408),R.drawable.emoji_e408);
		emoticons.put(String.format("%C",0xe409),R.drawable.emoji_e409);
		emoticons.put(String.format("%C",0xe40a),R.drawable.emoji_e40a);
		emoticons.put(String.format("%C",0xe40b),R.drawable.emoji_e40b);
		emoticons.put(String.format("%C",0xe40c),R.drawable.emoji_e40c);
		emoticons.put(String.format("%C",0xe40d),R.drawable.emoji_e40d);
		emoticons.put(String.format("%C",0xe40e),R.drawable.emoji_e40e);
		emoticons.put(String.format("%C",0xe40f),R.drawable.emoji_e40f);
		emoticons.put(String.format("%C",0xe410),R.drawable.emoji_e410);
		emoticons.put(String.format("%C",0xe411),R.drawable.emoji_e411);
		emoticons.put(String.format("%C",0xe412),R.drawable.emoji_e412);
		emoticons.put(String.format("%C",0xe413),R.drawable.emoji_e413);
		emoticons.put(String.format("%C",0xe414),R.drawable.emoji_e414);
		emoticons.put(String.format("%C",0xe415),R.drawable.emoji_e415);
		emoticons.put(String.format("%C",0xe416),R.drawable.emoji_e416);
		emoticons.put(String.format("%C",0xe417),R.drawable.emoji_e417);
		emoticons.put(String.format("%C",0xe418),R.drawable.emoji_e418);
		emoticons.put(String.format("%C",0xe419),R.drawable.emoji_e419);
		emoticons.put(String.format("%C",0xe41a),R.drawable.emoji_e41a);
		emoticons.put(String.format("%C",0xe41b),R.drawable.emoji_e41b);
		emoticons.put(String.format("%C",0xe41c),R.drawable.emoji_e41c);
		emoticons.put(String.format("%C",0xe41d),R.drawable.emoji_e41d);
		emoticons.put(String.format("%C",0xe41e),R.drawable.emoji_e41e);
		emoticons.put(String.format("%C",0xe41f),R.drawable.emoji_e41f);
		emoticons.put(String.format("%C",0xe420),R.drawable.emoji_e420);
		emoticons.put(String.format("%C",0xe421),R.drawable.emoji_e421);
		emoticons.put(String.format("%C",0xe422),R.drawable.emoji_e422);
		emoticons.put(String.format("%C",0xe423),R.drawable.emoji_e423);
		emoticons.put(String.format("%C",0xe424),R.drawable.emoji_e424);
		emoticons.put(String.format("%C",0xe425),R.drawable.emoji_e425);
		emoticons.put(String.format("%C",0xe426),R.drawable.emoji_e426);
		emoticons.put(String.format("%C",0xe427),R.drawable.emoji_e427);
		emoticons.put(String.format("%C",0xe428),R.drawable.emoji_e428);
		emoticons.put(String.format("%C",0xe429),R.drawable.emoji_e429);
		emoticons.put(String.format("%C",0xe42a),R.drawable.emoji_e42a);
		emoticons.put(String.format("%C",0xe42b),R.drawable.emoji_e42b);
		emoticons.put(String.format("%C",0xe42c),R.drawable.emoji_e42c);
		emoticons.put(String.format("%C",0xe42d),R.drawable.emoji_e42d);
		emoticons.put(String.format("%C",0xe42e),R.drawable.emoji_e42e);
		emoticons.put(String.format("%C",0xe42f),R.drawable.emoji_e42f);
		emoticons.put(String.format("%C",0xe430),R.drawable.emoji_e430);
		emoticons.put(String.format("%C",0xe431),R.drawable.emoji_e431);
		emoticons.put(String.format("%C",0xe432),R.drawable.emoji_e432);
		emoticons.put(String.format("%C",0xe433),R.drawable.emoji_e433);
		emoticons.put(String.format("%C",0xe434),R.drawable.emoji_e434);
		emoticons.put(String.format("%C",0xe435),R.drawable.emoji_e435);
		emoticons.put(String.format("%C",0xe436),R.drawable.emoji_e436);
		emoticons.put(String.format("%C",0xe437),R.drawable.emoji_e437);
		emoticons.put(String.format("%C",0xe438),R.drawable.emoji_e438);
		emoticons.put(String.format("%C",0xe439),R.drawable.emoji_e439);
		emoticons.put(String.format("%C",0xe43a),R.drawable.emoji_e43a);
		emoticons.put(String.format("%C",0xe43b),R.drawable.emoji_e43b);
		emoticons.put(String.format("%C",0xe43c),R.drawable.emoji_e43c);
		emoticons.put(String.format("%C",0xe43d),R.drawable.emoji_e43d);
		emoticons.put(String.format("%C",0xe43e),R.drawable.emoji_e43e);
		emoticons.put(String.format("%C",0xe43f),R.drawable.emoji_e43f);
		emoticons.put(String.format("%C",0xe440),R.drawable.emoji_e440);
		emoticons.put(String.format("%C",0xe441),R.drawable.emoji_e441);
		emoticons.put(String.format("%C",0xe442),R.drawable.emoji_e442);
		emoticons.put(String.format("%C",0xe443),R.drawable.emoji_e443);
		emoticons.put(String.format("%C",0xe444),R.drawable.emoji_e444);
		emoticons.put(String.format("%C",0xe445),R.drawable.emoji_e445);
		emoticons.put(String.format("%C",0xe446),R.drawable.emoji_e446);
		emoticons.put(String.format("%C",0xe447),R.drawable.emoji_e447);
		emoticons.put(String.format("%C",0xe448),R.drawable.emoji_e448);
		emoticons.put(String.format("%C",0xe449),R.drawable.emoji_e449);
		emoticons.put(String.format("%C",0xe44a),R.drawable.emoji_e44a);
		emoticons.put(String.format("%C",0xe44b),R.drawable.emoji_e44b);
		emoticons.put(String.format("%C",0xe44c),R.drawable.emoji_e44c);
		emoticons.put(String.format("%C",0xe501),R.drawable.emoji_e501);
		emoticons.put(String.format("%C",0xe502),R.drawable.emoji_e502);
		emoticons.put(String.format("%C",0xe503),R.drawable.emoji_e503);
		emoticons.put(String.format("%C",0xe504),R.drawable.emoji_e504);
		emoticons.put(String.format("%C",0xe505),R.drawable.emoji_e505);
		emoticons.put(String.format("%C",0xe506),R.drawable.emoji_e506);
		emoticons.put(String.format("%C",0xe507),R.drawable.emoji_e507);
		emoticons.put(String.format("%C",0xe508),R.drawable.emoji_e508);
		emoticons.put(String.format("%C",0xe509),R.drawable.emoji_e509);
		emoticons.put(String.format("%C",0xe50a),R.drawable.emoji_e50a);
		emoticons.put(String.format("%C",0xe50b),R.drawable.emoji_e50b);
		emoticons.put(String.format("%C",0xe50c),R.drawable.emoji_e50c);
		emoticons.put(String.format("%C",0xe50d),R.drawable.emoji_e50d);
		emoticons.put(String.format("%C",0xe50e),R.drawable.emoji_e50e);
		emoticons.put(String.format("%C",0xe50f),R.drawable.emoji_e50f);
		emoticons.put(String.format("%C",0xe510),R.drawable.emoji_e510);
		emoticons.put(String.format("%C",0xe511),R.drawable.emoji_e511);
		emoticons.put(String.format("%C",0xe512),R.drawable.emoji_e512);
		emoticons.put(String.format("%C",0xe513),R.drawable.emoji_e513);
		emoticons.put(String.format("%C",0xe514),R.drawable.emoji_e514);
		emoticons.put(String.format("%C",0xe515),R.drawable.emoji_e515);
		emoticons.put(String.format("%C",0xe516),R.drawable.emoji_e516);
		emoticons.put(String.format("%C",0xe517),R.drawable.emoji_e517);
		emoticons.put(String.format("%C",0xe518),R.drawable.emoji_e518);
		emoticons.put(String.format("%C",0xe519),R.drawable.emoji_e519);
		emoticons.put(String.format("%C",0xe51a),R.drawable.emoji_e51a);
		emoticons.put(String.format("%C",0xe51b),R.drawable.emoji_e51b);
		emoticons.put(String.format("%C",0xe51c),R.drawable.emoji_e51c);
		emoticons.put(String.format("%C",0xe51d),R.drawable.emoji_e51d);
		emoticons.put(String.format("%C",0xe51e),R.drawable.emoji_e51e);
		emoticons.put(String.format("%C",0xe51f),R.drawable.emoji_e51f);
		emoticons.put(String.format("%C",0xe520),R.drawable.emoji_e520);
		emoticons.put(String.format("%C",0xe521),R.drawable.emoji_e521);
		emoticons.put(String.format("%C",0xe522),R.drawable.emoji_e522);
		emoticons.put(String.format("%C",0xe523),R.drawable.emoji_e523);
		emoticons.put(String.format("%C",0xe524),R.drawable.emoji_e524);
		emoticons.put(String.format("%C",0xe525),R.drawable.emoji_e525);
		emoticons.put(String.format("%C",0xe526),R.drawable.emoji_e526);
		emoticons.put(String.format("%C",0xe527),R.drawable.emoji_e527);
		emoticons.put(String.format("%C",0xe528),R.drawable.emoji_e528);
		emoticons.put(String.format("%C",0xe529),R.drawable.emoji_e529);
		emoticons.put(String.format("%C",0xe52a),R.drawable.emoji_e52a);
		emoticons.put(String.format("%C",0xe52b),R.drawable.emoji_e52b);
		emoticons.put(String.format("%C",0xe52c),R.drawable.emoji_e52c);
		emoticons.put(String.format("%C",0xe52d),R.drawable.emoji_e52d);
		emoticons.put(String.format("%C",0xe52e),R.drawable.emoji_e52e);
		emoticons.put(String.format("%C",0xe52f),R.drawable.emoji_e52f);
		emoticons.put(String.format("%C",0xe530),R.drawable.emoji_e530);
		emoticons.put(String.format("%C",0xe531),R.drawable.emoji_e531);
		emoticons.put(String.format("%C",0xe532),R.drawable.emoji_e532);
		emoticons.put(String.format("%C",0xe533),R.drawable.emoji_e533);
		emoticons.put(String.format("%C",0xe534),R.drawable.emoji_e534);
		emoticons.put(String.format("%C",0xe535),R.drawable.emoji_e535);
		emoticons.put(String.format("%C",0xe536),R.drawable.emoji_e536);
		emoticons.put(String.format("%C",0xe537),R.drawable.emoji_e537);
		// así solamente se realiza la búsqueda en la inicialización
		categories.put(Tipo.Smiley.toString(), getCharsFromTags(Tipo.Smiley));
		categories.put(Tipo.Event.toString(), getCharsFromTags(Tipo.Event));
		categories.put(Tipo.Nature.toString(), getCharsFromTags(Tipo.Nature));
		categories.put(Tipo.Place.toString(), getCharsFromTags(Tipo.Place));
		categories.put(Tipo.Symbol.toString(), getCharsFromTags(Tipo.Symbol));
	}
	/**
	 * Transforma los vectores de código hexadecimal con los códigos de caracter unicode a los propios caracteres
	 * @param tipo Categoría del emoticono deseado
	 * @return Vector de caracteres unicode
	 */
	private static String[] getCharsFromTags(Tipo tipo) {
		int[] array = null;
		switch (tipo) {
			case Smiley:
				array = smileys;
				break;
			case Event:
				array = events;
				break;
			case Nature:
				array = nature;
				break;
			case Place:
				array = places;
				break;
			case Symbol:
				array = symbols;
				break;
		}
		LinkedList<String> tags = new LinkedList<String>();
		for (int i:array)
			tags.add(String.format("%C",i));
		return tags.toArray(new String[0]);
	}
	/**
	 * Devuelve un vector de caracteres unicode perteneciente a una categoría de emoji
	 *
	 * @param tipo Categoría de emoji deseada
	 * @return Vector de caracteres unicode de los emoji del tipo indicado
	 */
	public static String[] getTags(Tipo tipo) {
		return categories.get(tipo.toString());
	}
	/**
	 * Devuelve la ID del Resource perteneciente a un emoticono, dado su caracter unicode
	 *
	 * @param tag Caracter unicode del emoji deseado
	 * @return
	 */
	public static int getResource(String tag) {
		return emoticons.get(tag);
	}
	/**
	 * Nos devuelve el Spannable con la mezcla de texto/imágenes necesaria para la representación de los emoticonos
	 *
	 * @param context Contexto de ejecución donde se realiza la llamada
	 * @param text Texto a parsear con los caracteres de los emoticonos
	 * @return Devuelve un Spannable con las imágenes intercaladas en el texto
	 */
	public static Spannable getEmojiText(Context context, String text) {
		SpannableStringBuilder builder = new SpannableStringBuilder(text);
		int index;
		for (index = 0; index < builder.length(); index++) {
			for (Entry<String, Integer> entry : emoticons.entrySet()) {
				int length = entry.getKey().length();
				if (index + length > builder.length())
					continue;
				if (builder.subSequence(index, index + length).toString().equals(entry.getKey())) {
					builder.setSpan(new ImageSpan(context, entry.getValue()), index, index + length,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
					index += length - 1;
		        	break;
				}
			}
		}
		return builder;
	}
}

Para utilizar este código en tus proyectos, solamente hay que cambiar las implementaciones que utilicen setText de String a Spannable, que lo admiten perfectamente. Por ejemplo, os puedo comentar que tanto TextView como EditText lo admiten sin ningún problema. Un ejemplo de uso sería el que sigue.

final TextView mensajeTexto = (TextView)findViewById(R.id.mensajeTexto);
mensajeTexto.setText(EmoticonUtils.getEmojiText(ctx, textoPlano));

La variable textoPlano debe de ser una String en UTF-8 que puede contener tanto texto como caracteres emoji, que serán convenientemente cambiados por sus respectivas imágenes guardadas en los recursos del proyecto.

Espero que este código os sirva, que para mí ha sido un coñazo hacerlo. Lo mejoraré seguramente para minimizar los costes, pero a saber si me da por actualizar este post… de todos modos esto es totalmente funcional :) Si encontráis algún problema, dejádmelo en los comentarios.

Read more

Uso de XMPP en Android

Por (circunstancias) estoy trabajando con XMPP para un cliente multiplataforma (móvil) de mensajería, por su potencia, por ser un estándar conocido, y por las diversas implementaciones de gran calidad y extensibilidad que existen a nivel de servidor.

Para elegir una librería en Java, para usar en Android, la cosa está bastante clara: hay que tirar con Smack. Pero presenta una serie de problemas la librería, al menos con las versiones a día de hoy, que hacen que tengamos que buscar por otro lado: errores en la conexión por no poder utilizar el método SASL por defecto (al no estar presentes en la VM de Android algunos métodos utilizados), incapacidad de usar compresión, entre otras.

Entonces se llega a asmack, o sea, Smack para Android, que es un fork donde se han aplicado una serie de parches en la autenticación, DNS, y más.

Y a priori, todo funciona bien.

System.setProperty("java.net.preferIPv6Addresses", "false");
ConnectionConfiguration cc = new ConnectionConfiguration("domain",5222);
cc.setSecurityMode(SecurityMode.disabled);
cc.setCompressionEnabled(false);
cc.setReconnectionAllowed(true);

conn = new XMPPConnection(cc);
Connection.DEBUG_ENABLED = true;

try {
conn.connect();
if (conn.isConnected())
Log.d(TAG,"Conectado");
else {
Log.d(TAG,"No conectado");
return;
}

conn.login(user+"@domain", pass, "resource");

if (conn.isAuthenticated()) {
Log.d(TAG,"Autenticado");
res = true;
}
else
Log.d(TAG,"No autenticado");
} catch (XMPPException ex) { ex.printStackTrace(); }

Pero tiene pegas. Hay algunas funcionalidades que no van del todo bien, y para solventarlas en su mayoría hay que tirar de versiones de asmack que han parcheado. Yo tuve la suerte de encontrar un fork de asmack hecho por Flowdalic que soluciona la mayoría de problemas, como por ejemplo la búsqueda de usuarios en el servidor.

Pero hay un tema muy insidioso que nadie ha solucionado en sus JAR. Resulta que existe, dentro de la carpeta META-INF de los mismos, un archivo que se llama smack.providers que debería cargarse, puesto que cuenta con los IQ providers de la mayoría de añadidos útiles de XMPP, pero por cuestiones de cómo se generan los JAR de Android, no está presente. Por lo tanto -y que sepáis que es lo que más me dio por culo a la hora de encontrar qué fallaba- hay que registrarlos manualmente.

Antes de definir el ConnectionConfiguration, debemos añadir esta línea de código:

// poner entre el System.setProperty y el ConnectionConfiguration
configure(ProviderManager.getInstance());
// ha de ir siempre antes del establecimiento de la conexión

Y después crear una función que se llame configure, quedando como la que sigue:


// reemplazo para smack.providers ya que éste no funciona en asmack
private void configure(ProviderManager pm) {
//  Private Data Storage
pm.addIQProvider("query","jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());

//  Time
try {
pm.addIQProvider("query","jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
} catch (ClassNotFoundException e) {
Log.w(TAG, "Can't load class for org.jivesoftware.smackx.packet.Time");
}

//  XHTML
pm.addExtensionProvider("html","http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());

//  Roster Exchange
pm.addExtensionProvider("x","jabber:x:roster", new RosterExchangeProvider());
//  Message Events
pm.addExtensionProvider("x","jabber:x:event", new MessageEventProvider());
//  Chat State
pm.addExtensionProvider("active","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("composing","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("paused","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("inactive","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("gone","http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());

//   FileTransfer
pm.addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
pm.addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
pm.addIQProvider("open","http://jabber.org/protocol/ibb", new OpenIQProvider());
pm.addIQProvider("close","http://jabber.org/protocol/ibb", new CloseIQProvider());
pm.addExtensionProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());

//  Group Chat Invitations
pm.addExtensionProvider("x","jabber:x:conference", new GroupChatInvitation.Provider());
//  Service Discovery # Items
pm.addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
//  Service Discovery # Info
pm.addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
//  Data Forms
pm.addExtensionProvider("x","jabber:x:data", new DataFormProvider());
//  MUC User
pm.addExtensionProvider("x","http://jabber.org/protocol/muc#user", new MUCUserProvider());
//  MUC Admin
pm.addIQProvider("query","http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
//  MUC Owner
pm.addIQProvider("query","http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
//  Delayed Delivery
pm.addExtensionProvider("x","jabber:x:delay", new DelayInformationProvider());
//  Version
try {
pm.addIQProvider("query","jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
} catch (ClassNotFoundException e) {
Log.w(TAG, "Can't load class for org.jivesoftware.smackx.packet.Version");
}
//  VCard
pm.addIQProvider("vCard","vcard-temp", new VCardProvider());
//  Offline Message Requests
pm.addIQProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
//  Offline Message Indicator
pm.addExtensionProvider("offline","http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
//  Last Activity
pm.addIQProvider("query","jabber:iq:last", new LastActivity.Provider());
//  User Search
pm.addIQProvider("query","jabber:iq:search", new UserSearch.Provider());
//  SharedGroupsInfo
pm.addIQProvider("sharedgroup","http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());
//  JEP-33: Extended Stanza Addressing
pm.addExtensionProvider("addresses","http://jabber.org/protocol/address", new MultipleAddressesProvider());
}

Y con esto ya nos funcionarían todas las características, doy fe de ello: ya me funcionan IncomingFileTransfer y OutgoingFileTransfer, los chats multiusuario, e incluso los mensajes de OfflineMessageManager.

No sé si soy manco o qué, pero darme cuenta de todo esto y hallar las soluciones me ha costado bastantes semanas de dolor y agonía, y aquí lo comparto con vosotros, si es que a alguno alguna vez le toca trastear con XMPP en Android.

Sólo se que estoy temblando pensando en el momento que tenga que portar esta aplicación a iOS xDD

Read more