Posts Categorized: Coding

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í.
[download id=”43″ format=”1″]

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

AnimeUnderground 1.4 para Android

Para celebrar las 2000 descargas, he subido una actualización importante para la aplicación de Android de AU.

El changelog, como podemos ver en el Android Market, es el que sigue:

Novedades de esta versión:

  1. Rediseño del icono del launcher.
  2. Rediseño del widget.
  3. Añadida nueva ventana de login.
  4. Añadida nueva ventana de registro.
  5. Añadidas opciones en configuración.
  6. Mejoras en el login del foro.
  7. Corrección de FCs reportados por los usuarios.
  8. Se han arreglado las noticias de Abyss, ya funcionan todas bien y se muestran correctamente con su foto correspondiente.
  9. Se han arreglado los errores que salían al hacer check-in de una serie.

De paso, aprovecho para comentar que están en desarrollo versiones de AU para Windows Phone 7 y para dispositivos iOS 4.3.1 (en principio), sin tiempo estimado de salida, puesto que se hacen en los ratos libres cuando no pasamos el día trabajando.

Es que en AUDev molamos más que un bocata de chopped, y que el esmegma de un rancor.

Read more

AnimeUnderground para Android

Tras más de un mes sin poner nada por aquí, algo pasaba que me tenía tan ocupado. Pues eran varias cosas, entre ellas esta aplicación. La aplicación para Android de AnimeUnderground.

Con ella podréis ver las últimas noticias, toda la información sobre nuestras series y sobre los miembros de AU. También proporciona acceso rápido al foro, y te notifica cuando haya una nueva noticia. Además, incorpora un widget de 4×1 para estar al tanto de la última noticia y dar un acceso rápido a la misma y a la aplicación completa.

Os dejo unas cuantas capturas de la misma (hacedles click para verlas mejor).

Podéis descargarla, valorarla, y demás en este enlace.

Read more