最近有项需求是获取应用的缩略,用于在动画时显示。因此就对此块知识简要了解了一下。
在android中获取视频文件的缩略图有三种方法:
1.从媒体库中查询新视频增加后需要SDCard重新扫描才能给新增加的文件添加缩略图,灵活性差,而且不是很稳定,适合简单应用
2. android 2.2以后使用ThumbnailUtils类获取
实现简单,但2.2以前的版本不支持
3.调用jni文件,实现MediaMetadataRetriever类
实现复杂,但比较灵活,推荐使用
那么Android 中如何获取最近应用的缩略图,这块也有现成的函数,不过都被 @hide 掉了,所以需要利用java reflect 反射才能使用
核心代码如下:
- <span style="font-size:14px">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;
- </span>
- <span style="font-size:14px">/**
- * 调用隐藏方法的助手类
- */</span>
- <span style="font-size:14px">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();
- }
- }
- </span>
- <span style="font-size:14px"><span style="white-space:pre"> </span>/**
- <span style="white-space:pre"> </span> * 调用逻辑
- <span style="white-space:pre"> </span> *
- <span style="white-space:pre"> </span> * TaskThumbnails o = am.getTaskThumbnails(id)
- <span style="white-space:pre"> </span> * Bitmap b = o.mainThumbnail;
- <span style="white-space:pre"> </span> *
- <span style="white-space:pre"> </span> * @param am ActivityManager 类实例
- <span style="white-space:pre"> </span> * @param id 标识值
- <span style="white-space:pre"> </span> * @return
- <span style="white-space:pre"> </span> */</span>
- <span style="font-size:14px">
- 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;
- }
- }
- </span>
测试用例如下:
- <span style="font-size:14px">// 应用缩略图测试
- 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;
- }</span>
调用 loadThumbnail(X) 【索引值为0就是上一次的缩略图】拿到Bitmap对象,利用 SurfaceView 方法画出来即可:
- <span style="font-size:14px">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);
- }</span>
注意点:
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 := test
- LOCAL_CERTIFICATE := platform
- include $(BUILD_PACKAGE)
- include $(call all-makefiles-under,$(LOCAL_PATH))
-
顶
- 5
-
踩
- 0