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

时间:2019-05-19 10:01:44

标签: android application-cache

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

This是我用于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版本棉花糖及更高版本上遇到问题。

市场上存在的其他缓存清理器是否能够通过获得可访问性许可或任何其他方式来执行此操作?

2 个答案:

答案 0 :(得分:1)

从Android 6.0(棉花糖)开始,不允许任何普通应用清除其他应用的缓存。仅当您的应用是系统应用或由与系统签名相同的证书签名时,您才能清除其他应用的缓存。但是,如何使用却存在一些漏洞。

您可以使用可访问性服务(由您正确指向)来执行此操作。

AFAIK,您可以显示缓存值,然后询问用户可访问性权限,并在授予该权限后打开设置屏幕->进入存储->单击“缓存”按钮,然后按确定。

请记住,这只是黑客行为,并且可能会因各种OEM和Android版本而产生错误。

谈到如何实现,this是一个很好的示例,探讨了如何使用辅助功能。

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

答案 1 :(得分:0)

您可以使用反射来访问PackageManager.deleteApplicationCacheFiles()

  // 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));
      }
    }
  }