• 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 := test
    
    LOCAL_CERTIFICATE := platform
    
    include $(BUILD_PACKAGE)
    
    include $(call all-makefiles-under,$(LOCAL_PATH))


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


  • 相关阅读:
    前端--页面提交重置功能
    ztree获取当前选中节点子节点id集合的方法(转载)
    sqlserver锁表、解锁、查看销表 (转载)
    解决前端文件修改后浏览器页面未更新的问题
    简单的上传文件
    如何在Eclipse中查看JDK以及JAVA框架的源码(转载)
    设计模式--观察者模式
    WebService 学习
    学习quartz定时
    JS 中AJAX,Fetch,Axios关系
  • 原文地址:https://www.cnblogs.com/james1207/p/3366180.html
Copyright © 2020-2023  润新知