package com.netease.nim.uikit.session.emoji;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import android.util.Xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.netease.nim.uikit.NimUIKit;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
public class EmojiManager {
private static final String EMOT_DIR = "emoji/";
// max cache size
private static final int CACHE_MAX_SIZE = 1024;
private static Pattern pattern;
// default entries
private static final List<Entry> defaultEntries = new ArrayList<Entry>();
// text to entry
private static final Map<String, Entry> text2entry = new HashMap<String, Entry>();
// asset bitmap cache, key: asset path
private static LruCache<String, Bitmap> drawableCache;
static {
Context context = NimUIKit.getContext();
load(context, EMOT_DIR + "emoji.xml");
pattern = makePattern();
drawableCache = new LruCache<String, Bitmap>(CACHE_MAX_SIZE) {
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
if (oldValue != newValue)
oldValue.recycle();
}
};
}
private static class Entry {
String text;
String assetPath;
Entry(String text, String assetPath) {
this.text = text;
this.assetPath = assetPath;
}
}
//
// display
//
public static final int getDisplayCount() {
return defaultEntries.size();
}
public static final Drawable getDisplayDrawable(Context context, int index) {
String text = (index >= 0 && index < defaultEntries.size() ?
defaultEntries.get(index).text : null);
return text == null ? null : getDrawable(context, text);
}
public static final String getDisplayText(int index) {
return index >= 0 && index < defaultEntries.size() ? defaultEntries
.get(index).text : null;
}
public static final Pattern getPattern() {
return pattern;
}
public static final Drawable getDrawable(Context context, String text) {
Entry entry = text2entry.get(text);
if (entry == null) {
return null;
}
Bitmap cache = drawableCache.get(entry.assetPath);
if (cache == null) {
cache = loadAssetBitmap(context, entry.assetPath);
}
return new BitmapDrawable(context.getResources(), cache);
}
//
// internal
//
private static Pattern makePattern() {
return Pattern.compile(patternOfDefault());
}
private static String patternOfDefault() {
return "\\[[^\\[]{1,10}\\]";
}
private static Bitmap loadAssetBitmap(Context context, String assetPath) {
InputStream is = null;
try {
Resources resources = context.getResources();
Options options = new Options();
options.inDensity = DisplayMetrics.DENSITY_HIGH;
options.inScreenDensity = resources.getDisplayMetrics().densityDpi;
options.inTargetDensity = resources.getDisplayMetrics().densityDpi;
is = context.getAssets().open(assetPath);
Bitmap bitmap = BitmapFactory.decodeStream(is, new Rect(), options);
if (bitmap != null) {
drawableCache.put(assetPath, bitmap);
}
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
private static final void load(Context context, String xmlPath) {
new EntryLoader().load(context, xmlPath);
}
//
// load emoticons from asset
//
private static class EntryLoader extends DefaultHandler {
private String catalog = "";
void load(Context context, String assetPath) {
InputStream is = null;
try {
is = context.getAssets().open(assetPath);
Xml.parse(is, Xml.Encoding.UTF_8, this);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (localName.equals("Catalog")) {
catalog = attributes.getValue(uri, "Title");
} else if (localName.equals("Emoticon")) {
String tag = attributes.getValue(uri, "Tag");
String fileName = attributes.getValue(uri, "File");
Entry entry = new Entry(tag, EMOT_DIR + catalog + "/" + fileName);
text2entry.put(entry.text, entry);
if (catalog.equals("default")) {
defaultEntries.add(entry);
}
}
}
}
}