获取其他app的cache大小和删除其他app的cache

本文介绍了一种通过反射调用 PackageManager 的隐藏方法来获取指定 APP 的缓存大小及删除缓存的方法。由于直接文件操作受限于权限问题,文中详细阐述了如何利用 IPackageStatsObserver 和 IPackageDataObserver 的实现来完成需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    public static void getAppSize(Context context, String pkgName, IPackageStatsObserver.Stub observer) {
        try {
            if (observer != null) {
                PackageManager pm = context.getPackageManager();
                Method getPackageSizeInfo = pm.getClass()
                        .getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);
                getPackageSizeInfo.invoke(pm, pkgName, observer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class StatsObserver extends IPackageStatsObserver.Stub {
        @Override
        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
            long cacheSize = stats.cacheSize;
            if (Environment.isExternalStorageEmulated()) {
                cacheSize += stats.externalCacheSize;
            }
            Log.d("onGetStatsCompleted",String.valueOf(cacheSize));
        }
    }

    public static void delAppCache(Context context, String pkgName, IPackageDataObserver.Stub observer){
        try{
            if (observer != null) {
                PackageManager pm = context.getPackageManager();
                Method deleteApplicationCacheFiles = pm.getClass()
                        .getMethod("deleteApplicationCacheFiles", String.class, IPackageDataObserver.class);
                deleteApplicationCacheFiles.invoke(pm, pkgName, observer);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class ClearCacheObserver extends IPackageDataObserver.Stub {
        @Override
        public void onRemoveCompleted(String packageName,boolean succeeded) {
            Log.d("onRemoveCompleted",String.format("packageName = %s,succeeded = %b",packageName,succeeded));
        }
    }

      在项目开发过程中遇到了这么一个需求:获取其他app的cache大小和删除其他app的cache。

      app的cache是由data/data/app包名/cache和/sdcard/Android/data/app包名/cache两部分组成。

      大家一定会想到利用如下代码片段实现,但不幸的是,我们没有读写权限。

public static long getAppCacheSize(String packageName){
        File cache = new File(String.format("/data/data/%s/cache",packageName));
        File exCache = new File(String.format("/Android/data/%s/cache",packageName));
        return cache.length()+exCache.length();
}

    public static void deleteAppCache(String packageName){
        File cache = new File(String.format("/data/data/%s/cache",packageName));
        cache.delete();
        File exCache = new File(String.format("/Android/data/%s/cache",packageName));
        exCache.delete();
    }

既然此路不通,我们绕道试试。作为android开发人员我们对android系统的Setting非常熟悉吧,对,

我想说的就是,Setting中可以获取其他app的cache和删除其他app的cache的功能,于是乎,我就去

Setting的源码中找,功夫不负有心人终于找到了,但是,尼玛,它用到的一些方法居然是@hide,

也就是说我们不能直接用,没事我们不是还有发射么,哈哈,具体实现如下,我仿照着写了下。

IPackageStatsObserver.aidl

/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

package android.content.pm;

import android.content.pm.PackageStats;
/**
 * API for package data change related callbacks from the Package Manager.
 * Some usage scenarios include deletion of cache directory, generate
 * statistics related to code, data, cache usage(TODO)
 * {@hide}
 */
oneway interface IPackageStatsObserver {
    
    void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
}
IPackageDataObserver.aidl

/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/


package android.content.pm;


/**
 * API for package data change related callbacks from the Package Manager.
 * Some usage scenarios include deletion of cache directory, generate
 * statistics related to code, data, cache usage(TODO)
 * {@hide}
 */
oneway interface IPackageDataObserver {
    void onRemoveCompleted(in String packageName, boolean succeeded);
}

将IPackageStatsObserver.aidl和IPackageDataObserver.aidl置于aidl文件夹下(AndroidStudio),如下图

具体实现代码:

    public static void getAppSize(Context context, String pkgName, IPackageStatsObserver.Stub observer) {
        try {
            if (observer != null) {
                PackageManager pm = context.getPackageManager();
                Method getPackageSizeInfo = pm.getClass()
                        .getMethod("getPackageSizeInfo", String.class, IPackageStatsObserver.class);
                getPackageSizeInfo.invoke(pm, pkgName, observer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static class StatsObserver extends IPackageStatsObserver.Stub {
        @Override
        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
            long cacheSize = stats.cacheSize;
            if (Environment.isExternalStorageEmulated()) {
                cacheSize += stats.externalCacheSize;
            }
            Log.d("onGetStatsCompleted",String.valueOf(cacheSize));
        }
    }

    public static void delAppCache(Context context, String pkgName, IPackageDataObserver.Stub observer){
        try{
            if (observer != null) {
                PackageManager pm = context.getPackageManager();
                Method deleteApplicationCacheFiles = pm.getClass()
                        .getMethod("deleteApplicationCacheFiles", String.class, IPackageDataObserver.class);
                deleteApplicationCacheFiles.invoke(pm, pkgName, observer);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class ClearCacheObserver extends IPackageDataObserver.Stub {
        @Override
        public void onRemoveCompleted(String packageName,boolean succeeded) {
            Log.d("onRemoveCompleted",String.format("packageName = %s,succeeded = %b",packageName,succeeded));
        }
    }
再加上
<uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/>
<uses-permission android:name="android.permission.DELETE_CACHE_FILES"/>
这两个权限。

      本来以为这么着就可以了,没想到run下发现只能获取cache的大小,但不能清除cache,原因就是android.permission.DELETE_CACHE_FILES这个权限只能

赋予系统应用。好吧,如果知道普通第三方应用清除其他app的cache的方法还望告知,谢谢。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值