What could be wrong with file.renameTo (file) in Android

I am reading the renameTo(File) documentation in the File.class Android SDK document.

We have been using this method for some time in production, but still I wonder what possible things might go wrong. The documentation states

Renames this file to newPath. This operation is supported for both files and directories.

Numerous failures are possible. Some of the most likely failures include:

  • Permission to write to directories containing both source and destination paths is required.

  • Search permission is required for all parents of both paths.

  • Both paths are at the same mount point. In Android applications, this restriction is most likely to hit when trying to copy between the internal storage and the SD card. Note that this method does not throw an IOException on failure. Callers must check the return value.

What are other possible reasons why renameTo() might fail (referring to more likely crashes)? Is there any guaranteed state after calling renameTo ? When renameTo() fails, can I rely on having my original file? Any other conditions that I want to check to make sure that it works next to those described in the documents?

+4
source share
3 answers

On Android, File.renameTo calls Linux rename () (via libcore). You can check the POSIX standard for a list of possible crashes, it may be slightly different from Linux, but should give you a general idea.

Also note this statement:

If the rename () function does not work for any reason other than [EIO], any file named new will not be affected.

+2
source

Three of these are more likely failures. Less likely (but possible!) Failures include

  • user error (for example, the source is a file, and the destination is an existing directory, or vice versa)
  • no space left on device
  • read-only file system
  • damaged file system
  • damaged sector on a rotating disk
  • ...

Since Android is based on Linux, you can probably rely on them:

  • If renaming fails, both files remain as they were
  • if the destination file exists and rename successfully, in no case will any process detect a missing destination file (replacement is atomic)
+3
source

Due to the fact that I do not know, it is impossible to use file.rename () to move files between different installed directories on Android (for example, sdcard0 and sdcard1), here is my solution and it works for me:

 if(canRename(f1, f2)) { if(!f1.renameTo(f2)) { Log.e(TAG, "Error to move new app: " + f1 + " > " + f2); } } else { try { copy(f1, f2); f1.delete(); } catch (Exception ex) { Log.e(TAG, "Error to move new app: " + f1 + " > " + f2); } } private void copy(final File f1, final File f2) throws IOException { f2.createNewFile(); final RandomAccessFile file1 = new RandomAccessFile(f1, "r"); final RandomAccessFile file2 = new RandomAccessFile(f2, "rw"); file2.getChannel().write(file1.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length())); file1.close(); file2.close(); } private boolean canRename(final File f1, final File f2) { final String p1 = f1.getAbsolutePath().replaceAll("^(/mnt/|/)", ""); final String p2 = f2.getAbsolutePath().replaceAll("^(/mnt/|/)", ""); return p1.replaceAll("\\/\\w+", "").equals(p2.replaceAll("\\/\\w+", "")); } 
0
source

Source: https://habr.com/ru/post/1498282/


All Articles