From f44a7026477162930a7179511dda06cb8c2763d1 Mon Sep 17 00:00:00 2001 From: Hardcore Sushi Date: Tue, 25 Aug 2020 14:10:46 +0200 Subject: [PATCH] Volume on SD cards warning --- .../droidfs/ChangePasswordActivity.kt | 83 ++++++--- .../sushi/hardcore/droidfs/CreateActivity.kt | 174 +++++++++++------- .../sushi/hardcore/droidfs/OpenActivity.kt | 111 +++++++---- .../droidfs/explorers/BaseExplorerActivity.kt | 4 +- .../hardcore/droidfs/util/PathUtils.java | 42 +++-- .../res/layout/activity_change_password.xml | 2 +- app/src/main/res/layout/activity_create.xml | 2 +- app/src/main/res/layout/activity_open.xml | 2 +- app/src/main/res/values/strings.xml | 16 +- 9 files changed, 285 insertions(+), 151 deletions(-) diff --git a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt index cba6598..5d8bc79 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt @@ -20,6 +20,7 @@ import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver import sushi.hardcore.droidfs.util.* import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder +import java.io.File import java.util.* class ChangePasswordActivity : BaseActivity() { @@ -80,9 +81,25 @@ class ChangePasswordActivity : BaseActivity() { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { if (requestCode == PICK_DIRECTORY_REQUEST_CODE) { - if (data != null) { - val path = PathUtils.getFullPathFromTreeUri(data.data, this) - edit_volume_path.setText(path) + if (data?.data != null) { + if (PathUtils.isTreeUriOnPrimaryStorage(data.data)){ + val path = PathUtils.getFullPathFromTreeUri(data.data, this) + if (path != null){ + edit_volume_path.setText(path) + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.error) + .setMessage(R.string.path_from_uri_null_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.warning) + .setMessage(R.string.change_pwd_on_sdcard_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } } } } @@ -93,37 +110,52 @@ class ChangePasswordActivity : BaseActivity() { if (rootCipherDir.isEmpty()) { Toast.makeText(this, R.string.enter_volume_path, Toast.LENGTH_SHORT).show() } else { - changePassword(null) + if (!File(rootCipherDir).canWrite()){ + ColoredAlertDialogBuilder(this) + .setTitle(R.string.warning) + .setMessage(R.string.change_pwd_cant_write_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } else { + changePassword(null) + } } } private fun changePassword(givenHash: ByteArray?){ - object : LoadingTask(this, R.string.loading_msg_change_password){ - override fun doTask(activity: AppCompatActivity) { - val newPassword = edit_new_password.text.toString().toCharArray() - val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray() - if (!newPassword.contentEquals(newPasswordConfirm)) { - stopTaskWithToast(R.string.passwords_mismatch) - } else { + val newPassword = edit_new_password.text.toString().toCharArray() + val newPasswordConfirm = edit_new_password_confirm.text.toString().toCharArray() + if (!newPassword.contentEquals(newPasswordConfirm)) { + Toast.makeText(this, R.string.passwords_mismatch, Toast.LENGTH_SHORT).show() + } else { + object : LoadingTask(this, R.string.loading_msg_change_password) { + override fun doTask(activity: AppCompatActivity) { val oldPassword = edit_old_password.text.toString().toCharArray() var returnedHash: ByteArray? = null - if (usf_fingerprint && checkbox_save_password.isChecked){ + if (usf_fingerprint && checkbox_save_password.isChecked) { returnedHash = ByteArray(GocryptfsVolume.KeyLen) } var changePasswordImmediately = true - if (givenHash == null){ + if (givenHash == null) { val cipherText = sharedPrefs.getString(rootCipherDir, null) - if (cipherText != null){ //password hash saved + if (cipherText != null) { //password hash saved stopTask { fingerprintPasswordHashSaver.decrypt(cipherText, rootCipherDir, ::changePassword) } changePasswordImmediately = false } } - if (changePasswordImmediately){ - if (GocryptfsVolume.changePassword(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) { + if (changePasswordImmediately) { + if (GocryptfsVolume.changePassword( + rootCipherDir, + oldPassword, + givenHash, + newPassword, + returnedHash + ) + ) { val editor = sharedPrefs.edit() - if (sharedPrefs.getString(rootCipherDir, null) != null){ + if (sharedPrefs.getString(rootCipherDir, null) != null) { editor.remove(rootCipherDir) editor.apply() } @@ -133,17 +165,20 @@ class ChangePasswordActivity : BaseActivity() { val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList() if (!oldSavedVolumesPaths.contains(rootCipherDir)) { newSavedVolumesPaths.add(rootCipherDir) - editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet()) + editor.putStringSet( + ConstValues.saved_volumes_key, + newSavedVolumesPaths.toSet() + ) editor.apply() } - if (checkbox_save_password.isChecked && returnedHash != null){ - fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ -> + if (checkbox_save_password.isChecked && returnedHash != null) { + fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ -> stopTask { onPasswordChanged() } } continueImmediately = false } } - if (continueImmediately){ + if (continueImmediately) { stopTask { onPasswordChanged() } } } else { @@ -158,8 +193,10 @@ class ChangePasswordActivity : BaseActivity() { } Arrays.fill(oldPassword, 0.toChar()) } - Arrays.fill(newPassword, 0.toChar()) - Arrays.fill(newPasswordConfirm, 0.toChar()) + override fun doFinally(activity: AppCompatActivity) { + Arrays.fill(newPassword, 0.toChar()) + Arrays.fill(newPasswordConfirm, 0.toChar()) + } } } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt index 25a55fd..d9b9081 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt @@ -5,12 +5,9 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.view.View +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_create.* -import kotlinx.android.synthetic.main.activity_create.checkbox_remember_path -import kotlinx.android.synthetic.main.activity_create.checkbox_save_password -import kotlinx.android.synthetic.main.activity_create.edit_password -import kotlinx.android.synthetic.main.activity_create.edit_volume_path import kotlinx.android.synthetic.main.toolbar.* import sushi.hardcore.droidfs.explorers.ExplorerActivity import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver @@ -19,6 +16,7 @@ import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import java.io.File import java.util.* + class CreateActivity : BaseActivity() { companion object { private const val PICK_DIRECTORY_REQUEST_CODE = 1 @@ -53,91 +51,129 @@ class CreateActivity : BaseActivity() { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { if (requestCode == PICK_DIRECTORY_REQUEST_CODE) { - if (data != null) { - val path = PathUtils.getFullPathFromTreeUri(data.data, this) - edit_volume_path.setText(path) + if (data?.data != null) { + if (PathUtils.isTreeUriOnPrimaryStorage(data.data)){ + val path = PathUtils.getFullPathFromTreeUri(data.data, this) + if (path != null){ + edit_volume_path.setText(path) + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.error) + .setMessage(R.string.path_from_uri_null_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.warning) + .setMessage(R.string.create_on_sdcard_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } } } } } fun onClickCreate(view: View?) { - object: LoadingTask(this, R.string.loading_msg_create){ - override fun doTask(activity: AppCompatActivity) { - val password = edit_password.text.toString().toCharArray() - val passwordConfirm = edit_password_confirm.text.toString().toCharArray() - if (!password.contentEquals(passwordConfirm)) { - stopTaskWithToast(R.string.passwords_mismatch) - } else { - rootCipherDir = edit_volume_path.text.toString() - val volumePathFile = File(rootCipherDir) - var goodDirectory = false - if (!volumePathFile.isDirectory) { - if (volumePathFile.mkdirs()) { - goodDirectory = true - } else { - stopTaskWithToast(R.string.error_mkdir) - } - } else { - val dirContent = volumePathFile.list() - if (dirContent != null){ - if (dirContent.isEmpty()) { + rootCipherDir = edit_volume_path.text.toString() + if (rootCipherDir.isEmpty()) { + Toast.makeText(this, R.string.enter_volume_path, Toast.LENGTH_SHORT).show() + } else { + val password = edit_password.text.toString().toCharArray() + val passwordConfirm = edit_password_confirm.text.toString().toCharArray() + if (!password.contentEquals(passwordConfirm)) { + Toast.makeText(this, R.string.passwords_mismatch, Toast.LENGTH_SHORT).show() + } else { + object: LoadingTask(this, R.string.loading_msg_create){ + override fun doTask(activity: AppCompatActivity) { + val volumePathFile = File(rootCipherDir) + var goodDirectory = false + if (!volumePathFile.isDirectory) { + if (volumePathFile.mkdirs()) { goodDirectory = true } else { - stopTaskWithToast(R.string.dir_not_empty) + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(R.string.warning) + .setMessage(R.string.create_cant_write_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } } } else { - stopTaskWithToast(R.string.listdir_null_error_msg) - } - } - if (goodDirectory) { - if (GocryptfsVolume.createVolume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) { - var returnedHash: ByteArray? = null - if (usf_fingerprint && checkbox_save_password.isChecked){ - returnedHash = ByteArray(GocryptfsVolume.KeyLen) - } - sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash) - if (sessionID != -1) { - var startExplorerImmediately = true - if (checkbox_remember_path.isChecked) { - val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set - val editor = sharedPrefs.edit() - val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList() - if (oldSavedVolumesPaths.contains(rootCipherDir)) { - if (sharedPrefs.getString(rootCipherDir, null) != null){ - editor.remove(rootCipherDir) - } + val dirContent = volumePathFile.list() + if (dirContent != null){ + if (dirContent.isEmpty()) { + if (volumePathFile.canWrite()){ + goodDirectory = true } else { - newSavedVolumesPaths.add(rootCipherDir) - editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet()) - } - editor.apply() - if (checkbox_save_password.isChecked && returnedHash != null){ - fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ -> - stopTask { startExplorer() } + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(R.string.warning) + .setMessage(R.string.create_cant_write_error_msg) + .setPositiveButton(R.string.ok, null) + .show() } - startExplorerImmediately = false } - } - if (startExplorerImmediately){ - stopTask { startExplorer() } + } else { + stopTaskWithToast(R.string.dir_not_empty) } } else { - stopTaskWithToast(R.string.open_volume_failed) + stopTaskWithToast(R.string.listdir_null_error_msg) } - } else { - stopTask { - ColoredAlertDialogBuilder(activity) - .setTitle(R.string.error) - .setMessage(R.string.create_volume_failed) - .setPositiveButton(R.string.ok, null) - .show() + } + if (goodDirectory) { + if (GocryptfsVolume.createVolume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) { + var returnedHash: ByteArray? = null + if (usf_fingerprint && checkbox_save_password.isChecked){ + returnedHash = ByteArray(GocryptfsVolume.KeyLen) + } + sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash) + if (sessionID != -1) { + var startExplorerImmediately = true + if (checkbox_remember_path.isChecked) { + val oldSavedVolumesPaths = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set + val editor = sharedPrefs.edit() + val newSavedVolumesPaths = oldSavedVolumesPaths.toMutableList() + if (oldSavedVolumesPaths.contains(rootCipherDir)) { + if (sharedPrefs.getString(rootCipherDir, null) != null){ + editor.remove(rootCipherDir) + } + } else { + newSavedVolumesPaths.add(rootCipherDir) + editor.putStringSet(ConstValues.saved_volumes_key, newSavedVolumesPaths.toSet()) + } + editor.apply() + if (checkbox_save_password.isChecked && returnedHash != null){ + fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir){ _ -> + stopTask { startExplorer() } + } + startExplorerImmediately = false + } + } + if (startExplorerImmediately){ + stopTask { startExplorer() } + } + } else { + stopTaskWithToast(R.string.open_volume_failed) + } + } else { + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(R.string.error) + .setMessage(R.string.create_volume_failed) + .setPositiveButton(R.string.ok, null) + .show() + } } } } + override fun doFinally(activity: AppCompatActivity) { + Arrays.fill(password, 0.toChar()) + Arrays.fill(passwordConfirm, 0.toChar()) + } } - Arrays.fill(password, 0.toChar()) - Arrays.fill(passwordConfirm, 0.toChar()) } } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt index c1908a1..192d957 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt @@ -7,8 +7,16 @@ import android.os.Bundle import android.view.MenuItem import android.view.View import android.widget.AdapterView.OnItemClickListener +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import kotlinx.android.synthetic.main.activity_change_password.* +import kotlinx.android.synthetic.main.activity_create.* import kotlinx.android.synthetic.main.activity_open.* +import kotlinx.android.synthetic.main.activity_open.checkbox_remember_path +import kotlinx.android.synthetic.main.activity_open.checkbox_save_password +import kotlinx.android.synthetic.main.activity_open.edit_password +import kotlinx.android.synthetic.main.activity_open.edit_volume_path +import kotlinx.android.synthetic.main.activity_open.saved_path_listview import kotlinx.android.synthetic.main.toolbar.* import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter import sushi.hardcore.droidfs.explorers.ExplorerActivity @@ -82,52 +90,81 @@ class OpenActivity : BaseActivity() { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { if (requestCode == PICK_DIRECTORY_REQUEST_CODE) { - if (data != null) { - val path = PathUtils.getFullPathFromTreeUri(data.data, this) - edit_volume_path.setText(path) + if (data?.data != null) { + if (PathUtils.isTreeUriOnPrimaryStorage(data.data)){ + val path = PathUtils.getFullPathFromTreeUri(data.data, this) + if (path != null){ + edit_volume_path.setText(path) + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.error) + .setMessage(R.string.path_from_uri_null_error_msg) + .setPositiveButton(R.string.ok, null) + .show() + } + } else { + ColoredAlertDialogBuilder(this) + .setTitle(R.string.warning) + .setMessage(R.string.open_on_sdcard_warning) + .setPositiveButton(R.string.ok, null) + .show() + } } } } } fun onClickOpen(view: View?) { + rootCipherDir = edit_volume_path.text.toString() + if (rootCipherDir.isEmpty()) { + Toast.makeText(this, R.string.enter_volume_path, Toast.LENGTH_SHORT).show() + } else { + if (!File(rootCipherDir).canWrite()){ + ColoredAlertDialogBuilder(this) + .setTitle(R.string.warning) + .setMessage(R.string.open_cant_write_warning) + .setCancelable(false) + .setPositiveButton(R.string.ok) { _, _ -> openVolume() } + .show() + } else { + openVolume() + } + } + } + + private fun openVolume(){ object : LoadingTask(this, R.string.loading_msg_open){ override fun doTask(activity: AppCompatActivity) { - rootCipherDir = edit_volume_path.text.toString() //fresh get in case of manual rewrite - if (rootCipherDir.isEmpty()) { - stopTaskWithToast(R.string.enter_volume_path) - } else { - val password = edit_password.text.toString().toCharArray() - var returnedHash: ByteArray? = null - if (usf_fingerprint && checkbox_save_password.isChecked){ - returnedHash = ByteArray(GocryptfsVolume.KeyLen) - } - sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash) - if (sessionID != -1) { - var startExplorerImmediately = true - if (checkbox_remember_path.isChecked) { - savedVolumesAdapter.addVolumePath(rootCipherDir) - if (checkbox_save_password.isChecked && returnedHash != null){ - fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ -> - stopTask { startExplorer() } - } - startExplorerImmediately = false - } - } - if (startExplorerImmediately){ - stopTask { startExplorer() } - } - } else { - stopTask { - ColoredAlertDialogBuilder(activity) - .setTitle(R.string.open_volume_failed) - .setMessage(R.string.open_volume_failed_msg) - .setPositiveButton(R.string.ok, null) - .show() - } - } - Arrays.fill(password, 0.toChar()) + val password = edit_password.text.toString().toCharArray() + var returnedHash: ByteArray? = null + if (usf_fingerprint && checkbox_save_password.isChecked){ + returnedHash = ByteArray(GocryptfsVolume.KeyLen) } + sessionID = GocryptfsVolume.init(rootCipherDir, password, null, returnedHash) + if (sessionID != -1) { + var startExplorerImmediately = true + if (checkbox_remember_path.isChecked) { + savedVolumesAdapter.addVolumePath(rootCipherDir) + if (checkbox_save_password.isChecked && returnedHash != null){ + fingerprintPasswordHashSaver.encryptAndSave(returnedHash, rootCipherDir) { _ -> + stopTask { startExplorer() } + } + startExplorerImmediately = false + } + } + if (startExplorerImmediately){ + stopTask { startExplorer() } + } + } else { + stopTask { + ColoredAlertDialogBuilder(activity) + .setTitle(R.string.open_volume_failed) + .setMessage(R.string.open_volume_failed_msg) + .setPositiveButton(R.string.ok, null) + .show() + } + } + Arrays.fill(password, 0.toChar()) } } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt index c8fc145..c9e90f2 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt @@ -194,7 +194,9 @@ open class BaseExplorerActivity : BaseActivity() { } } total_size_text.text = getString(R.string.total_size, PathUtils.formatSize(totalSize)) - explorerAdapter.notifyDataSetChanged() + runOnUiThread { + explorerAdapter.notifyDataSetChanged() + } }.start() } diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java index 523fc52..bef2ea2 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java +++ b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java @@ -6,7 +6,9 @@ import android.net.Uri; import android.os.storage.StorageManager; import android.provider.DocumentsContract; import android.provider.OpenableColumns; + import androidx.annotation.Nullable; + import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -81,24 +83,35 @@ public class PathUtils { return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups))+" "+units[digitGroups]; } + public static Boolean isTreeUriOnPrimaryStorage(Uri treeUri){ + String volumeId = getVolumeIdFromTreeUri(treeUri); + if (volumeId != null) { + return volumeId.equals(PRIMARY_VOLUME_NAME) || volumeId.equals("home") || volumeId.equals("downloads"); + } else { + return false; + } + } + private static final String PRIMARY_VOLUME_NAME = "primary"; @Nullable - public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con) { + public static String getFullPathFromTreeUri(@Nullable Uri treeUri, Context context) { if (treeUri == null) return null; - String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri),con); - if (volumePath == null) return File.separator; - if (volumePath.endsWith(File.separator)) - volumePath = volumePath.substring(0, volumePath.length() - 1); - String documentPath = getDocumentPathFromTreeUri(treeUri); - if (documentPath.endsWith(File.separator)) - documentPath = documentPath.substring(0, documentPath.length() - 1); - if (documentPath.length() > 0) { - if (documentPath.startsWith(File.separator)) - return volumePath + documentPath; - else - return volumePath + File.separator + documentPath; + if ("content".equalsIgnoreCase(treeUri.getScheme())) { + String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri),context); + if (volumePath == null) return null; + if (volumePath.endsWith(File.separator)) + volumePath = volumePath.substring(0, volumePath.length() - 1); + String documentPath = getDocumentPathFromTreeUri(treeUri); + if (documentPath.endsWith(File.separator)) + documentPath = documentPath.substring(0, documentPath.length() - 1); + if (documentPath.length() > 0) { + return path_join(volumePath, documentPath); + } + else return volumePath; + } else if ("file".equalsIgnoreCase(treeUri.getScheme())) { + return treeUri.getPath(); } - else return volumePath; + return null; } private static String getVolumePath(final String volumeId, Context context) { @@ -117,7 +130,6 @@ public class PathUtils { Object storageVolumeElement = Array.get(result, i); String uuid = (String) getUuid.invoke(storageVolumeElement); Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement); - if (primary && PRIMARY_VOLUME_NAME.equals(volumeId)) return (String) getPath.invoke(storageVolumeElement); if (uuid != null && uuid.equals(volumeId)) diff --git a/app/src/main/res/layout/activity_change_password.xml b/app/src/main/res/layout/activity_change_password.xml index ca7ca28..d9655b0 100644 --- a/app/src/main/res/layout/activity_change_password.xml +++ b/app/src/main/res/layout/activity_change_password.xml @@ -143,7 +143,7 @@ android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:layout_marginBottom="@dimen/action_activity_button_margin_bottom" android:onClick="onClickChangePassword" - android:text="@string/change_volume_password" + android:text="@string/change_password" style="@style/button"/> diff --git a/app/src/main/res/layout/activity_create.xml b/app/src/main/res/layout/activity_create.xml index 812ed8e..7488313 100644 --- a/app/src/main/res/layout/activity_create.xml +++ b/app/src/main/res/layout/activity_create.xml @@ -114,7 +114,7 @@ android:layout_height="@dimen/action_activity_button_height" android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:onClick="onClickCreate" - android:text="@string/create_volume" + android:text="@string/create" style="@style/button"/> diff --git a/app/src/main/res/layout/activity_open.xml b/app/src/main/res/layout/activity_open.xml index 3dd0170..edb1336 100644 --- a/app/src/main/res/layout/activity_open.xml +++ b/app/src/main/res/layout/activity_open.xml @@ -102,7 +102,7 @@ android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:layout_marginBottom="@dimen/action_activity_button_margin_bottom" android:onClick="onClickOpen" - android:text="@string/open_volume" + android:text="@string/open" style="@style/button"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 12fa7e5..a9db081 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,8 +1,11 @@ DroidFS - OPEN A VOLUME - CREATE A VOLUME - CHANGE VOLUME PASSWORD + Open a volume + Create a volume + Change a volume\'s password + Open + Create + Change password Password: Password (confirmation): Volume Path: @@ -163,4 +166,11 @@ Choose filter Filters can only be applied to reduced quality images. If you want to take high definition photos, do not apply any filters. Please enter a numeric value + Failed to retrieve the selected path. + DroidFS doesn\'t have write access to this path. Please try another location. + DroidFS can\'t write on removable SD cards, please select a path on internal storage. + DroidFS can\'t write on removable SD cards. You will only have read-only access to the volumes therein. + DroidFS doesn\'t have write access to this path. You will only have read-only access to this volume. + DroidFS doesn\'t have write access to this path. You can try to move the volume to a writable location. + DroidFS can\'t write on removable SD cards, please move the volume to internal storage.