/**
   * Create a folder. The folder may even be on external SD card for Kitkat.
   *
   * @param file The folder to be created.
   * @return True if creation was successful.
   */
  public static boolean mkdir(final File file, Context context) {
    if (file == null) return false;
    if (file.exists()) {
      // nothing to create.
      return file.isDirectory();
    }

    // Try the normal way
    if (file.mkdirs()) {
      return true;
    }

    // Try with Storage Access Framework.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        && FileUtil.isOnExtSdCard(file, context)) {
      DocumentFile document = getDocumentFile(file, true, context);
      // getDocumentFile implicitly creates the directory.

      return document.exists();
    }

    // Try the Kitkat workaround.
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
      try {
        return MediaStoreHack.mkdir(context, file);
      } catch (IOException e) {
        return false;
      }
    }

    return false;
  }
  /**
   * Check for a directory if it is possible to create files within this directory, either via
   * normal writing or via Storage Access Framework.
   *
   * @param folder The directory
   * @return true if it is possible to write in this directory.
   */
  public static final boolean isWritableNormalOrSaf(final File folder, Context c) {
    // Verify that this is a directory.
    if (folder == null) return false;
    if (!folder.exists() || !folder.isDirectory()) {
      return false;
    }

    // Find a non-existing file in this directory.
    int i = 0;
    File file;
    do {
      String fileName = "AugendiagnoseDummyFile" + (++i);
      file = new File(folder, fileName);
    } while (file.exists());

    // First check regular writability
    if (isWritable(file)) {
      return true;
    }

    // Next check SAF writability.
    DocumentFile document = getDocumentFile(file, false, c);

    if (document == null) {
      return false;
    }

    // This should have created the file - otherwise something is wrong with access URL.
    boolean result = document.canWrite() && file.exists();

    // Ensure that the dummy file is not remaining.
    document.delete();

    return result;
  }
  /**
   * Delete a file. May be even on external SD card.
   *
   * @param file the file to be deleted.
   * @return True if successfully deleted.
   */
  public static final boolean deleteFile(@NonNull final File file, Context context) {
    // First try the normal deletion.
    boolean fileDelete = deleteFilesInFolder(file, context);
    if (file.delete() || fileDelete) return true;

    // Try with Storage Access Framework.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        && FileUtil.isOnExtSdCard(file, context)) {

      DocumentFile document = getDocumentFile(file, false, context);
      return document.delete();
    }

    // Try the Kitkat workaround.
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
      ContentResolver resolver = context.getContentResolver();

      try {
        Uri uri = MediaStoreUtil.getUriFromFile(file.getAbsolutePath(), context);
        resolver.delete(uri, null, null);
        return !file.exists();
      } catch (Exception e) {
        Log.e("AmazeFileUtils", "Error when deleting file " + file.getAbsolutePath(), e);
        return false;
      }
    }

    return !file.exists();
  }
Пример #4
0
 private DocumentFile getDCIMDocumentFolder(boolean create) {
   DocumentFile documentFile = null;
   DocumentFile sdDir;
   if ((sdDir = getExternalSdDocumentFile()) != null) {
     documentFile = sdDir.findFile("DCIM");
     if (documentFile == null && create) documentFile = sdDir.createDirectory("DCIM");
   }
   return documentFile;
 }
Пример #5
0
 @Override
 public DocumentFile getFreeDcamDocumentFolder() {
   DocumentFile dcimfolder;
   DocumentFile freedcamfolder = null;
   if ((dcimfolder = getDCIMDocumentFolder(true)) != null) {
     freedcamfolder = dcimfolder.findFile("FreeDcam");
     if (freedcamfolder == null) freedcamfolder = dcimfolder.createDirectory("FreeDcam");
   }
   return freedcamfolder;
 }
  /**
   * Rename a folder. In case of extSdCard in Kitkat, the old folder stays in place, but files are
   * moved.
   *
   * @param source The source folder.
   * @param target The target folder.
   * @return true if the renaming was successful.
   */
  public static final boolean renameFolder(
      @NonNull final File source, @NonNull final File target, Context context) {
    // First try the normal rename.
    if (new Futils().rename(source, target.getName(), false)) {
      return true;
    }
    if (target.exists()) {
      return false;
    }

    // Try the Storage Access Framework if it is just a rename within the same parent folder.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        && source.getParent().equals(target.getParent())
        && FileUtil.isOnExtSdCard(source, context)) {
      DocumentFile document = getDocumentFile(source, true, context);
      if (document.renameTo(target.getName())) {
        return true;
      }
    }

    // Try the manual way, moving files individually.
    if (!mkdir(target, context)) {
      return false;
    }

    File[] sourceFiles = source.listFiles();

    if (sourceFiles == null) {
      return true;
    }

    for (File sourceFile : sourceFiles) {
      String fileName = sourceFile.getName();
      File targetFile = new File(target, fileName);
      if (!copyFile(sourceFile, targetFile, context)) {
        // stop on first error
        return false;
      }
    }
    // Only after successfully copying all files, delete files on source folder.
    for (File sourceFile : sourceFiles) {
      if (!deleteFile(sourceFile, context)) {
        // stop on first error
        return false;
      }
    }
    return true;
  }
  /**
   * Get a DocumentFile corresponding to the given file (for writing on ExtSdCard on Android 5). If
   * the file is not existing, it is created.
   *
   * @param file The file.
   * @param isDirectory flag indicating if the file should be a directory.
   * @return The DocumentFile
   */
  public static DocumentFile getDocumentFile(
      final File file, final boolean isDirectory, Context context) {
    String baseFolder = getExtSdCardFolder(file, context);
    boolean originalDirectory = false;
    if (baseFolder == null) {
      return null;
    }

    String relativePath = null;
    try {
      String fullPath = file.getCanonicalPath();
      if (!baseFolder.equals(fullPath)) relativePath = fullPath.substring(baseFolder.length() + 1);
      else originalDirectory = true;
    } catch (IOException e) {
      return null;
    } catch (Exception f) {
      originalDirectory = true;
      // continue
    }
    String as = PreferenceManager.getDefaultSharedPreferences(context).getString("URI", null);

    Uri treeUri = null;
    if (as != null) treeUri = Uri.parse(as);
    if (treeUri == null) {
      return null;
    }

    // start with root of SD card and then parse through document tree.
    DocumentFile document = DocumentFile.fromTreeUri(context, treeUri);
    if (originalDirectory) return document;
    String[] parts = relativePath.split("\\/");
    for (int i = 0; i < parts.length; i++) {
      DocumentFile nextDocument = document.findFile(parts[i]);

      if (nextDocument == null) {
        if ((i < parts.length - 1) || isDirectory) {
          nextDocument = document.createDirectory(parts[i]);
        } else {
          nextDocument = document.createFile("image", parts[i]);
        }
      }
      document = nextDocument;
    }

    return document;
  }
  public static boolean rmdir(final File file, Context context) {
    if (file == null) return false;
    if (!file.exists()) {
      return true;
    }
    if (!file.isDirectory()) {
      return false;
    }
    String[] fileList = file.list();
    if (fileList != null && fileList.length > 0) {
      //  empty the folder.
      rmdir1(file, context);
    }
    String[] fileList1 = file.list();
    if (fileList1 != null && fileList1.length > 0) {
      // Delete only empty folder.
      return false;
    }
    // Try the normal way
    if (file.delete()) {
      return true;
    }

    // Try with Storage Access Framework.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      DocumentFile document = getDocumentFile(file, true, context);
      return document.delete();
    }

    // Try the Kitkat workaround.
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
      ContentResolver resolver = context.getContentResolver();
      ContentValues values = new ContentValues();
      values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
      resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

      // Delete the created entry, such that content provider will delete the file.
      resolver.delete(
          MediaStore.Files.getContentUri("external"),
          MediaStore.MediaColumns.DATA + "=?",
          new String[] {file.getAbsolutePath()});
    }

    return !file.exists();
  }
Пример #9
0
 @Override
 public DocumentFile getExternalSdDocumentFile() {
   DocumentFile sdDir = null;
   String extSdFolder = appSettingsManager.GetBaseFolder();
   if (extSdFolder == null || extSdFolder.equals("")) return null;
   Uri uri = Uri.parse(extSdFolder);
   sdDir = DocumentFile.fromTreeUri(getContext(), uri);
   return sdDir;
 }
Пример #10
0
 @Nullable
 private boolean deletFile(File file) {
   if (!file.delete()) {
     DocumentFile sdDir = getExternalSdDocumentFile();
     if (sdDir == null) return false;
     String baseS = sdDir.getName();
     String fileFolder = file.getAbsolutePath();
     String[] split = fileFolder.split("/");
     DocumentFile tmpdir = null;
     boolean append = false;
     for (String aSplit : split) {
       if (aSplit.equals(baseS) || append) {
         if (!append) {
           append = true;
           tmpdir = sdDir;
         } else {
           tmpdir = tmpdir.findFile(aSplit);
         }
       }
     }
     boolean d = false;
     d = !(tmpdir != null && tmpdir.exists()) || tmpdir.delete();
     Logger.d("delteDocumentFile", "file delted:" + d);
     return d;
   }
   return true;
 }
  public static boolean mkfile(final File file, Context context) throws IOException {
    if (file == null) return false;
    if (file.exists()) {
      // nothing to create.
      return !file.isDirectory();
    }

    // Try the normal way
    try {
      if (file.createNewFile()) {
        return true;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    boolean b = true;
    // Try with Storage Access Framework.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        && FileUtil.isOnExtSdCard(file, context)) {
      DocumentFile document = getDocumentFile(file.getParentFile(), true, context);
      // getDocumentFile implicitly creates the directory.
      try {
        b = document.createFile(MimeTypes.getMimeType(file), file.getName()) != null;
        return b;
      } catch (Exception e) {
        e.printStackTrace();
        return false;
      }
    }

    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
      try {
        return MediaStoreHack.mkfile(context, file);
      } catch (Exception e) {
        return false;
      }
    }
    return false;
  }
  public static OutputStream getOutputStream(@NonNull final File target, Context context, long s) {

    OutputStream outStream = null;
    try {
      // First try the normal way
      if (isWritable(target)) {
        // standard way
        outStream = new FileOutputStream(target);
      } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          // Storage Access Framework
          DocumentFile targetDocument = getDocumentFile(target, false, context);
          outStream = context.getContentResolver().openOutputStream(targetDocument.getUri());
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
          // Workaround for Kitkat ext SD card
          return MediaStoreHack.getOutputStream(context, target, s);
        }
      }
    } catch (Exception e) {
      Log.e("AmazeFileUtils", "Error when copying file from " + target.getAbsolutePath(), e);
    }
    return outStream;
  }
  /**
   * Copy a file. The target file may even be on external SD card for Kitkat.
   *
   * @param source The source file
   * @param target The target file
   * @return true if the copying was successful.
   */
  @SuppressWarnings("null")
  public static boolean copyFile(final File source, final File target, Context context) {
    FileInputStream inStream = null;
    OutputStream outStream = null;
    FileChannel inChannel = null;
    FileChannel outChannel = null;
    try {
      inStream = new FileInputStream(source);

      // First try the normal way
      if (isWritable(target)) {
        // standard way
        outStream = new FileOutputStream(target);
        inChannel = inStream.getChannel();
        outChannel = ((FileOutputStream) outStream).getChannel();
        inChannel.transferTo(0, inChannel.size(), outChannel);
      } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          // Storage Access Framework
          DocumentFile targetDocument = getDocumentFile(target, false, context);
          outStream = context.getContentResolver().openOutputStream(targetDocument.getUri());
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
          // Workaround for Kitkat ext SD card
          Uri uri = MediaStoreUtil.getUriFromFile(target.getAbsolutePath(), context);
          outStream = context.getContentResolver().openOutputStream(uri);
        } else {
          return false;
        }

        if (outStream != null) {
          // Both for SAF and for Kitkat, write to output stream.
          byte[] buffer = new byte[16384]; // MAGIC_NUMBER
          int bytesRead;
          while ((bytesRead = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, bytesRead);
          }
        }
      }
    } catch (Exception e) {
      Log.e(
          "AmazeFileUtils",
          "Error when copying file from "
              + source.getAbsolutePath()
              + " to "
              + target.getAbsolutePath(),
          e);
      return false;
    } finally {
      try {
        inStream.close();
      } catch (Exception e) {
        // ignore exception
      }
      try {
        outStream.close();
      } catch (Exception e) {
        // ignore exception
      }
      try {
        inChannel.close();
      } catch (Exception e) {
        // ignore exception
      }
      try {
        outChannel.close();
      } catch (Exception e) {
        // ignore exception
      }
    }
    return true;
  }