您的位置:首页 > 移动开发 > Android开发

Android 获取最近应用的缩略图

2013-10-12 23:16 316 查看
最近有项需求是获取应用的缩略,用于在动画时显示。因此就对此块知识简要了解了一下。

在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 := test

LOCAL_CERTIFICATE := platform

include $(BUILD_PACKAGE)

include $(call all-makefiles-under,$(LOCAL_PATH))


下一篇文章将针对其系统代码及原理分析清楚,用于新需求开发使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: