一键清理流程图

一键清理流程图.png

系统缓存分析

Android 已安装 app /data/data/packagename/cache 文件夹和 /sdcard/Android/data/packagename/cache 文件夹组成

原生设置(Settings) - 已安装应用 - 详情页

Paste_Image.png

Settings APP 使用了 PackageManager.getPackageSizeInfo 方法来做此事,难道 so easy?屁颠屁颠去查了一下 Android API,发现 PacakgeManager 的文档中压根就没有出现 getPackageSizeInfo 的身影,好吧这是一个不对外公开的 API.

Settings 计算缓存大小方法:

 @Override    public void handleMessage(Message msg) {        ......        switch (msg.what) {            ......            case MSG_LOAD_SIZES: {                synchronized (mEntriesMap) {                    ......                                mPm.getPackageSizeInfo(mCurComputingSizePkg, mStatsObserver);                    ......                }            } break;        }    }    ......

使用 getPackageSizeInfo 需要解决的问题:


Paste_Image.png
  1. getPackageSizeInfo 方法是一个 @hide 方法,需要通过反射来调用;
  2. 使用getPackageSizeInfo 需要在AndroidManiFest.xml 文件中申明权限GET_PACKAGE_SIZE
  3. 传给 getPackageSizeInfo 方法的第二个参数类型 IPackageStatsObserver 是在 android.content.pm 包下,需要自已通过 aidl 方式定义

计算缓存大小的实现:

实现流程:

  1. 工程的 src/main 目录下创建包目录结构 aidl/android/content/pm
  2. Android 源码 frameworks/base/core/java/android/content/pm 目录下的 IPackageStatsObserver.aidl 与其依赖的 PackageStats.aidl 拷贝到上面一步创建的目录里;
  3. AndroidManifest.xml 里声明需要 GET_PACKAGE_SIZE 权限
  4. 获取缓存大小实现
PackageManager pm = mContext.getPackageManager();List installedPackages = pm.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES);mScanTotalCount = installedPackages.size();for (int i = 0; i < mScanTotalCount; i++) {            ApplicationInfo appInfo = installedPackages.get(i);            getAppCacheSize(appInfo.packageName,observer );                  }public void getAppCacheSize(String packageName, IPackageStatsObserver.Stub observer) {    try {        PackageManager pm = ContextUtil.applicationContext.getPackageManager();        Method getPackageSizeInfo = pm.getClass()                .getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);        getPackageSizeInfo.invoke(pm, packageName, observer);    } catch (NoSuchMethodException e ) {        e.printStackTrace();    } catch (IllegalAccessException e) {        e.printStackTrace();    } catch (InvocationTargetException e) {        e.printStackTrace();    }}private class PackageSizeObserver extends IPackageStatsObserver.Stub {    @Override    public void onGetStatsCompleted(PackageStats packageStats, boolean succeeded)            throws RemoteException {        if (packageStats == null || !succeeded) {        } else {            AppEntry entry = new AppEntry();            entry.packageName = packageStats.packagename;            entry.cacheSize = packageStats.cacheSize + packageStats.externalCacheSize;            // do something else,比如把 entry 通过消息发送给需要的地方,或者添加到你的列表里        }    }}

系统缓存清理

借鉴系统Settings清理缓存方案

public void onClick(View v) {        ......        } else if (v == mClearCacheButton) {            // Lazy initialization of observer            if (mClearCacheObserver == null) {                mClearCacheObserver = new ClearCacheObserver();            }            mPm.deleteApplicationCacheFiles(packageName, mClearCacheObserver);        }        ......    }

系统缓存清理实现

  1. AndroidManiFest.xml 中添加权限:
  1. 将 Android 源码 frameworks/base/core/java/android/content/pm 目录下的 IPackageDataObserver.aidl copy到工程pm目录下面;
  2. 删除缓存实现
private void deleteCacheFile(String packageName) {        Log.d(TAG, "deleteCacheFile: ");        try {            Method deleteApplicationCacheFiles = PackageManager.class.getDeclaredMethod("deleteApplicationCacheFiles", String.class, IPackageDataObserver.class);            deleteApplicationCacheFiles.invoke(pm, packageName, new PackageDataObserver());        }        catch (NoSuchMethodException e) {            e.printStackTrace();        }        catch (InvocationTargetException e) {            e.printStackTrace();        }        catch (IllegalAccessException e) {            e.printStackTrace();        }    }public class PackageDataObserver extends IPackageDataObserver.Stub {    @Override    public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {        Log.d(TAG, "onRemoveCompleted: "+packageName);    }    @Override    public IBinder asBinder() {        return null;    }}

4.app 使用DELETE_CACHE_FILES权限 需要系统签名;

扫描其他文件

        //获取SDCard 文件目录        File externalDir = Environment.getExternalStorageDirectory();        if (externalDir != null) {            traverPath(externalDir, 0);        } private void traverPath(File root, int level) {        if (root == null || !root.exists() || level > SCAN_LEVEL) {            return;        }        File[] listFiles = root.listFiles();        for (File file : listFiles) {            mInfProgress.setPath(file.getAbsolutePath());            if (file.isFile()) {                String fileName = file.getName();                if (fileName.endsWith(".apk") || fileName.endsWith(".log") || fileName.endsWith(".tmp") || fileName.endsWith(".temp")) {                    mDataSize += file.length();                    CleanDataInfo cleanInfo = new CleanDataInfo();//                    List filePath = new ArrayList<>();                    cleanInfo.setPath(file.getAbsolutePath());                    cleanInfo.setSize(mDataSize);                    listsInfo.add(cleanInfo);                    Log.d(MyApplication.TAG, "traverPath: " + cleanInfo.getPath());                }                if (mInfProgress != null) {                    mScanListener.onProgress(mInfProgress);                }            }            else {                if (level < SCAN_LEVEL) {                    traverPath(file, level + 1);                }            }        }    }

更多相关文章

  1. Nginx系列教程(六)| 手把手教你搭建 LNMP 架构并部署天空网络电影
  2. android AIDL简单步骤
  3. Android(安卓)百分比布局详解及实例代码
  4. Android(安卓)利用soap协议与服务端进行通信
  5. Android在标准linux基础上对休眠唤醒的实现(一)(二)(三)【转】
  6. 采用Scroller实现任意布局的上下左右弹性效果
  7. android 常用系统信息获取总结
  8. S3C6410 移植Android(安卓)内核
  9. 【Android(安卓)开发教程】Spinner

随机推荐

  1. Android调试工具之adbs
  2. Android调用相机并将照片存储到sd卡上
  3. Android(安卓)Studio 使用技巧:修改默认bu
  4. android,java,ndk,c++ iphone 之争
  5. 我看IPhone
  6. Android自动隐藏键盘
  7. Android设置透明、半透明效果
  8. 浅析android 四大布局
  9. Charles Android 抓包失败SSLHandshake:
  10. Android(安卓)反编译apk文件得到项目文件