Clearing the Cache on OS Versions above Marshmallo

2019-06-21 06:10发布

I want to make an Android App which will clean the cache of other apps. I have figured out how to do that for Android Version below Marshmallow.

This is what I am using for Android Honeycom and above:

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

But I am having an issue to figure out how to do it for Android Version Marshmallow and above.

Other cache cleaners present in the market are able to perform this by taking accessibility permission or any other way?

2条回答
我只想做你的唯一
2楼-- · 2019-06-21 06:39

Starting from Android 6.0 (Marshmallow) any normal app is not permitted to clear the cache of other apps. You can clear the cache of other apps only if your app is a system app or is signed by the same certificate the system is signed. But there is a hack on how you can.

You can perform this by using accessibility service(which is correctly pointed by you).

AFAIK you can show the cache value and then ask the user for the accessibility permission and after the permission is granted open the settings screen-->go to storage-->click the Cache button and then press ok.

Keep in mind that this is only a hack and may produce errors based on various OEM's and Android version.

Coming to how you can achieve, this is a very good example to explore how accessibility service can be used.

ALSO, KEEP IN MIND THAT YOU NEED TO TAKE PRE APPROVAL FROM GOOGLE PLAY TO USE ACCESSIBILITY OR ELSE THE MIGHT REMOVE THE APP FROM THE PLAY STORE. DO TAKE PERMISSION BEFORE GIVING AN UPDATE OR ELSE THEY MIGHT SUSPEND OR TERMINATE YOUR APP. BE VERY CAREFUL ABOUT THIS.

查看更多
可以哭但决不认输i
3楼-- · 2019-06-21 06:56

If the application is a system app, it can request the android.permission.DELETE_CACHE_FILES and you could use reflection to access the 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));
      }
    }
  }
查看更多
登录 后发表回答