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的方法还望告知,谢谢。