当前位置: 代码迷 >> Android >> Android 获取不久前应用的缩略图
  详细解决方案

Android 获取不久前应用的缩略图

热度:9   发布时间:2016-04-28 07:46:26.0
Android 获取最近应用的缩略图

最近有项需求是获取应用的缩略,用于在动画时显示。因此就对此块知识简要了解了一下。


在android中获取视频文件的缩略图有三种方法:

1.从媒体库中查询
新视频增加后需要SDCard重新扫描才能给新增加的文件添加缩略图,灵活性差,而且不是很稳定,适合简单应用
2. android 2.2以后使用ThumbnailUtils类获取
实现简单,但2.2以前的版本不支持
3.调用jni文件,实现MediaMetadataRetriever类

实现复杂,但比较灵活,推荐使用


那么Android 中如何获取最近应用的缩略图,这块也有现成的函数,不过都被 @hide 掉了,所以需要利用java reflect 反射才能使用


核心代码如下:

package com.example.testondraw;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import android.app.ActivityManager;import android.graphics.Bitmap;import android.util.Log;
/** * 调用隐藏方法的助手类 */
public class HideExploder {	static final String TAG = "HideExploder";	private final static Object refLock = new Object();	private static Method getTaskThumbnails = null;	private static Field taskThumbnailsBitmap = null;	@SuppressWarnings("rawtypes")	public static void listAllObject(String classFullName) {		try {			Log.i(TAG, "listAllObject classFullName: " + classFullName);			Class<?> clazz = Class.forName(classFullName);			// 反射属性字段			Field[] fields = clazz.getDeclaredFields();			// 反射方法字段			Method[] methods = clazz.getDeclaredMethods();			// 反射构造器			Constructor[] constuctors = clazz.getDeclaredConstructors();			Log.i(TAG, "FIELD========");			for (Field f : fields) {				Log.i(TAG, "TYPE: " + f.getType() + " NAME: " + f.getName());			}			Log.i(TAG, "METHOD========");			for (Method m : methods) {				Log.i(TAG, "METHOD NAME: " + m.getName());			}			Log.i(TAG, "CONSTUCTOR========");			for (Constructor c : constuctors) {				Log.i(TAG, "NAME:" + c.getName());				Class[] clss = c.getParameterTypes();				Object o = null;				// 产生实例				try {					if (clss.length == 0)						o = c.newInstance();					else if (clss.length > 0) {						// TODO					}					Log.i(TAG, "object: " + o);				} catch (Exception e) {					e.printStackTrace();				}			}		} catch (Exception e) {			e.printStackTrace();		}	}
	/**	 * 调用逻辑		 * TaskThumbnails o = am.getTaskThumbnails(id)	 * Bitmap b = o.mainThumbnail;		 * @param am ActivityManager 类实例	 * @param id 标识值	 * @return	 */
	public static Bitmap getTaskThumbnailsBitmap(ActivityManager am, int id) {		synchronized (refLock) {			try {				if (getTaskThumbnails == null) {					getTaskThumbnails = am.getClass().getDeclaredMethod(							"getTaskThumbnails", int.class);				}				if (getTaskThumbnails != null) {					Object thumbnails = getTaskThumbnails.invoke(am,							Integer.valueOf(id));					if (thumbnails != null) {						if (taskThumbnailsBitmap == null)							taskThumbnailsBitmap = thumbnails.getClass()									.getField("mainThumbnail");						if (taskThumbnailsBitmap != null) {							return (Bitmap) taskThumbnailsBitmap									.get(thumbnails);						}					}				}			} catch (Exception e) {				Log.w(TAG, "getTaskThumbnailsBitmap error:" + e);				e.printStackTrace();			}		}		return null;	}}

测试用例如下:


// 应用缩略图测试	static final int MAX_RECENT_TASKS = 64;	Bitmap loadThumbnail(int index) {		ActivityManager am = (ActivityManager) this				.getSystemService(Context.ACTIVITY_SERVICE);		List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(				MAX_RECENT_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);		int numTasks = recentTasks.size();		if (index < numTasks) {			final ActivityManager.RecentTaskInfo info = recentTasks.get(index);			if (info != null) {				Bitmap b = HideExploderX.getTaskThumbnailsBitmap(am,						info.persistentId);				return b;			}		}		return null;	}

调用 loadThumbnail(X) 【索引值为0就是上一次的缩略图】拿到Bitmap对象,利用 SurfaceView 方法画出来即可:

 

public void drawBitmap() {		// 锁定画布,得到canvas		if (mSurfaceHolder == null || this.mBitmap == null)			return;		Canvas canvas = mSurfaceHolder.lockCanvas();		if (canvas == null) {			return;		}		// 绘图		Paint paint = new Paint();		paint.setAntiAlias(true);		paint.setColor(Color.BLUE);		canvas.drawBitmap(this.mBitmap, 0, 0, paint);		// 绘制后解锁,绘制后必须解锁才能显示		mSurfaceHolder.unlockCanvasAndPost(canvas);	}


注意点:

1、添加应用权限

    <uses-permission android:name="android.permission.GET_TASKS"/>
    <uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>

   否则会报:

W/System.err( 3314): Caused by: java.lang.SecurityException: Permission Denial: getTaskThumbnails() from pid=3314, uid=10040 requires android.permission.READ_FRAME_BUFFER


2、有 eclipse 上调试运行时,即使加上权限了也还是会报上述错误,有两个方法解决,要么进行系统签名,要不放到linux上编译,利用platform 签名,Android.mk 如下:

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optional# Only compile source java files in this apk.LOCAL_SRC_FILES := $(call all-java-files-under, src)$(warning build apk)LOCAL_PACKAGE_NAME := testLOCAL_CERTIFICATE := platforminclude $(BUILD_PACKAGE)include $(call all-makefiles-under,$(LOCAL_PATH))


下一篇文章将针对其系统代码及原理分析清楚,用于新需求开发使用。


  相关解决方案