Android 在棉花糖以上的OS版本上清除缓存

Android 在棉花糖以上的OS版本上清除缓存,android,application-cache,Android,Application Cache,我想制作一个Android应用程序,它将清除其他应用程序的缓存。我已经想出了如何在棉花糖下面的Android版本中做到这一点 是我在Android Honeycom及以上版本中使用的: if (isExternalStorageWritable()) { final File externalDataDirectory = new File(Environment .getExternalStorageDirectory().getAbso

我想制作一个Android应用程序,它将清除其他应用程序的缓存。我已经想出了如何在棉花糖下面的Android版本中做到这一点

是我在Android Honeycom及以上版本中使用的:

    if (isExternalStorageWritable()) {
        final File externalDataDirectory = new File(Environment
                .getExternalStorageDirectory().getAbsolutePath(), "/Android/data");

        final String externalCachePath = externalDataDirectory.getAbsolutePath() +
                "/%s/cache";

        if (externalDataDirectory.isDirectory()) {
            final File[] files = externalDataDirectory.listFiles();

            for (File file : files) {
                if (!deleteDirectory(new File(String.format(externalCachePath,
                        file.getName())), true)) {
                    Log.e(TAG, "External storage suddenly becomes unavailable");

                    return false;
                }
            }
        } else {
            Log.e(TAG, "External data directory is not a directory!");
        }
    } else {
        Log.d(TAG, "External storage is unavailable");
    }
但我有一个问题要弄清楚如何为Android版本的棉花糖和更高版本做到这一点


市场上的其他缓存清理器可以通过获取可访问性权限或任何其他方式来执行此操作?

如果应用程序是系统应用程序,它可以请求android.permission。删除缓存文件,您可以使用反射来访问

//由反射延迟实例化
@可为空的私有方法deleteApplicationCacheMethod;
public ListenableFuture deleteApplicationCache(字符串packageName)引发异常{
setTableFutureDelete=SettableFuture.create();
ClearCacheObserver=新的ClearCacheObserver(packageName,deleteObserver);
//通过反射调用deleteApplicationCacheFiles()
方法deleteApplicationCacheMethod=deleteApplicationCacheMethod(packageManager);
deleteApplicationCacheMethod.invoke(packageManager、packageName、observer);
返回未来删除;
}
/**返回{@link PackageManager#deleteApplicationCacheFiles}的可访问版本*/
私有静态方法deleteApplicationCacheMethod()抛出InvocationTargetException{
if(deleteApplicationCacheMethod==null){
deleteApplicationCacheMethod=packageManager
.getClass()
.getDeclaredMethod(
“deleteApplicationCacheFiles”,String.class,IPackageDataObserver.class);
deleteApplicationCacheMethod.setAccessible(true);
}
返回deleteApplicationCacheMethod;
}
/**在IPackageDataObserver中包装番石榴的未来*/
私有静态类ClearCacheObserver扩展了IPackageDataObserver.Stub{
最终字符串封装名称;
最终设置未来删除;
ClearCacheObserver(字符串packageName、SettableFuture-futureDelete){
this.packageName=packageName;
this.futureDelete=futureDelete;
}
@凌驾
移除已完成的公用void(字符串包,布尔值成功){
如果(!packageName.equals(package))){
返回;
}
如果(成功){
futureDelete.set(空);
}否则{
setException(新异常(“未能删除”+包的缓存”);
}
}
}
从Android 6.0(棉花糖)开始,任何普通应用程序都不允许清除其他应用程序的缓存。只有当您的应用程序是系统应用程序或由系统签署的同一证书签署时,才能清除其他应用程序的缓存。但是有一个关于如何做到的技巧

您可以通过使用辅助功能服务(您正确地指出了该服务)来执行此操作

确认后,您可以显示缓存值,然后向用户请求访问权限,授予权限后,打开设置屏幕-->转到存储-->单击缓存按钮,然后按确定

请记住,这只是一种黑客行为,可能会根据各种OEM和Android版本产生错误

接下来介绍如何实现,这是一个很好的示例,可以用来探索如何使用无障碍服务


此外,请记住,要使用易访问性,您需要事先获得GOOGLE PLAY的批准,否则该应用可能会从PLAY商店中删除。在进行更新之前,请务必获得许可,否则他们可能会暂停或终止您的应用程序。对此要非常小心。

我想看看开源缓存清理器是如何做到这一点的。在进行粗略的搜索时,我发现了一条注释:“如果您使用的是Android 6.0或更高版本,则不需要它。进入设置->存储和USB->内部存储>缓存数据。鉴于此,您寻找的api功能可能已被弃用?@TrevorReid感谢您的评论。我知道你建议的方法是用户可以清理缓存的方法之一,但是去每个应用程序,一些用户可能不喜欢清理,另外一些用户可能没有意识到这一点,并且可能会发现很难做到这一点。因此,我一直在寻找一种方法,让我的应用程序能够为用户提供服务。我相信这是可能的,因为其他应用程序正在这样做。任何一点建议都能帮我找到一个合适的解决办法。如果您有任何建议或解决方案,请提出建议。您的方法有哪些不适用?我在
adb shell
(非root)上看到
rm-rf/sdcard/Android/data/com.google.Android.apps.maps/cache
仍然可以在Pie上运行。@rds谢谢你的回答。但我想你误解了我的问题。我想制作一个类似Clean Master(缓存清理器应用)的Android应用程序。我想清除用户设备中可能没有根目录的缓存。任何建议或帮助。我已经理解了,shell命令表明您所做的应该是有效的。与人们普遍认为的相反,错误消息和日志会有所帮助。无论如何,我可以提出另一种方法。谢谢你的回答。你的回答似乎很有趣。我将测试它并很快更新您。我尝试了您的答案,但由于我的应用程序没有Android M及以上版本的清除缓存权限,因此解决方案无法工作。同时,我能收集到的是,其他应用程序使用可访问性来执行此操作。您能帮助我理解如何在后台打开设置页面,然后单击存储按钮,然后单击清除缓存按钮吗?请帮助。如果您想清除其他应用缓存,我认为请求相关权限是合理的。但是
清除缓存权限
仅授予系统应用,普通应用无法以任何方式请求。因此,唯一的解决方案是使用可访问性服务,它将打开背景设置,然后单击存储按钮,然后单击清除缓存按钮。所有这一切都会在用户没有注意到的情况下发生。你能帮我提供无障碍服务吗?谢谢
  // Lazily instantiated by reflection
  @Nullable private Method deleteApplicationCacheMethod;

  public ListenableFuture<Void> deleteApplicationCache(String packageName) throws Exception {
    SettableFuture<Void> futureDelete = SettableFuture.create();
    ClearCacheObserver observer = new ClearCacheObserver(packageName, deleteObserver);
    // Invoke deleteApplicationCacheFiles() by reflection
    Method deleteApplicationCacheMethod = deleteApplicationCacheMethod(packageManager);
    deleteApplicationCacheMethod.invoke(packageManager, packageName, observer);
    return futureDelete;
  }

  /** Returns an accessible version of the {@link PackageManager#deleteApplicationCacheFiles}. */
  private static Method deleteApplicationCacheMethod() throws InvocationTargetException {
    if (deleteApplicationCacheMethod == null) {
      deleteApplicationCacheMethod = packageManager
          .getClass()
          .getDeclaredMethod(
               "deleteApplicationCacheFiles", String.class, IPackageDataObserver.class);
     deleteApplicationCacheMethod.setAccessible(true);
   }
   return deleteApplicationCacheMethod;
 }

  /** Wraps a Guava Future in a IPackageDataObserver. */
  private static class ClearCacheObserver extends IPackageDataObserver.Stub {
    final String packageName;
    final SettableFuture<Void> futureDelete;

    ClearCacheObserver(String packageName, SettableFuture<Void> futureDelete) {
      this.packageName = packageName;
      this.futureDelete = futureDelete;
    }

    @Override
    public void onRemoveCompleted(String package, boolean succeeded) {
      if (!packageName.equals(package))) {
        return;
      }
      if (succeeded) {
        futureDelete.set(null);
      } else {
        futureDelete.setException(new Exception("Failed to delete cache for " + package));
      }
    }
  }