package com.mogoo.launcher2.utils;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.util.TypedValue;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import com.mogoo.launcher.R;
import com.mogoo.launcher2.IconCache;
import com.mogoo.launcher2.LauncherApplication;
import com.mogoo.launcher2.config.Mogoo_GlobalConfig;
/**
* application 级生命周期bitmap的缓存工具类
*
* @author 黄悦
*/
public class Mogoo_BitmapCache extends IconCache {
public static final int RECYCLE_RESID_NOMAL = 0;
public static final int RECYCLE_RESID_SCALE = 1;
public static final int RECYCLE_COMPONENT_NAME_ALL = -1;
public static final int RECYCLE_COMPONENT_NAME_NOMAL = 0;
public static final int RECYCLE_COMPONENT_NAME_REFLECTION = 1;
public static final int RECYCLE_COMPONENT_NAME_VIBRATION = 2;
private long memSize;
private Random random = new Random();
private LauncherApplication application;
private final ArrayList<HashMap<Integer, Bitmap>> resIdCache = new ArrayList<HashMap<Integer, Bitmap>>();
private final ArrayList<HashMap<ComponentName, Bitmap>> componentCache = new ArrayList<HashMap<ComponentName, Bitmap>>();
private final HashMap<ComponentName, Bitmap[]> vibrationCache = new HashMap<ComponentName, Bitmap[]>(
INITIAL_ICON_CACHE_CAPACITY);
private final HashMap<String, Bitmap> mollacCache = new HashMap<String, Bitmap>(
INITIAL_ICON_CACHE_CAPACITY);
private final long BITMAP_BUD_MEMERY = 8 * 1024 * 1024;
private final float MEMERY_LOW_POINT = 0.8f;
private Matrix matrix;
public Mogoo_BitmapCache(LauncherApplication context) {
super(context);
application = context;
initCache();
}
// /**
// * 通过图片id获得bitmap
// * @author 黄悦
// * @param resId 图片资源id
// * @return
// */
// public Bitmap getBitmap(Context cxt, int resId) {
// Bitmap bitmap = getBitmapFromCache(resIdCache, resId,
// RECYCLE_RESID_NOMAL);
//
// if(bitmap == null || bitmap.isRecycled()){
// bitmap = BitmapFactory.decodeResource(cxt.getResources(), resId);
// addMemSize(bitmap);
// resIdCache.get(RECYCLE_RESID_NOMAL).put(resId, bitmap);
// }
//
// return bitmap;
// }
/**
* 通过组建名称获得shortcut的对应抖动动画帧数组
*
* @author 黄悦
* @param componentName
* @return
*/
public synchronized Bitmap[] getIconWithAngle(ComponentName componentName, Bitmap drawCache) {
if (vibrationCache.containsKey(componentName)) {
return vibrationCache.get(componentName);
}
float[] angles = Mogoo_GlobalConfig.getFrameAngle();
Bitmap[] temp = new Bitmap[angles.length];
for (int i = 0; i < temp.length; i++) {
temp[i] = createRotaImg(angles[i], drawCache);
if(temp[i] == null){
clearBitmapArray(temp);
return null;
}
}
vibrationCache.put(componentName, temp);
angles = null;
return temp;
}
private void clearBitmapArray(Bitmap[] bitmaps){
}
/**
* 通过组建名称获得shortcut的倒影bitmap
*
* @author 魏景春
* @param intent
* @return
*/
public Bitmap getIconWithReflection(Intent intent) {
Bitmap bitmap = getBitmapFromCache(componentCache, intent.getComponent(),
RECYCLE_COMPONENT_NAME_REFLECTION);
if (bitmap == null || bitmap.isRecycled()) {
// CacheEntry entry = mCache.get(intent.getComponent());
bitmap = Mogoo_BitmapUtils.createReflection(getIcon(intent));
addMemSize(bitmap);
componentCache.get(RECYCLE_COMPONENT_NAME_REFLECTION)
.put(intent.getComponent(), bitmap);
}
return bitmap;
}
/**
* 通过组建名称获得shortcut的倒影bitmap
*
* @author 黄悦
* @param componentName
* @return
*/
public Bitmap getIconWithReflection(ComponentName componentName) {
Bitmap bitmap = getBitmapFromCache(componentCache, componentName,
RECYCLE_COMPONENT_NAME_REFLECTION);
if (bitmap == null || bitmap.isRecycled()) {
CacheEntry entry = mCache.get(componentName);
bitmap = Mogoo_BitmapUtils.createReflection(entry.icon);
addMemSize(bitmap);
componentCache.get(RECYCLE_COMPONENT_NAME_REFLECTION).put(componentName, bitmap);
}
return bitmap;
}
/**
* 获得与key相关的bitmap @ author: 黄悦
*
* @param key
*/
public Bitmap getBitmapByKey(String key, int width, int height, Config config) {
Bitmap temp = mollacCache.get(key);
if (temp == null || temp.isRecycled()) {
temp = Bitmap.createBitmap(width, height, config);
addMemSize(temp);
mollacCache.put(key, temp);
}
return temp;
}
/**
* 获得指定资源的缩放图片
*
* @author 黄悦
* @param resId
* @param width
* @param height
* @return
*/
public Bitmap getScaleBitmap(int resId, int width, int height) {
Bitmap bitmap = getBitmapFromCache(resIdCache, resId, RECYCLE_RESID_SCALE);
if (bitmap == null || bitmap.isRecycled()) {
CacheEntry entry = mCache.get(resId);
bitmap = Mogoo_BitmapUtils.createScale(entry.icon, width, height);
addMemSize(bitmap);
resIdCache.get(RECYCLE_RESID_SCALE).put(resId, bitmap);
}
return bitmap;
}
/**
* 用于在制式图标上展示短信,未接电话等数量
*
* @author 黄悦
* @param count
* @return
*/
public Bitmap getDigitalIcon(int count) {
if (count > 0) {
if (count < 10) {
return Mogoo_BitmapUtils.drawIconCountInfo(mContext.getResources().getDrawable(R.drawable.mogoo_noblackicon_1),
count + "");
} else if (count >= 10 && count < 100) {
return Mogoo_BitmapUtils.drawIconCountInfo(mContext.getResources().getDrawable(R.drawable.mogoo_noblackicon_2),
count + "");
} else if (count < 1000 && count >= 100) {
return Mogoo_BitmapUtils.drawIconCountInfo(mContext.getResources().getDrawable(R.drawable.mogoo_noblackicon_3),
count + "");
} else {
return Mogoo_BitmapUtils.drawIconCountInfo(mContext.getResources().getDrawable(R.drawable.mogoo_noblackicon_3),
"999");
}
}
return null;
}
/**
* 回收由resId获取的对象 类型有: 未改变bitmap RECYCLE_RESID_NOMAL 缩放bitmap
* RECYCLE_RESID_SCALE
*
* @author 黄悦
* @param resId
* @param recycleType
*/
public void recycle(int resId, int recycleType) {
recycleBitmap(resIdCache.get(recycleType), resId);
}
/**
* 回收由ComponentName获取的对象 recycleType类型有: RECYCLE_COMPONENT_NAME_NOMAL:
* 未改变bitmap RECYCLE_COMPONENT_NAME_REFLECTION: 倒影bitmap
* RECYCLE_COMPONENT_NAME_ANGLE: 抖动帧组 RECYCLE_COMPONENT_NAME_ALL:
* 删除所有与名称相关内容
*
* @author 黄悦
* @param resId
* @param recycleType
*/
public void recycle(ComponentName componentName, int recycleType) {
if (RECYCLE_COMPONENT_NAME_VIBRATION == recycleType) {
recycleCBitmap(vibrationCache, componentName);
} else if (RECYCLE_COMPONENT_NAME_ALL == recycleType) {
recycleAll(componentName);
} else {
recycleCBitmap(componentCache.get(recycleType), componentName);
}
}
/**
* 申请 bitmap 空间回收 @ author: 黄悦
*
* @param bitmapKey
*/
public void recycle(String bitmapKey) {
Bitmap temp = mollacCache.remove(bitmapKey);
if (temp != null) {
subMemSize(temp);
temp.recycle();
}
temp = null;
}
/**
* 返回已用byte总数 @ author: 黄悦
*
* @return
*/
public long getMemoryCount() {
return memSize / 4;
}
/**
* 当前图片缓存剩余内存状态是否为low @ author: 黄悦
*
* @return
*/
public boolean isLowMemery() {
return (memSize / 4) / BITMAP_BUD_MEMERY > MEMERY_LOW_POINT;
}
/**
* 将图标的获取改成现有的方式
*/
@Override
protected CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
CacheEntry entry = mCache.get(componentName);
if (entry == null) {
entry = new CacheEntry();
mCache.put(componentName, entry);
entry.title = info.loadLabel(mPackageManager).toString();
if (entry.title == null) {
entry.title = info.activityInfo.name;
}
// entry.icon =
// MT_BitmapUtils.createIconBitmap(info.activityInfo.loadIcon(mPackageManager),
// mContext, application.getModel().isSystemApp(componentName));
entry.icon = CalendarUtils.getCalendarIcon(info, this);
if(entry.icon == null)
{
//modify by weijingchun 2011-12-8
// entry.icon = Mogoo_BitmapUtils.createIconBitmap(loadIcon(mPackageManager, info), mContext,
// application.getModel().isSystemApp(componentName));
String title = Mogoo_BitmapUtils.getApplicationTitle(componentName);
if(title!=null && !title.equals(""))
{
entry.title = Mogoo_BitmapUtils.getApplicationTitle(componentName);
}
entry.icon = Mogoo_BitmapUtils.getApplicationIcon(componentName);
if(entry.icon == null)
{
Log.d("Mogoo_BitmapCache", "componentName==" + componentName + " entry.icon is null");
entry.icon = Mogoo_BitmapUtils.createIconBitmap(loadIcon(mPackageManager, info), mContext,
application.getModel().isSystemApp(componentName));
}else
{
Log.d("Mogoo_BitmapCache", "componentName==" + componentName);
}
//-----------------end---------------
}
addMemSize(entry.icon);
}
return entry;
}
protected Bitmap getFolderIcon(ComponentName componentName) {
CacheEntry entry = mCache.get(componentName);
if (entry == null) {
// MT_BitmapUtils.createFolderBitmap(mContext, this);
return null;
}
return entry.icon;
}
private void initCache() {
// 初始化resIdCache 两种类型的缓存区
resIdCache.add(new HashMap<Integer, Bitmap>());
resIdCache.add(new HashMap<Integer, Bitmap>());
// 初始化componentCache 两种类型的缓存区
componentCache.add(new HashMap<ComponentName, Bitmap>());
componentCache.add(new HashMap<ComponentName, Bitmap>());
}
// 防止缓存类型空指针
private Bitmap getBitmapFromCache(ArrayList<HashMap<Integer, Bitmap>> cache, int resId, int type) {
if (cache.get(type) == null) {
cache.add(type, new HashMap<Integer, Bitmap>());
}
return cache.get(type).get(resId);
}
// 防止缓存类型空指针
private Bitmap getBitmapFromCache(ArrayList<HashMap<ComponentName, Bitmap>> cache,
ComponentName componentName, int type) {
if (cache.get(type) == null) {
cache.add(type, new HashMap<ComponentName, Bitmap>());
}
return cache.get(type).get(componentName);
}
/*
* 回收resId bitmap处理
*/
private void recycleBitmap(HashMap<Integer, ?> cache, int id) {
if (cache == null) {
return;
}
Object obj = cache.remove(id);
if (obj instanceof Bitmap) {
subMemSize((Bitmap) obj);
((Bitmap) obj).recycle();
}
obj = null;
}
private void addMemSize(Bitmap bitmap) {
if (bitmap != null) {
memSize += bitmap.getHeight() * bitmap.getWidth();
}
}
private void subMemSize(Bitmap bitmap) {
if (bitmap != null) {
memSize -= bitmap.getHeight() * bitmap.getWidth();
}
}
/*
* 回收ComponentName bitmap处理
*/
private void recycleCBitmap(HashMap<ComponentName, ?> cache, ComponentName componentName) {
if (cache == null) {
return;
}
Object obj = cache.remove(componentName);
if (obj instanceof Bitmap[]) {
for (int i = 0; i < ((Bitmap[]) obj).length; i++) {
((Bitmap[]) obj)[i].recycle();
}
} else if (obj instanceof Bitmap) {
((Bitmap) obj).recycle();
}
obj = null;
}
private Bitmap createRotaImg(Float angle, Bitmap b) {
int w = b.getWidth();
int h = b.getHeight();
Matrix matrix = new Matrix();
matrix.setRotate(angle, w / 2, h / 2);
Bitmap res = null;
try {
res = Bitmap.createBitmap(b, 0, 0, w, h, matrix, true);
matrix = null;
} catch (Exception e) {
return null;
} catch (OutOfMemoryError e) {
return null;
}
return res;
}
/**
* 通过图片id获得bitmap
*
* @author 黄悦
* @param resId 图片资源id
* @return
*/
public Bitmap getBitmap(int resId) {
Bitmap bitmap = getBitmapFromCache(resIdCache, resId, RECYCLE_RESID_NOMAL);
if (bitmap == null || bitmap.isRecycled()) {
bitmap = Mogoo_BitmapUtils.decodeResource(mContext.getResources(), resId);
addMemSize(bitmap);
resIdCache.get(RECYCLE_RESID_NOMAL).put(resId, bitmap);
}
return bitmap;
}
/**
* 清空名称对应的位图 @ author: 黄悦
*
* @param name
*/
private void recycleAll(ComponentName name) {
recycle(name, RECYCLE_COMPONENT_NAME_VIBRATION);
for (HashMap<ComponentName, Bitmap> m : componentCache) {
recycleCBitmap(m, name);
}
}
public void recycleAllByType(int type){
Set<ComponentName> sets = mCache.keySet();
if(sets != null){
Iterator<ComponentName> itr = sets.iterator();
while(itr.hasNext()){
recycle(itr.next(), type);
}
}
}
public void recycleAll(){
Set<ComponentName> sets = mCache.keySet();
if(sets != null){
Iterator<ComponentName> itr = sets.iterator();
while(itr.hasNext()){
recycleAll(itr.next());
}
}
flush();
}
public Bitmap getIcon(Intent intent){
ComponentName component = intent.getComponent();
String str = component.getClassName();
if(str.startsWith(Mogoo_Utilities.DEFAULT_CLASS_NAME_PREFIX)){
CacheEntry entry = mCache.get(intent.getComponent());
if(entry == null){
return null;
}
return entry.icon;
}else{
return super.getIcon(intent);
}
}
/**
*
* 存放图标文件夹缩略图
* @ author: 黄悦
*@param bitmap
*@param intent
*/
public void putFodlerIcon(Bitmap bitmap, Intent intent){
CacheEntry entry = new CacheEntry();
entry.icon = bitmap;
mCache.put(intent.getComponent(), entry);
}
public Drawable loadIcon(PackageManager pm, ResolveInfo info) {
if (pm == null || info == null) {
return null;
}
ComponentInfo ci = info.activityInfo != null ? info.activityInfo : info.serviceInfo;
ApplicationInfo appInfo = ci.applicationInfo;
Drawable icon = null;
try {
if (info.getIconResource() != 0) {
Resources r = pm.getResourcesForApplication(appInfo);
icon = Mogoo_BitmapUtils.createFromResource(r, info.getIconResource());
} else {
icon= pm.getDefaultActivityIcon();
}
} catch (NameNotFoundException e) {
Log.w("PackageManager", "Failure retrieving resources for" + appInfo.packageName);
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return default icon.
Log.w("PackageManager", "Failure retrieving icon 0x" + Integer.toHexString(info.icon)
+ " in package " + info.activityInfo.packageName, e);
}
if(icon == null){
icon= pm.getDefaultActivityIcon();
}
return icon;
}
}