Очистка кэша на версиях ОС выше Marshmallow - PullRequest
5 голосов
/ 19 мая 2019

Я хочу создать приложение для Android, которое будет очищать кеш других приложений. Я разобрался, как это сделать для версии Android ниже Marshmallow.

Это - это то, что я использую для 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 версии Marshmallow и выше.

Другие устройства для очистки кэша, представленные на рынке, могут выполнить это, получив разрешение на доступ или любым другим способом?

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Начиная с Android 6.0 (Marshmallow), любому нормальному приложению запрещено очищать кэш других приложений.Вы можете очистить кеш других приложений, только если ваше приложение является системным приложением или подписано тем же сертификатом, что и система.Но есть хак на том, как вы можете.

Вы можете сделать это с помощью службы специальных возможностей (которая правильно указана вами).

AFAIK вы можете показать значение кэша, а затем спроситьпользователю для разрешения доступа и после того, как разрешение будет предоставлено, откройте экран настроек -> перейдите в хранилище -> нажмите кнопку Cache и затем нажмите ok.

Имейте в виду, что это только взлом и можетвыдает ошибки, основываясь на различных версиях OEM и Android.

Что касается того, как вы можете достичь, этот является очень хорошим примером для изучения возможностей использования службы специальных возможностей.

ТАКЖЕ ВНИМАНИЕ, ЧТО ВЫ ДОЛЖНЫ ПОЛУЧИТЬ ПРЕДВАРИТЕЛЬНОЕ УТВЕРЖДЕНИЕ ИЗ GOOGLE PLAY, ЧТОБЫ ИСПОЛЬЗОВАТЬ ДОСТУПНОСТЬ ИЛИ ЛИБО УДАЛИТЬ ПРИЛОЖЕНИЕ ИЗ МАГАЗИНА.ПРИНИМАЙТЕ РАЗРЕШЕНИЕ, ПРЕЖДЕ ЧЕМ ДАТЬ ОБНОВЛЕНИЕ, ИЛИ В противном случае они МОГУТ ПРИОСТАНОВИТЬ ИЛИ ПРЕКРАТИТЬ СВОЕ ПРИЛОЖЕНИЕ.БУДЬТЕ ОЧЕНЬ ОСТОРОЖНЫМ.

0 голосов
/ 27 мая 2019

Если приложение является системным приложением, оно может запросить android.permission.DELETE_CACHE_FILES, и вы можете использовать отражение для доступа к 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));
      }
    }
  }
...