content: 
  package com.banrossyn.imageloader.utils;
  
  import static android.os.Environment.MEDIA_MOUNTED;
  
  import android.content.Context;
  import android.content.pm.PackageManager;
  import android.os.Build;
  import android.os.Environment;
  
  import java.io.File;
  import java.io.IOException;
  
  /**
   * Provides application storage paths
   *
   * @author rossyn (banrossyn[at]gmail[dot]com)
   * @since 1.0.0
   */
  public final class StorageUtils {
  
      private static final String[] EXTERNAL_STORAGE_PERMISSION = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ? new String[]{"android.permission.READ_MEDIA_IMAGES", "android.permission.READ_MEDIA_VIDEO", "android.permission.READ_MEDIA_AUDIO"} : new String[]{"android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"};
      private static final String INDIVIDUAL_DIR_NAME = "uil-images";
  
      private StorageUtils() {
      }
  
      /**
       * Returns application cache directory. Cache directory will be created on SD card
       * <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted and app has appropriate permission. Else -
       * Android defines cache directory on device's file system.
       *
       * @param context Application context
       * @return Cache {@link File directory}.<br />
       * <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
       * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
       */
      public static File getCacheDirectory(Context context) {
          return getCacheDirectory(context, true);
      }
  
      /**
       * Returns application cache directory. Cache directory will be created on SD card
       * <i>("/Android/data/[app_package_name]/cache")</i> (if card is mounted and app has appropriate permission) or
       * on device's file system depending incoming parameters.
       *
       * @param context        Application context
       * @param preferExternal Whether prefer external location for cache
       * @return Cache {@link File directory}.<br />
       * <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
       * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
       */
      public static File getCacheDirectory(Context context, boolean preferExternal) {
          File appCacheDir = null;
          String externalStorageState;
          try {
              externalStorageState = Environment.getExternalStorageState();
          } catch (NullPointerException e) { // (sh)it happens (Issue #660)
              externalStorageState = "";
          } catch (IncompatibleClassChangeError e) { // (sh)it happens too (Issue #989)
              externalStorageState = "";
          }
          if (preferExternal && MEDIA_MOUNTED.equals(externalStorageState) && hasExternalStoragePermission(context)) {
              appCacheDir = getExternalCacheDir(context);
          }
          if (appCacheDir == null) {
              appCacheDir = context.getCacheDir();
          }
          if (appCacheDir == null) {
              String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
              L.w("Can't define system cache directory! '%s' will be used.", cacheDirPath);
              appCacheDir = new File(cacheDirPath);
          }
          return appCacheDir;
      }
  
      /**
       * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
       * created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted and app has
       * appropriate permission. Else - Android defines cache directory on device's file system.
       *
       * @param context Application context
       * @return Cache {@link File directory}
       */
      public static File getIndividualCacheDirectory(Context context) {
          return getIndividualCacheDirectory(context, INDIVIDUAL_DIR_NAME);
      }
  
      /**
       * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
       * created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted and app has
       * appropriate permission. Else - Android defines cache directory on device's file system.
       *
       * @param context  Application context
       * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
       * @return Cache {@link File directory}
       */
      public static File getIndividualCacheDirectory(Context context, String cacheDir) {
          File appCacheDir = getCacheDirectory(context);
          File individualCacheDir = new File(appCacheDir, cacheDir);
          if (!individualCacheDir.exists()) {
              if (!individualCacheDir.mkdir()) {
                  individualCacheDir = appCacheDir;
              }
          }
          return individualCacheDir;
      }
  
      /**
       * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
       * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system.
       *
       * @param context  Application context
       * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
       * @return Cache {@link File directory}
       */
      public static File getOwnCacheDirectory(Context context, String cacheDir) {
          File appCacheDir = null;
          if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
              appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
          }
          if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
              appCacheDir = context.getCacheDir();
          }
          return appCacheDir;
      }
  
      /**
       * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
       * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system.
       *
       * @param context  Application context
       * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
       * @return Cache {@link File directory}
       */
      public static File getOwnCacheDirectory(Context context, String cacheDir, boolean preferExternal) {
          File appCacheDir = null;
          if (preferExternal && MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
              appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
          }
          if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
              appCacheDir = context.getCacheDir();
          }
          return appCacheDir;
      }
  
      private static File getExternalCacheDir(Context context) {
          File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
          File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
          if (!appCacheDir.exists()) {
              if (!appCacheDir.mkdirs()) {
                  L.w("Unable to create external cache directory");
                  return null;
              }
              try {
                  new File(appCacheDir, ".nomedia").createNewFile();
              } catch (IOException e) {
                  L.i("Can't create \".nomedia\" file in application external cache directory");
              }
          }
          return appCacheDir;
      }
  
      private static boolean hasPermissions(Context context, String... permissions) {
          for (String permission : permissions) {
              int perm = context.checkCallingOrSelfPermission(permission);
              if (perm != PackageManager.PERMISSION_GRANTED) {
                  return false;
              }
          }
          return true;
      }
  
      private static boolean hasExternalStoragePermission(Context context) {
          return hasPermissions(context, EXTERNAL_STORAGE_PERMISSION);
      }
  }