From a2bd77e98ecb71a55bef337517d9ac692ea43d2d Mon Sep 17 00:00:00 2001 From: Sean Mac Gillicuddy Date: Thu, 15 Aug 2019 13:48:31 +0100 Subject: [PATCH] #1333 cleanup and extension correction --- .../eu/mhutti1/utils/storage/StorageDevice.kt | 39 ++++----- .../utils/storage/StorageDeviceUtils.kt | 82 +++++++++---------- 2 files changed, 58 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/eu/mhutti1/utils/storage/StorageDevice.kt b/app/src/main/java/eu/mhutti1/utils/storage/StorageDevice.kt index f55cfd162..01214c164 100644 --- a/app/src/main/java/eu/mhutti1/utils/storage/StorageDevice.kt +++ b/app/src/main/java/eu/mhutti1/utils/storage/StorageDevice.kt @@ -21,19 +21,27 @@ package eu.mhutti1.utils.storage import android.os.Build import android.os.StatFs -import android.util.Log import java.io.BufferedReader import java.io.File import java.io.FileReader import java.io.FileWriter -import java.io.IOException + +const val LOCATION_EXTENSION = "storageLocationMarker" data class StorageDevice( val file: File, val isInternal: Boolean ) { - var isDuplicate = true + constructor(path: String, internal: Boolean) : this(File(path), internal) + + init { + if (file.exists()) { + createLocationCode() + } + } + + var isDuplicate = false private set val name: String @@ -62,32 +70,19 @@ data class StorageDevice( it.blockSize.toLong() * it.blockCount.toLong() } - constructor(path: String, internal: Boolean) : this(File(path), internal) - - init { - if (file.exists()) { - createLocationCode() - } - } - // Create unique file to identify duplicate devices. private fun createLocationCode() { if (!getLocationCodeFromFolder(file)) { - val locationCode = File(file.path, ".storageLocationMarker") - try { + File(file.path, ".$LOCATION_EXTENSION").let { locationCode -> locationCode.createNewFile() - val fw = FileWriter(locationCode) - fw.write(file.path) - fw.close() - } catch (e: IOException) { - Log.d("android-storage-devices", "Unable to create marker file, duplicates may be listed") + FileWriter(locationCode).use { it.write(file.path) } } } } // Check if there is already a device code in our path private fun getLocationCodeFromFolder(folder: File): Boolean { - val locationCode = File(folder.path, ".storageLocationMarker") + val locationCode = File(folder.path, ".$LOCATION_EXTENSION") if (locationCode.exists()) { try { BufferedReader(FileReader(locationCode)).use { br -> @@ -102,11 +97,11 @@ data class StorageDevice( return true } } - val parentFile = folder.parentFile - if (parentFile == null) { + val parent = folder.parentFile + if (parent == null) { isDuplicate = false return false } - return getLocationCodeFromFolder(parentFile) + return getLocationCodeFromFolder(parent) } } diff --git a/app/src/main/java/eu/mhutti1/utils/storage/StorageDeviceUtils.kt b/app/src/main/java/eu/mhutti1/utils/storage/StorageDeviceUtils.kt index bd55565af..d31d031ca 100644 --- a/app/src/main/java/eu/mhutti1/utils/storage/StorageDeviceUtils.kt +++ b/app/src/main/java/eu/mhutti1/utils/storage/StorageDeviceUtils.kt @@ -25,20 +25,18 @@ import androidx.core.content.ContextCompat import java.io.File import java.io.FileFilter import java.io.RandomAccessFile -import java.nio.channels.FileLock import java.util.ArrayList object StorageDeviceUtils { @JvmStatic fun getStorageDevices(context: Context, writable: Boolean): List { - val storageDevices = ArrayList() - - storageDevices.add(environmentDevices(Environment.getExternalStorageDirectory().path, writable)) - storageDevices.addAll(externalMountPointDevices()) - storageDevices.addAll(externalFilesDirsDevices(context, writable)) - - return validate(storageDevices, writable).also(::deleteStorageMarkers) + val storageDevices = ArrayList().apply { + add(environmentDevices(writable)) + addAll(externalMountPointDevices()) + addAll(externalFilesDirsDevices(context, writable)) + } + return validate(storageDevices, writable) } private fun externalFilesDirsDevices( @@ -48,44 +46,47 @@ object StorageDeviceUtils { .filterNotNull() .map { dir -> StorageDevice(generalisePath(dir.path, writable), false) } - private fun externalMountPointDevices(): Collection { - val storageDevices = ArrayList() - for (path in ExternalPaths.possiblePaths) { - if (path.endsWith("*")) { - val root = File(path.substringBeforeLast("*")) - root.listFiles(FileFilter(File::isDirectory)) - ?.mapTo(storageDevices) { dir -> StorageDevice(dir, false) } - } else { - storageDevices.add(StorageDevice(path, false)) + private fun externalMountPointDevices(): Collection = + ExternalPaths.possiblePaths.fold(mutableListOf(), { acc, path -> + acc.apply { + if (path.endsWith("*")) { + addAll(devicesBeneath(File(path.substringBeforeLast("*")))) + } else { + add(StorageDevice(path, false)) + } } - } - return storageDevices - } + }) + + private fun devicesBeneath(directory: File) = + directory.listFiles(FileFilter(File::isDirectory)) + ?.map { dir -> StorageDevice(dir, false) } + .orEmpty() private fun environmentDevices( - environmentPath: String, writable: Boolean ) = - // This is our internal storage directory - if (Environment.isExternalStorageEmulated()) - StorageDevice(generalisePath(environmentPath, writable), true) - // This is an external storage directory - else StorageDevice(generalisePath(environmentPath, writable), false) + StorageDevice( + generalisePath(Environment.getExternalStorageDirectory().path, writable), + Environment.isExternalStorageEmulated() + ) // Remove app specific path from directories so that we can search them from the top private fun generalisePath(path: String, writable: Boolean) = if (writable) path - else path.substringBeforeLast("/Android/data/") + else path.substringBefore("/Android/data/") // Amazingly file.canWrite() does not always return the correct value - private fun canWrite(file: File) = "$file/test.txt".let { + private fun canWrite(file: File): Boolean = "$file/test.txt".let { try { RandomAccessFile(it, "rw").use { randomAccessFile -> randomAccessFile.channel.use { channel -> - channel.lock().also(FileLock::release) - true + channel.lock().use { fileLock -> + fileLock.release() + true + } } } + } catch (ignore: Exception) { false } finally { File(it).delete() @@ -95,13 +96,13 @@ object StorageDeviceUtils { private fun validate( storageDevices: ArrayList, writable: Boolean - ): List { - return storageDevices.asSequence().distinct() - .filter { it.file.exists() } - .filter { it.file.isDirectory } - .filter { (!writable || canWrite(it.file)) } - .filterNot(StorageDevice::isDuplicate).toList() - } + ) = storageDevices.asSequence().distinct() + .filter { it.file.exists() } + .filter { it.file.isDirectory } + .filter { canWrite(it.file) || !writable } + .filterNot(StorageDevice::isDuplicate) + .toList() + .also(StorageDeviceUtils::deleteStorageMarkers) private fun deleteStorageMarkers(validatedDevices: List) { validatedDevices.forEach { recursiveDeleteStorageMarkers(it.file) } @@ -109,10 +110,9 @@ object StorageDeviceUtils { private fun recursiveDeleteStorageMarkers(file: File) { file.listFiles().forEach { - if (it.isDirectory) { - recursiveDeleteStorageMarkers(it) - } else if (it.extension == "storageMarker") { - it.delete() + when { + it.isDirectory -> recursiveDeleteStorageMarkers(it) + it.extension == LOCATION_EXTENSION -> it.delete() } } }