diff --git a/app/build.gradle b/app/build.gradle index c331a7d..06d502a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,6 +59,7 @@ android { } buildFeatures { viewBinding true + buildConfig true } compileOptions { sourceCompatibility JavaVersion.VERSION_17 diff --git a/app/gradle.properties b/app/gradle.properties index fd2fe2c..7045eca 100644 --- a/app/gradle.properties +++ b/app/gradle.properties @@ -1,4 +1,4 @@ -android.defaults.buildfeatures.buildconfig=true +# SPDX-License-Identifier: MIT android.enableJetifier=true android.nonFinalResIds=false android.nonTransitiveRClass=false diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a93f066..5e6f58a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,8 +39,9 @@ - + (R.id.drawer_layout) as DrawerLayout + R.id.navigation_drawer, findViewById(R.id.drawer_layout) as DrawerLayout ) ensureAllPermissionsGranted() @@ -124,8 +122,7 @@ class EasySSHFSActivity : AppCompatActivity(), NavigationDrawerFragment.Navigati val permissions = allPermissions.filter { ContextCompat.checkSelfPermission( - applicationContext, - it + applicationContext, it ) != PackageManager.PERMISSION_GRANTED } @@ -142,8 +139,7 @@ class EasySSHFSActivity : AppCompatActivity(), NavigationDrawerFragment.Navigati } override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, grantResults: IntArray + requestCode: Int, permissions: Array, grantResults: IntArray ) { if (requestCode == PERMISSION_REQUEST_CODE) { for (i in permissions.indices) { diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/NavigationDrawerFragment.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/NavigationDrawerFragment.kt index bba6144..f284ec7 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/NavigationDrawerFragment.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/NavigationDrawerFragment.kt @@ -15,6 +15,7 @@ import android.widget.ArrayAdapter import android.widget.ListView import androidx.appcompat.app.ActionBar import androidx.appcompat.app.ActionBarDrawerToggle +import androidx.core.content.edit import androidx.core.view.GravityCompat import androidx.core.view.MenuHost import androidx.core.view.MenuProvider @@ -54,7 +55,7 @@ class NavigationDrawerFragment : EasySSHFSFragment(), DrawerStatus { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Read in the flag indicating whether or not the user has demonstrated awareness of the + // Read in the flag indicating whether the user has demonstrated awareness of the // drawer. val sp = PreferenceManager.getDefaultSharedPreferences(requireContext()) userLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false) @@ -87,9 +88,7 @@ class NavigationDrawerFragment : EasySSHFSFragment(), DrawerStatus { } override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { drawerListView = inflater.inflate(R.layout.fragment_navigation_drawer, container, false) as ListView @@ -128,7 +127,7 @@ class NavigationDrawerFragment : EasySSHFSFragment(), DrawerStatus { actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setHomeButtonEnabled(true) - // ActionBarDrawerToggle ties together the the proper interactions + // ActionBarDrawerToggle ties together the proper interactions // between the navigation drawer and the action bar app icon. drawerToggle = object : ActionBarDrawerToggle( activity, /* host Activity */ @@ -156,7 +155,7 @@ class NavigationDrawerFragment : EasySSHFSFragment(), DrawerStatus { // the navigation drawer automatically in the future. userLearnedDrawer = true val sp = PreferenceManager.getDefaultSharedPreferences(requireContext()) - sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply() + sp.edit { putBoolean(PREF_USER_LEARNED_DRAWER, true) } } // Show the global app actions in the action bar. See also diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt index f551ecb..255d635 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt @@ -43,9 +43,7 @@ object ShellBuilder { } private fun isMagiskV27x(): Boolean { - val sh = Builder.create() - .setFlags(Shell.FLAG_NON_ROOT_SHELL) - .build() + val sh = Builder.create().setFlags(Shell.FLAG_NON_ROOT_SHELL).build() // The result should be something like this: // $ su -v 2>/dev/null diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/VersionUpdater.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/VersionUpdater.kt index 2ad21d6..47ca6b4 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/VersionUpdater.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/VersionUpdater.kt @@ -8,6 +8,7 @@ import android.os.Build import android.system.Os import android.util.Log import androidx.annotation.RequiresApi +import androidx.core.content.edit import ru.nsu.bobrofon.easysshfs.log.AppLog import ru.nsu.bobrofon.easysshfs.mountpointlist.MountPointsList import ru.nsu.bobrofon.easysshfs.mountpointlist.mountpoint.MountPoint @@ -35,9 +36,9 @@ class VersionUpdater( update02to03() } - val prefsEditor = settings.edit() - prefsEditor.putInt("version", currentVersion) - prefsEditor.apply() + settings.edit { + putInt("version", currentVersion) + } } private fun update02to03() { @@ -127,7 +128,7 @@ class VersionUpdater( } else { Reflected.Os.lstat(path) } - } catch (e: Exception) { + } catch (_: Exception) { // ErrnoException is only available since API 21 return false } diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogFragment.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogFragment.kt index 9d8f74d..13f8bac 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogFragment.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogFragment.kt @@ -29,8 +29,7 @@ class LogFragment : EasySSHFSFragment(), LogChangeObserver { override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { Log.i(TAG, "onCreateView") super.onCreateView(inflater, container, savedInstanceState) diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogObservable.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogObservable.kt index 41c25a4..7ce274e 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogObservable.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/log/LogObservable.kt @@ -11,8 +11,7 @@ interface LogChangeObserver { fun onLogChanged(logView: LogView) } -internal class LogObservable(private val logView: LogView) : - Observable() { +internal class LogObservable(private val logView: LogView) : Observable() { override fun registerObserver(observer: LogChangeObserver) { super.registerObserver(observer) diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountPointsList.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountPointsList.kt index 6ffb511..62b6945 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountPointsList.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountPointsList.kt @@ -3,6 +3,7 @@ package ru.nsu.bobrofon.easysshfs.mountpointlist import android.content.Context import android.util.Log +import androidx.core.content.edit import com.topjohnwu.superuser.Shell import org.json.JSONArray import org.json.JSONException @@ -76,8 +77,9 @@ class MountPointsList( selJson.put(item.json()) } - val prefsEditor = settings.edit() - prefsEditor.putString(STORAGE_FILE, selJson.toString()).apply() + settings.edit { + putString(STORAGE_FILE, selJson.toString()) + } autoMountObservable.notifyChanged(isAutoMountEnabled) } diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountpointFragment.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountpointFragment.kt index 52468b2..0fc5050 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountpointFragment.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/MountpointFragment.kt @@ -17,7 +17,6 @@ import androidx.core.view.MenuProvider import androidx.lifecycle.Lifecycle import ru.nsu.bobrofon.easysshfs.EasySSHFSFragment import ru.nsu.bobrofon.easysshfs.R -import ru.nsu.bobrofon.easysshfs.mountpointlist.MountpointFragment.OnFragmentInteractionListener import ru.nsu.bobrofon.easysshfs.mountpointlist.mountpoint.MountPointsArrayAdapter import ru.nsu.bobrofon.easysshfs.mountpointlist.mountpoint.MountStateChangeObserver @@ -34,9 +33,7 @@ class MountpointFragment : EasySSHFSFragment(), AdapterView.OnItemClickListener, private lateinit var mountPointsList: MountPointsList override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val context = requireContext() val shell = shell!! diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/EditFragment.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/EditFragment.kt index 5248591..62d555c 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/EditFragment.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/EditFragment.kt @@ -6,14 +6,18 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle -import android.view.* +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts.GetContent import androidx.activity.result.contract.ActivityResultContracts.OpenDocumentTree import androidx.annotation.RequiresApi import androidx.core.view.MenuHost import androidx.core.view.MenuProvider import androidx.lifecycle.Lifecycle - import ru.nsu.bobrofon.easysshfs.EasySSHFSActivity import ru.nsu.bobrofon.easysshfs.EasySSHFSFragment import ru.nsu.bobrofon.easysshfs.R @@ -50,8 +54,7 @@ class EditFragment : EasySSHFSFragment() { } override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { super.onCreateView(inflater, container, savedInstanceState) @@ -150,30 +153,29 @@ class EditFragment : EasySSHFSFragment() { } } - override fun onMenuItemSelected(menuItem: MenuItem): Boolean = - when (menuItem.itemId) { - R.id.action_save -> { - saveAction() - true - } - - R.id.action_delete -> { - deleteAction() - true - } + override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) { + R.id.action_save -> { + saveAction() + true + } - R.id.action_mount -> { - mountAction() - true - } + R.id.action_delete -> { + deleteAction() + true + } - R.id.action_umount -> { - umountAction() - true - } + R.id.action_mount -> { + mountAction() + true + } - else -> false + R.id.action_umount -> { + umountAction() + true } + + else -> false + } } private fun saveAction() { @@ -222,26 +224,24 @@ class EditFragment : EasySSHFSFragment() { } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - private val localDirPicker = - registerForActivityResult(OpenDocumentTree()) { uri: Uri? -> - uri?.let { setLocalPath(it) } - } + private val localDirPicker = registerForActivityResult(OpenDocumentTree()) { uri: Uri? -> + uri?.let { setLocalPath(it) } + } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) private fun selectLocalDir() { localDirPicker.launch(/* starting location */ null) } - private val identityFilePicker = - registerForActivityResult(object : GetContent() { - override fun createIntent(context: Context, input: String): Intent { - val intent = super.createIntent(context, input) - intent.addCategory(Intent.CATEGORY_OPENABLE) - return Intent.createChooser(intent, "Select IdentityFile") - } - }) { uri: Uri? -> - uri?.let { setIdentityFile(it) } + private val identityFilePicker = registerForActivityResult(object : GetContent() { + override fun createIntent(context: Context, input: String): Intent { + val intent = super.createIntent(context, input) + intent.addCategory(Intent.CATEGORY_OPENABLE) + return Intent.createChooser(intent, "Select IdentityFile") } + }) { uri: Uri? -> + uri?.let { setIdentityFile(it) } + } private fun selectIdentityFile() { identityFilePicker.launch("*/*") diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/FileUtil.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/FileUtil.kt index fc82b2a..2a17425 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/FileUtil.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/FileUtil.kt @@ -11,9 +11,9 @@ import android.os.Environment import android.os.storage.StorageManager import android.provider.DocumentsContract import android.provider.MediaStore +import androidx.core.net.toUri import ru.nsu.bobrofon.easysshfs.DeprecatedApi import java.io.File -import kotlin.Array import java.lang.reflect.Array as JArray // Some strange code from stackoverflow @@ -25,8 +25,7 @@ object FileUtil { volumePath = volumePath.trimEnd(File.separatorChar) documentPath = documentPath.trim(File.separatorChar) - return if (documentPath.isNotEmpty()) - volumePath + File.separator + documentPath else volumePath + return if (documentPath.isNotEmpty()) volumePath + File.separator + documentPath else volumePath } private fun getVolumePath(volumeId: String, context: Context): String? { @@ -86,7 +85,7 @@ object FileUtil { // not found return null - } catch (ex: Exception) { + } catch (_: Exception) { return null } } @@ -106,23 +105,20 @@ object FileUtil { private fun splitId(id: String): Array = id.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - fun getPath(uri: Uri, context: Context): String? = - when { - isDocumentUri(context, uri) -> getDocumentProviderPath(context, uri) - isMediaStoreUri(uri) -> getRemoteAddress(context, uri) - isFileUri(uri) -> uri.path - else -> null - } + fun getPath(uri: Uri, context: Context): String? = when { + isDocumentUri(context, uri) -> getDocumentProviderPath(context, uri) + isMediaStoreUri(uri) -> getRemoteAddress(context, uri) + isFileUri(uri) -> uri.path + else -> null + } private fun isDocumentUri(context: Context, uri: Uri): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri) - private fun isMediaStoreUri(uri: Uri): Boolean = - "content".equals(uri.scheme, ignoreCase = true) + private fun isMediaStoreUri(uri: Uri): Boolean = "content".equals(uri.scheme, ignoreCase = true) - private fun isFileUri(uri: Uri): Boolean = - "file".equals(uri.scheme, ignoreCase = true) + private fun isFileUri(uri: Uri): Boolean = "file".equals(uri.scheme, ignoreCase = true) private fun getDocumentProviderPath(context: Context, uri: Uri): String? = when { isExternalStorageDocument(uri) -> getExternalStorageProviderPath(uri) @@ -152,8 +148,8 @@ object FileUtil { return if ("primary".equals(uriType, ignoreCase = true)) { DeprecatedApi.Environment.getExternalStorageDirectory().path + "/" + uriValue } else { - val storageDefinition = if (Environment.isExternalStorageRemovable()) - "EXTERNAL_STORAGE" else "SECONDARY_STORAGE" + val storageDefinition = + if (Environment.isExternalStorageRemovable()) "EXTERNAL_STORAGE" else "SECONDARY_STORAGE" val storage = System.getenv(storageDefinition) ?: "" "$storage/$uriValue" @@ -165,7 +161,7 @@ object FileUtil { val id = DocumentsContract.getDocumentId(uri) val contentUri = try { ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), + "content://downloads/public_downloads".toUri(), java.lang.Long.valueOf(id) ) } catch (e: NumberFormatException) { @@ -199,8 +195,7 @@ object FileUtil { } private fun getDataColumn( - context: Context, uri: Uri, selection: String? = null, - selectionArgs: Array? = null + context: Context, uri: Uri, selection: String? = null, selectionArgs: Array? = null ): String? { val projection = arrayOf(DATA_COLUMN_NAME) @@ -208,11 +203,10 @@ object FileUtil { .use { cursor -> cursor?.let { getDataColumn(cursor) } } } - private fun getDataColumn(cursor: Cursor): String? = - if (cursor.moveToFirst()) { - val columnIndex = cursor.getColumnIndexOrThrow(DATA_COLUMN_NAME) - cursor.getString(columnIndex) - } else null + private fun getDataColumn(cursor: Cursor): String? = if (cursor.moveToFirst()) { + val columnIndex = cursor.getColumnIndexOrThrow(DATA_COLUMN_NAME) + cursor.getString(columnIndex) + } else null private const val DATA_COLUMN_NAME = "_data" diff --git a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/MountPoint.kt b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/MountPoint.kt index 98ba431..bdfa40b 100644 --- a/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/MountPoint.kt +++ b/app/src/main/java/ru/nsu/bobrofon/easysshfs/mountpointlist/mountpoint/MountPoint.kt @@ -15,7 +15,7 @@ import java.io.File import java.io.FileNotFoundException import java.io.IOException import java.lang.ref.WeakReference -import java.util.* +import java.util.LinkedList class MountPoint( @@ -45,7 +45,7 @@ class MountPoint( var port: Int = port set(value) { - if (value < 0 || value > 65535) { + if (value !in 0..65535) { logMessage("Port $value is out of range [0; 65535]") return } @@ -57,7 +57,7 @@ class MountPoint( fun setPort(value: String) { try { port = Integer.parseInt(value) - } catch (e: NumberFormatException) { + } catch (_: NumberFormatException) { logMessage("'$port' is invalid port value") } @@ -181,16 +181,17 @@ class MountPoint( private const val TAG = "MOUNT_POINT" - private class CheckMountTask constructor( + private class CheckMountTask( private val mountPoint: MountPoint, private val context: WeakReference = WeakReference(null) - ) : - AsyncTask>() { + ) : AsyncTask>() { private val mountFile = "/proc/mounts" - constructor(mountPoint: MountPoint, context: Context?) : - this(mountPoint, WeakReference(context)) + constructor(mountPoint: MountPoint, context: Context?) : this( + mountPoint, + WeakReference(context) + ) @Deprecated("Deprecated in Java") override fun doInBackground(vararg params: Void): Pair { @@ -212,8 +213,8 @@ class MountPoint( val result: Boolean try { - val procmount = File(mountFile) - result = procmount.useLines { lines -> + val procMounts = File(mountFile) + result = procMounts.useLines { lines -> lines.any { line -> line.contains(mountLine.toString()) } } } catch (e: FileNotFoundException) { @@ -244,14 +245,17 @@ class MountPoint( } } - private class MountTask constructor( + private class MountTask( private val mountPoint: MountPoint, private val shell: Shell, private val context: WeakReference = WeakReference(null) ) : AsyncTask() { - constructor(mountPoint: MountPoint, shell: Shell, context: Context?) : - this(mountPoint, shell, WeakReference(context)) + constructor(mountPoint: MountPoint, shell: Shell, context: Context?) : this( + mountPoint, + shell, + WeakReference(context) + ) @Deprecated("Deprecated in Java") override fun doInBackground(vararg params: Void): String { diff --git a/app/src/main/res/layout/fragment_edit.xml b/app/src/main/res/layout/fragment_edit.xml index 2e7faed..7b58fce 100644 --- a/app/src/main/res/layout/fragment_edit.xml +++ b/app/src/main/res/layout/fragment_edit.xml @@ -1,3 +1,4 @@ + @@ -89,6 +93,7 @@ diff --git a/app/src/main/res/raw/discard.xml b/app/src/main/res/raw/discard.xml deleted file mode 100644 index c7dab48..0000000 --- a/app/src/main/res/raw/discard.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml index 8b570f1..f1b303f 100644 --- a/app/src/main/res/xml/data_extraction_rules.xml +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -1,4 +1,5 @@ + - \ No newline at end of file + diff --git a/app/src/main/res/xml/full_backup_content.xml b/app/src/main/res/xml/full_backup_content.xml index 92b352b..917dc86 100644 --- a/app/src/main/res/xml/full_backup_content.xml +++ b/app/src/main/res/xml/full_backup_content.xml @@ -1,2 +1,4 @@ - \ No newline at end of file + + +