Mr.Alright---安卓 P MTK文件管理器显示apk图标的实现,磁盘缓存

安卓P,mtk的文件管理器中的apk,不显示apk的图标;这个其实是原来的设计,所有的apk都用安卓机器人表示,但是为了让apk看起来更直观,因此需要显示图标。同时,不能因为获取图标导致异常的卡顿。

原来的逻辑是注释掉的那行代码,下面的那句是改过的

alps/vendor/mediatek/proprietary/packages/apps/FileManager/src/com/mediatek/filemanager/FileInfoAdapter.java

 private void setIcon(FileViewHolder viewHolder, FileInfo fileInfo, int viewDirection) {
        // Modify  start ^_^
//        Bitmap icon = IconManager.getInstance().getIcon(mResources, fileInfo, mService, viewDirection);
        Bitmap icon = IconManager.getInstance().getIcon(mContext, mResources, fileInfo, mService, viewDirection);
        // Modify end ^_^

        viewHolder.mIcon.setImageBitmap(icon);
        viewHolder.mIcon.setAlpha(DEFAULT_ICON_ALPHA);
        if (FileInfoManager.PASTE_MODE_CUT == mFileInfoManager.getPasteType()) {
            if (mFileInfoManager.isPasteItem(fileInfo)) {
                viewHolder.mIcon.setAlpha(CUT_ICON_ALPHA);
            }
        }
....
}

 

alps/vendor/mediatek/proprietary/packages/apps/FileManager/src/com/mediatek/filemanager/IconManager.java中添加方法

    // Add  start ^_^
    public Bitmap getIcon(Context context, Resources res, FileInfo fileInfo, FileManagerService service, int viewDirection) {
        if (mCurrentDirection != viewDirection) {
            mDirectionChanged = true;
            mCurrentDirection = viewDirection;
        }

        Bitmap icon = null;
        boolean isExternal = MountPointManager.getInstance().isExternalFile(fileInfo);
        //LogUtils.d(TAG, "getIcon,isExternal =" + isExternal);
        if (fileInfo.isDirectory()) {
            icon = getFolderIcon(fileInfo, isExternal);
        } else {
            String mimeType = fileInfo.getFileMimeType(service);
            // Add by zhiheng.huang on 2019/3/12 for  start ^_^
            if (mimeType.startsWith("application/vnd.android.package-archive")) {
                Bitmap bitmap = DiskCacheUtil.getInstance(context).getBitmap(fileInfo.getFileAbsolutePath());
                if (bitmap != null) {
                    return bitmap;
                }
                return getApkIcon(context, fileInfo.getFileAbsolutePath());
            }
            // Add by zhiheng.huang on 2019/3/12 for  end ^_^
            LogUtils.d(TAG, "getIcon imimeType =" + mimeType);
            int iconId = getDrawableId(service, mimeType);
            if (fileInfo.isDrmFile()) {
                // try to get the DRM file icon.
                icon = DrmManager.getInstance().overlayDrmIconSkew(res,
                        fileInfo.getFileAbsolutePath(), iconId);
                if (icon != null && isExternal) {
                    icon = createExternalIcon(icon);
                }
            }
            if (icon == null) {
                icon = getFileIcon(iconId, isExternal);
            }
        }

        return icon;
    }

    private Bitmap getApkIcon(Context context, String apkPath) {
        PackageManager pm = context.getPackageManager();
        PackageInfo info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES);
        if (info != null) {
            ApplicationInfo appInfo = info.applicationInfo;
            appInfo.sourceDir = apkPath;
            appInfo.publicSourceDir = apkPath;
            try {
                Bitmap bitmap = DiskCacheUtil.drawable2Bitmap(appInfo.loadIcon(pm));
                DiskCacheUtil.getInstance(context).put(apkPath, bitmap);
                return bitmap;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    // Add  end ^_^

获取apk的图标并显示并不难,但是为了保证流畅,我才用的是DiskLruCache来缓存获取的图片,下次进来的时候直接去缓存读取,就不需要再次解析包名获取了,下面是缓存的代码文件

package com.mediatek.filemanager.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Add by HZH on 2019/3/13
 */
public class DiskCacheUtil {
    private static final long DEFAULT_MAX_SIZE = Long.MAX_VALUE;
    private static final int DEFAULT_MAX_COUNT = Integer.MAX_VALUE;
    private static final String CACHE_PREFIX = "cdu";

    private static final Map CACHE_MAP = new HashMap<>();

    private final String mCacheKey;
    private final File mCacheDir;
    private final long mMaxSize;
    private final int mMaxCount;
    private DiskCacheManager mDiskCacheManager;
    private static Context mContext;

    /**
     * Return the single {@link DiskCacheUtil} instance.
     * 

cache directory: /data/data/package/cache/cacheUtils

*

cache size: unlimited

*

cache count: unlimited

* * @return the single {@link DiskCacheUtil} instance */ public static DiskCacheUtil getInstance(Context context) { mContext = context; return getInstance(context, "", DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT); } /** * Return the single {@link DiskCacheUtil} instance. *

cache directory: /data/data/package/cache/cacheName

* * @param cacheName The name of cache. * @param maxSize The max size of cache, in bytes. * @param maxCount The max count of cache. * @return the single {@link DiskCacheUtil} instance */ public static DiskCacheUtil getInstance(Context context, String cacheName, final long maxSize, final int maxCount) { mContext = context; if (isSpace(cacheName)) cacheName = "cacheUtils"; File file = new File(context.getCacheDir(), cacheName); return getInstance(file, maxSize, maxCount); } /** * Return the single {@link DiskCacheUtil} instance. *

cache size: unlimited

*

cache count: unlimited

* * @param cacheDir The directory of cache. * @return the single {@link DiskCacheUtil} instance */ public static DiskCacheUtil getInstance(final File cacheDir) { return getInstance(cacheDir, DEFAULT_MAX_SIZE, DEFAULT_MAX_COUNT); } /** * Return the single {@link DiskCacheUtil} instance. * * @param cacheDir The directory of cache. * @param maxSize The max size of cache, in bytes. * @param maxCount The max count of cache. * @return the single {@link DiskCacheUtil} instance */ public static DiskCacheUtil getInstance(final File cacheDir, final long maxSize, final int maxCount) { final String cacheKey = cacheDir.getAbsoluteFile() + "_" + maxSize + "_" + maxCount; DiskCacheUtil cache = CACHE_MAP.get(cacheKey); if (cache == null) { synchronized (DiskCacheUtil.class) { cache = CACHE_MAP.get(cacheKey); if (cache == null) { cache = new DiskCacheUtil(cacheKey, cacheDir, maxSize, maxCount); CACHE_MAP.put(cacheKey, cache); } } } return cache; } private DiskCacheUtil(final String cacheKey, final File cacheDir, final long maxSize, final int maxCount) { mCacheKey = cacheKey; mCacheDir = cacheDir; mMaxSize = maxSize; mMaxCount = maxCount; } private DiskCacheManager getDiskCacheManager() { if (mCacheDir.exists()) { if (mDiskCacheManager == null) { mDiskCacheManager = new DiskCacheManager(mCacheDir, mMaxSize, mMaxCount); } } else { if (mCacheDir.mkdirs()) { mDiskCacheManager = new DiskCacheManager(mCacheDir, mMaxSize, mMaxCount); } else { Log.e("DiskCacheUtil", "can't make dirs in " + mCacheDir.getAbsolutePath()); } } return mDiskCacheManager; } @Override public String toString() { return mCacheKey + "@" + Integer.toHexString(hashCode()); } /// // about bytes /// /** * Put bytes in cache. * * @param key The key of cache. * @param value The value of cache. */ public void put(final String key, final byte[] value) { put(key, value, -1); } /** * Put bytes in cache. * * @param key The key of cache. * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ public void put(final String key, byte[] value, final int saveTime) { if (value == null) return; DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return; if (saveTime >= 0) value = DiskCacheHelper.newByteArrayWithTime(saveTime, value); File file = diskCacheManager.getFileBeforePut(key); writeFileFromBytes(file, value); diskCacheManager.updateModify(file); diskCacheManager.put(file); } /** * Return the bytes in cache. * * @param key The key of cache. * @return the bytes if cache exists or null otherwise */ public byte[] getBytes(final String key) { return getBytes(key, null); } /** * Return the bytes in cache. * * @param key The key of cache. * @param defaultValue The default value if the cache doesn't exist. * @return the bytes if cache exists or defaultValue otherwise */ public byte[] getBytes(final String key, final byte[] defaultValue) { DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return defaultValue; final File file = diskCacheManager.getFileIfExists(key); if (file == null) return defaultValue; byte[] data = readFile2Bytes(file); if (DiskCacheHelper.isDue(data)) { diskCacheManager.removeByKey(key); return defaultValue; } diskCacheManager.updateModify(file); return DiskCacheHelper.getDataWithoutDueTime(data); } /// // about Bitmap /// /** * Put bitmap in cache. * * @param key The key of cache. * @param value The value of cache. */ public void put(final String key, final Bitmap value) { put(key, value, -1); } /** * Put bitmap in cache. * * @param key The key of cache. * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ public void put(final String key, final Bitmap value, final int saveTime) { put(key, bitmap2Bytes(value), saveTime); } /** * Return the bitmap in cache. * * @param key The key of cache. * @return the bitmap if cache exists or null otherwise */ public Bitmap getBitmap(final String key) { return getBitmap(key, null); } /** * Return the bitmap in cache. * * @param key The key of cache. * @param defaultValue The default value if the cache doesn't exist. * @return the bitmap if cache exists or defaultValue otherwise */ public Bitmap getBitmap(final String key, final Bitmap defaultValue) { byte[] bytes = getBytes(key); if (bytes == null) return defaultValue; return bytes2Bitmap(bytes); } /// // about Drawable /// /** * Put drawable in cache. * * @param key The key of cache. * @param value The value of cache. */ public void put(final String key, final Drawable value) { put(key, value, -1); } /** * Put drawable in cache. * * @param key The key of cache. * @param value The value of cache. * @param saveTime The save time of cache, in seconds. */ public void put(final String key, final Drawable value, final int saveTime) { put(key, drawable2Bytes(value), saveTime); } /** * Return the drawable in cache. * * @param key The key of cache. * @return the drawable if cache exists or null otherwise */ public Drawable getDrawable(final String key) { return getDrawable(key, null); } /** * Return the drawable in cache. * * @param key The key of cache. * @param defaultValue The default value if the cache doesn't exist. * @return the drawable if cache exists or defaultValue otherwise */ public Drawable getDrawable(final String key, final Drawable defaultValue) { byte[] bytes = getBytes(key); if (bytes == null) return defaultValue; return bytes2Drawable(bytes); } /** * Return the size of cache, in bytes. * * @return the size of cache, in bytes */ public long getCacheSize() { DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return 0; return diskCacheManager.getCacheSize(); } /** * Return the count of cache. * * @return the count of cache */ public int getCacheCount() { DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return 0; return diskCacheManager.getCacheCount(); } /** * Remove the cache by key. * * @param key The key of cache. * @return {@code true}: success
{@code false}: fail */ public boolean remove(final String key) { DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return true; return diskCacheManager.removeByKey(key); } /** * Clear all of the cache. * * @return {@code true}: success
{@code false}: fail */ public boolean clear() { DiskCacheManager diskCacheManager = getDiskCacheManager(); if (diskCacheManager == null) return true; return diskCacheManager.clear(); } private static final class DiskCacheManager { private final AtomicLong cacheSize; private final AtomicInteger cacheCount; private final long sizeLimit; private final int countLimit; private final Map lastUsageDates = Collections.synchronizedMap(new HashMap()); private final File cacheDir; private final Thread mThread; private DiskCacheManager(final File cacheDir, final long sizeLimit, final int countLimit) { this.cacheDir = cacheDir; this.sizeLimit = sizeLimit; this.countLimit = countLimit; cacheSize = new AtomicLong(); cacheCount = new AtomicInteger(); mThread = new Thread(new Runnable() { @Override public void run() { int size = 0; int count = 0; final File[] cachedFiles = cacheDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith(CACHE_PREFIX); } }); if (cachedFiles != null) { for (File cachedFile : cachedFiles) { size += cachedFile.length(); count += 1; lastUsageDates.put(cachedFile, cachedFile.lastModified()); } cacheSize.getAndAdd(size); cacheCount.getAndAdd(count); } } }); mThread.start(); } private long getCacheSize() { try { mThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } return cacheSize.get(); } private int getCacheCount() { try { mThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } return cacheCount.get(); } private File getFileBeforePut(final String key) { File file = new File(cacheDir, CACHE_PREFIX + String.valueOf(key.hashCode())); if (file.exists()) { cacheCount.addAndGet(-1); cacheSize.addAndGet(-file.length()); } return file; } private File getFileIfExists(final String key) { File file = new File(cacheDir, CACHE_PREFIX + String.valueOf(key.hashCode())); if (!file.exists()) return null; return file; } private void put(final File file) { cacheCount.addAndGet(1); cacheSize.addAndGet(file.length()); while (cacheCount.get() > countLimit || cacheSize.get() > sizeLimit) { cacheSize.addAndGet(-removeOldest()); cacheCount.addAndGet(-1); } } private void updateModify(final File file) { Long millis = System.currentTimeMillis(); file.setLastModified(millis); lastUsageDates.put(file, millis); } private boolean removeByKey(final String key) { File file = getFileIfExists(key); if (file == null) return true; if (!file.delete()) return false; cacheSize.addAndGet(-file.length()); cacheCount.addAndGet(-1); lastUsageDates.remove(file); return true; } private boolean clear() { File[] files = cacheDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith(CACHE_PREFIX); } }); if (files == null || files.length <= 0) return true; boolean flag = true; for (File file : files) { if (!file.delete()) { flag = false; continue; } cacheSize.addAndGet(-file.length()); cacheCount.addAndGet(-1); lastUsageDates.remove(file); } if (flag) { lastUsageDates.clear(); cacheSize.set(0); cacheCount.set(0); } return flag; } /** * Remove the oldest files. * * @return the size of oldest files, in bytes */ private long removeOldest() { if (lastUsageDates.isEmpty()) return 0; Long oldestUsage = Long.MAX_VALUE; File oldestFile = null; Set> entries = lastUsageDates.entrySet(); synchronized (lastUsageDates) { for (Map.Entry entry : entries) { Long lastValueUsage = entry.getValue(); if (lastValueUsage < oldestUsage) { oldestUsage = lastValueUsage; oldestFile = entry.getKey(); } } } if (oldestFile == null) return 0; long fileSize = oldestFile.length(); if (oldestFile.delete()) { lastUsageDates.remove(oldestFile); return fileSize; } return 0; } } private static final class DiskCacheHelper { static final int TIME_INFO_LEN = 14; private static byte[] newByteArrayWithTime(final int second, final byte[] data) { byte[] time = createDueTime(second).getBytes(); byte[] content = new byte[time.length + data.length]; System.arraycopy(time, 0, content, 0, time.length); System.arraycopy(data, 0, content, time.length, data.length); return content; } /** * Return the string of due time. * * @param seconds The seconds. * @return the string of due time */ private static String createDueTime(final int seconds) { return String.format( Locale.getDefault(), "_$%010d$_", System.currentTimeMillis() / 1000 + seconds ); } private static boolean isDue(final byte[] data) { long millis = getDueTime(data); return millis != -1 && System.currentTimeMillis() > millis; } private static long getDueTime(final byte[] data) { if (hasTimeInfo(data)) { String millis = new String(copyOfRange(data, 2, 12)); try { return Long.parseLong(millis) * 1000; } catch (NumberFormatException e) { return -1; } } return -1; } private static byte[] getDataWithoutDueTime(final byte[] data) { if (hasTimeInfo(data)) { return copyOfRange(data, TIME_INFO_LEN, data.length); } return data; } private static byte[] copyOfRange(final byte[] original, final int from, final int to) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); byte[] copy = new byte[newLength]; System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); return copy; } private static boolean hasTimeInfo(final byte[] data) { return data != null && data.length >= TIME_INFO_LEN && data[0] == '_' && data[1] == '$' && data[12] == '$' && data[13] == '_'; } } /// // other utils methods /// private static byte[] string2Bytes(final String string) { if (string == null) return null; return string.getBytes(); } private static String bytes2String(final byte[] bytes) { if (bytes == null) return null; return new String(bytes); } private static Object bytes2Object(final byte[] bytes) { if (bytes == null) return null; ObjectInputStream ois = null; try { ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); return ois.readObject(); } catch (Exception e) { e.printStackTrace(); return null; } finally { try { if (ois != null) { ois.close(); } } catch (IOException e) { e.printStackTrace(); } } } private static byte[] bitmap2Bytes(final Bitmap bitmap) { if (bitmap == null) return null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } private static Bitmap bytes2Bitmap(final byte[] bytes) { return (bytes == null || bytes.length <= 0) ? null : BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } private static byte[] drawable2Bytes(final Drawable drawable) { return drawable == null ? null : bitmap2Bytes(drawable2Bitmap(drawable)); } private static Drawable bytes2Drawable(final byte[] bytes) { return bytes == null ? null : bitmap2Drawable(bytes2Bitmap(bytes)); } public static Bitmap drawable2Bitmap(final Drawable drawable) { if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } Bitmap bitmap; if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { bitmap = Bitmap.createBitmap( 1, 1, drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565 ); } else { bitmap = Bitmap.createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565 ); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } private static Drawable bitmap2Drawable(final Bitmap bitmap) { return bitmap == null ? null : new BitmapDrawable(mContext.getResources(), bitmap); } private static void writeFileFromBytes(final File file, final byte[] bytes) { FileChannel fc = null; try { fc = new FileOutputStream(file, false).getChannel(); fc.write(ByteBuffer.wrap(bytes)); fc.force(true); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fc != null) { fc.close(); } } catch (IOException e) { e.printStackTrace(); } } } private static byte[] readFile2Bytes(final File file) { FileChannel fc = null; try { fc = new RandomAccessFile(file, "r").getChannel(); int size = (int) fc.size(); MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size).load(); byte[] data = new byte[size]; mbb.get(data, 0, size); return data; } catch (IOException e) { e.printStackTrace(); return null; } finally { try { if (fc != null) { fc.close(); } } catch (IOException e) { e.printStackTrace(); } } } private static boolean isSpace(final String s) { if (s == null) return true; for (int i = 0, len = s.length(); i < len; ++i) { if (!Character.isWhitespace(s.charAt(i))) { return false; } } return true; } }

 

你可能感兴趣的:(系统修改,DiskLruCache,apk图标获取)