diff --git a/app/build.gradle b/app/build.gradle
index afca7ae..f857036 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,12 +6,16 @@ android {
compileSdkVersion 29
buildToolsVersion "30.0.0"
+ compileOptions {
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
defaultConfig {
applicationId "sushi.hardcore.droidfs"
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 29
versionCode 1
- versionName "1.0.1"
+ versionName "1.1.0"
ndk {
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
@@ -35,7 +39,7 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.core:core-ktx:1.3.0'
+ implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
@@ -44,4 +48,6 @@ dependencies {
implementation 'com.github.clans:fab:1.6.4'
implementation 'com.jaredrummler:cyanea:1.0.2'
implementation 'com.github.bumptech.glide:glide:4.11.0'
+ implementation 'com.google.android.exoplayer:exoplayer-core:2.11.7'
+ implementation 'com.google.android.exoplayer:exoplayer-ui:2.11.7'
}
diff --git a/app/libgocryptfs/main.go b/app/libgocryptfs/main.go
index f1f7fa5..bbc0002 100644
--- a/app/libgocryptfs/main.go
+++ b/app/libgocryptfs/main.go
@@ -771,7 +771,6 @@ func gcf_open_read_mode(sessionID int, path string) int {
}
defer syscall.Close(dirfd)
fd, err := syscallcompat.Openat(dirfd, cName, newFlags, 0)
- // Handle a few specific errors
if err != nil {
return -1
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a7ad0da..49ae32d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,10 @@
+
+
@@ -13,7 +17,8 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
- android:theme="@style/AppTheme">
+ android:theme="@style/AppTheme"
+ android:requestLegacyExternalStorage="true">
+ android:writePermission="${applicationId}.WRITE_TEMPORARY_STORAGE"/>
diff --git a/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt
index 8ddfc2d..7e3e069 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt
@@ -3,7 +3,6 @@ package sushi.hardcore.droidfs
import android.content.SharedPreferences
import android.os.Bundle
import android.view.WindowManager
-import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import com.jaredrummler.cyanea.app.CyaneaAppCompatActivity
diff --git a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt
index ac77acc..1127668 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt
@@ -7,7 +7,6 @@ import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
-import android.view.WindowManager
import android.widget.AdapterView.OnItemClickListener
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_change_password.*
@@ -18,7 +17,7 @@ import kotlinx.android.synthetic.main.activity_change_password.saved_path_listvi
import kotlinx.android.synthetic.main.toolbar.*
import sushi.hardcore.droidfs.adapters.SavedVolumesAdapter
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.util.Wiper
@@ -80,7 +79,7 @@ class ChangePasswordActivity : BaseActivity() {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
if (data != null) {
- val path = FilesUtils.getFullPathFromTreeUri(data.data, this)
+ val path = PathUtils.getFullPathFromTreeUri(data.data, this)
edit_volume_path.setText(path)
}
}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt
index 2e09257..9fc4aae 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt
@@ -1,5 +1,6 @@
package sushi.hardcore.droidfs
+import android.net.Uri
import java.io.File
class ConstValues {
@@ -7,6 +8,7 @@ class ConstValues {
const val creator = "DroidFS"
const val saved_volumes_key = "saved_volumes"
const val sort_order_key = "sort_order"
+ val fakeUri = Uri.parse("fakeuri://droidfs")
const val wipe_passes = 2
const val seek_bar_inc = 200
private val fileExtensions = mapOf(
diff --git a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt
index 7facd16..250b7fb 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/CreateActivity.kt
@@ -5,7 +5,6 @@ import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.View
-import android.view.WindowManager
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_create.*
import kotlinx.android.synthetic.main.activity_create.checkbox_remember_path
@@ -15,7 +14,7 @@ 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
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.util.Wiper
@@ -57,7 +56,7 @@ class CreateActivity : BaseActivity() {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
if (data != null) {
- val path = FilesUtils.getFullPathFromTreeUri(data.data, this)
+ val path = PathUtils.getFullPathFromTreeUri(data.data, this)
edit_volume_path.setText(path)
}
}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt
index bf1a8e5..975c52d 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt
@@ -35,14 +35,14 @@ class MainActivity : BaseActivity() {
if (!storageAvailable) {
ColoredAlertDialog(this)
.setTitle(R.string.storage_unavailable)
- .setMessage(getString(R.string.storage_unavailable_msg))
+ .setMessage(R.string.storage_unavailable_msg)
.setPositiveButton(R.string.ok
) { _, _ -> finish() }.show()
}
if (!sharedPrefs.getBoolean("alreadyLaunched", false)){
ColoredAlertDialog(this)
.setTitle(R.string.warning)
- .setMessage(getString(R.string.usf_home_warning_msg))
+ .setMessage(R.string.usf_home_warning_msg)
.setCancelable(false)
.setPositiveButton(getString(R.string.see_unsafe_features)){ _, _ ->
val intent = Intent(this, SettingsActivity::class.java)
@@ -65,7 +65,7 @@ class MainActivity : BaseActivity() {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
ColoredAlertDialog(this)
.setTitle(R.string.storage_perm_denied)
- .setMessage(getString(R.string.storage_perm_denied_msg))
+ .setMessage(R.string.storage_perm_denied_msg)
.setPositiveButton(R.string.ok
) { _, _ -> finish() }.show()
}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt
index 51c2bff..65f978b 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/OpenActivity.kt
@@ -5,7 +5,6 @@ import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.View
-import android.view.WindowManager
import android.widget.AdapterView.OnItemClickListener
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_open.checkbox_remember_path
@@ -19,7 +18,7 @@ import sushi.hardcore.droidfs.explorers.ExplorerActivity
import sushi.hardcore.droidfs.explorers.ExplorerActivityDrop
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
import sushi.hardcore.droidfs.fingerprint_stuff.FingerprintPasswordHashSaver
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.util.Wiper
@@ -76,7 +75,7 @@ class OpenActivity : BaseActivity() {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
if (data != null) {
- val path = FilesUtils.getFullPathFromTreeUri(data.data, this)
+ val path = PathUtils.getFullPathFromTreeUri(data.data, this)
edit_volume_path.setText(path)
}
}
@@ -128,7 +127,7 @@ class OpenActivity : BaseActivity() {
} else {
ColoredAlertDialog(this)
.setTitle(R.string.open_volume_failed)
- .setMessage(getString(R.string.open_failed_hash_msg))
+ .setMessage(R.string.open_failed_hash_msg)
.setPositiveButton(R.string.ok, null)
.show()
}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt
index 7c9f208..9bfcb6b 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt
@@ -14,23 +14,23 @@ import androidx.core.content.ContextCompat
import sushi.hardcore.droidfs.ConstValues.Companion.getAssociatedDrawable
import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ThemeColor
import java.text.DateFormat
import java.util.*
class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
private val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, context.resources.configuration.locale)
- private lateinit var explorer_elements: List
+ private lateinit var explorerElements: List
private val inflater: LayoutInflater = LayoutInflater.from(context)
val selectedItems: MutableList = ArrayList()
private val themeColor = ThemeColor.getThemeColor(context)
override fun getCount(): Int {
- return explorer_elements.size
+ return explorerElements.size
}
override fun getItem(position: Int): ExplorerElement {
- return explorer_elements[position]
+ return explorerElements[position]
}
override fun getItemId(position: Int): Long {
@@ -55,7 +55,7 @@ class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
}
else -> {
textElementMtime.text = dateFormat.format(currentElement.mTime)
- textElementSize.text = FilesUtils.formatSize(currentElement.size)
+ textElementSize.text = PathUtils.formatSize(currentElement.size)
drawableId = getAssociatedDrawable(currentElement.name)
}
}
@@ -73,56 +73,55 @@ class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
fun onItemClick(position: Int) {
if (selectedItems.isNotEmpty()) {
- if (!explorer_elements[position].isParentFolder) {
+ if (!explorerElements[position].isParentFolder) {
if (selectedItems.contains(position)) {
selectedItems.remove(position)
} else {
selectedItems.add(position)
}
- notifyDataSetInvalidated()
+ notifyDataSetChanged()
}
}
}
fun onItemLongClick(position: Int) {
- if (!explorer_elements[position].isParentFolder) {
+ if (!explorerElements[position].isParentFolder) {
if (!selectedItems.contains(position)) {
selectedItems.add(position)
} else {
selectedItems.remove(position)
}
- notifyDataSetInvalidated()
+ notifyDataSetChanged()
}
}
fun selectAll() {
- for (i in explorer_elements.indices) {
- if (!selectedItems.contains(i) && !explorer_elements[i].isParentFolder) {
+ for (i in explorerElements.indices) {
+ if (!selectedItems.contains(i) && !explorerElements[i].isParentFolder) {
selectedItems.add(i)
}
}
- notifyDataSetInvalidated()
+ notifyDataSetChanged()
}
fun unSelectAll() {
selectedItems.clear()
- notifyDataSetInvalidated()
+ notifyDataSetChanged()
}
fun setExplorerElements(explorer_elements: List) {
unSelectAll()
- this.explorer_elements = explorer_elements
+ this.explorerElements = explorer_elements
}
val currentDirectoryTotalSize: Long
get() {
- var total_size: Long = 0
- for (e in explorer_elements) {
+ var totalSize: Long = 0
+ for (e in explorerElements) {
if (e.isRegularFile) {
- total_size += e.size
+ totalSize += e.size
}
}
- return total_size
+ return totalSize
}
-
}
\ No newline at end of file
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 0cfe35e..03f8845 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt
@@ -1,7 +1,6 @@
package sushi.hardcore.droidfs.explorers
import android.content.Intent
-import android.content.SharedPreferences
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
@@ -29,50 +28,48 @@ import sushi.hardcore.droidfs.file_viewers.AudioPlayer
import sushi.hardcore.droidfs.file_viewers.ImageViewer
import sushi.hardcore.droidfs.file_viewers.TextEditor
import sushi.hardcore.droidfs.file_viewers.VideoPlayer
-import sushi.hardcore.droidfs.provider.TemporaryFileProvider
+import sushi.hardcore.droidfs.provider.RestrictedFileProvider
import sushi.hardcore.droidfs.util.ExternalProvider
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
import java.util.*
open class BaseExplorerActivity : BaseActivity() {
- private lateinit var shared_prefs_editor: SharedPreferences.Editor
- private lateinit var sort_modes_entries: Array
- private lateinit var sort_modes_values: Array
- private var current_sort_mode_index = 0
+ private lateinit var sortModesEntries: Array
+ private lateinit var sortModesValues: Array
+ private var currentSortModeIndex = 0
protected lateinit var gocryptfsVolume: GocryptfsVolume
- private lateinit var volume_name: String
- protected var current_path = ""
- protected lateinit var explorer_elements: MutableList
- protected lateinit var explorer_adapter: ExplorerElementAdapter
+ private lateinit var volumeName: String
+ protected var currentDirectoryPath = ""
+ protected lateinit var explorerElements: MutableList
+ protected lateinit var explorerAdapter: ExplorerElementAdapter
private var usf_open = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
usf_open = sharedPrefs.getBoolean("usf_open", false)
val intent = intent
- volume_name = intent.getStringExtra("volume_name") ?: ""
+ volumeName = intent.getStringExtra("volume_name") ?: ""
val sessionID = intent.getIntExtra("sessionID", -1)
gocryptfsVolume = GocryptfsVolume(sessionID)
- sort_modes_entries = resources.getStringArray(R.array.sort_orders_entries)
- sort_modes_values = resources.getStringArray(R.array.sort_orders_values)
- current_sort_mode_index = resources.getStringArray(R.array.sort_orders_values).indexOf(sharedPrefs.getString(ConstValues.sort_order_key, "name"))
- shared_prefs_editor = sharedPrefs.edit()
+ sortModesEntries = resources.getStringArray(R.array.sort_orders_entries)
+ sortModesValues = resources.getStringArray(R.array.sort_orders_values)
+ currentSortModeIndex = resources.getStringArray(R.array.sort_orders_values).indexOf(sharedPrefs.getString(ConstValues.sort_order_key, "name"))
init()
setSupportActionBar(toolbar)
title = ""
- title_text.text = getString(R.string.volume, volume_name)
- explorer_adapter = ExplorerElementAdapter(this)
- setCurrentPath(current_path)
- list_explorer.adapter = explorer_adapter
+ title_text.text = getString(R.string.volume, volumeName)
+ explorerAdapter = ExplorerElementAdapter(this)
+ setCurrentPath(currentDirectoryPath)
+ list_explorer.adapter = explorerAdapter
list_explorer.onItemClickListener = OnItemClickListener { _, _, position, _ -> onExplorerItemClick(position) }
list_explorer.onItemLongClickListener = OnItemLongClickListener { _, _, position, _ ->
- explorer_adapter.onItemLongClick(position)
+ explorerAdapter.onItemLongClick(position)
invalidateOptionsMenu()
true
}
refresher.setOnRefreshListener {
- setCurrentPath(current_path)
+ setCurrentPath(currentDirectoryPath)
refresher.isRefreshing = false
}
}
@@ -89,29 +86,29 @@ open class BaseExplorerActivity : BaseActivity() {
}
protected open fun onExplorerItemClick(position: Int) {
- val wasSelecting = explorer_adapter.selectedItems.isNotEmpty()
- explorer_adapter.onItemClick(position)
- if (explorer_adapter.selectedItems.isEmpty()) {
+ val wasSelecting = explorerAdapter.selectedItems.isNotEmpty()
+ explorerAdapter.onItemClick(position)
+ if (explorerAdapter.selectedItems.isEmpty()) {
if (!wasSelecting) {
- val full_path = FilesUtils.path_join(current_path, explorer_elements[position].name)
+ val fullPath = PathUtils.path_join(currentDirectoryPath, explorerElements[position].name)
when {
- explorer_elements[position].isDirectory -> {
- setCurrentPath(full_path)
+ explorerElements[position].isDirectory -> {
+ setCurrentPath(fullPath)
}
- explorer_elements[position].isParentFolder -> {
- setCurrentPath(FilesUtils.get_parent_path(current_path))
+ explorerElements[position].isParentFolder -> {
+ setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
}
- isImage(full_path) -> {
- startFileViewer(ImageViewer::class.java, full_path)
+ isImage(fullPath) -> {
+ startFileViewer(ImageViewer::class.java, fullPath)
}
- isVideo(full_path) -> {
- startFileViewer(VideoPlayer::class.java, full_path)
+ isVideo(fullPath) -> {
+ startFileViewer(VideoPlayer::class.java, fullPath)
}
- isText(full_path) -> {
- startFileViewer(TextEditor::class.java, full_path)
+ isText(fullPath) -> {
+ startFileViewer(TextEditor::class.java, fullPath)
}
- isAudio(full_path) -> {
- startFileViewer(AudioPlayer::class.java, full_path)
+ isAudio(fullPath) -> {
+ startFileViewer(AudioPlayer::class.java, fullPath)
}
else -> {
val dialogListView = layoutInflater.inflate(R.layout.dialog_listview, null)
@@ -125,10 +122,10 @@ open class BaseExplorerActivity : BaseActivity() {
.create()
listView.setOnItemClickListener{_, _, fileTypePosition, _ ->
when (adapter.getItem(fileTypePosition)){
- "image" -> startFileViewer(ImageViewer::class.java, full_path)
- "video" -> startFileViewer(VideoPlayer::class.java, full_path)
- "audio" -> startFileViewer(AudioPlayer::class.java, full_path)
- "text" -> startFileViewer(TextEditor::class.java, full_path)
+ "image" -> startFileViewer(ImageViewer::class.java, fullPath)
+ "video" -> startFileViewer(VideoPlayer::class.java, fullPath)
+ "audio" -> startFileViewer(AudioPlayer::class.java, fullPath)
+ "text" -> startFileViewer(TextEditor::class.java, fullPath)
}
dialog.dismiss()
}
@@ -141,41 +138,42 @@ open class BaseExplorerActivity : BaseActivity() {
}
private fun sortExplorerElements() {
- when (sort_modes_values[current_sort_mode_index]) {
+ when (sortModesValues[currentSortModeIndex]) {
"name" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> o1.name.compareTo(o2.name) })
+ explorerElements.sortWith(Comparator { o1, o2 -> o1.name.compareTo(o2.name) })
}
"size" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> (o1.size - o2.size).toInt() })
+ explorerElements.sortWith(Comparator { o1, o2 -> (o1.size - o2.size).toInt() })
}
"date" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> o1.mTime.compareTo(o2.mTime) })
+ explorerElements.sortWith(Comparator { o1, o2 -> o1.mTime.compareTo(o2.mTime) })
}
"name_desc" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> o2.name.compareTo(o1.name) })
+ explorerElements.sortWith(Comparator { o1, o2 -> o2.name.compareTo(o1.name) })
}
"size_desc" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> (o2.size - o1.size).toInt() })
+ explorerElements.sortWith(Comparator { o1, o2 -> (o2.size - o1.size).toInt() })
}
"date_desc" -> {
- explorer_elements.sortWith(Comparator { o1, o2 -> o2.mTime.compareTo(o1.mTime) })
+ explorerElements.sortWith(Comparator { o1, o2 -> o2.mTime.compareTo(o1.mTime) })
}
}
- shared_prefs_editor.putString(ConstValues.sort_order_key, sort_modes_values[current_sort_mode_index])
- shared_prefs_editor.apply()
+ val sharedPrefsEditor = sharedPrefs.edit()
+ sharedPrefsEditor.putString(ConstValues.sort_order_key, sortModesValues[currentSortModeIndex])
+ sharedPrefsEditor.apply()
}
protected fun setCurrentPath(path: String) {
- explorer_elements = gocryptfsVolume.list_dir(path)
- text_dir_empty.visibility = if (explorer_elements.size == 0) View.VISIBLE else View.INVISIBLE
+ explorerElements = gocryptfsVolume.list_dir(path)
+ text_dir_empty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.INVISIBLE
sortExplorerElements()
if (path.isNotEmpty()) { //not root
- explorer_elements.add(0, ExplorerElement("..", (-1).toShort(), -1, -1))
+ explorerElements.add(0, ExplorerElement("..", (-1).toShort(), -1, -1))
}
- explorer_adapter.setExplorerElements(explorer_elements)
- current_path = path
- current_path_text.text = getString(R.string.location, current_path)
- total_size_text.text = getString(R.string.total_size, FilesUtils.formatSize(explorer_adapter.currentDirectoryTotalSize))
+ explorerAdapter.setExplorerElements(explorerElements)
+ currentDirectoryPath = path
+ current_path_text.text = getString(R.string.location, currentDirectoryPath)
+ total_size_text.text = getString(R.string.total_size, PathUtils.formatSize(explorerAdapter.currentDirectoryTotalSize))
}
private fun askCloseVolume() {
@@ -193,19 +191,19 @@ open class BaseExplorerActivity : BaseActivity() {
protected open fun closeVolumeOnDestroy() {
gocryptfsVolume.close()
- TemporaryFileProvider.wipeAll() //additional security
+ RestrictedFileProvider.wipeAll() //additional security
}
override fun onBackPressed() {
- if (explorer_adapter.selectedItems.isEmpty()) {
- val parent_path = FilesUtils.get_parent_path(current_path)
- if (parent_path == current_path) {
+ if (explorerAdapter.selectedItems.isEmpty()) {
+ val parentPath = PathUtils.get_parent_path(currentDirectoryPath)
+ if (parentPath == currentDirectoryPath) {
askCloseVolume()
} else {
- setCurrentPath(FilesUtils.get_parent_path(current_path))
+ setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
}
} else {
- explorer_adapter.unSelectAll()
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
}
}
@@ -214,14 +212,14 @@ open class BaseExplorerActivity : BaseActivity() {
if (folder_name.isEmpty()) {
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
} else {
- if (!gocryptfsVolume.mkdir(FilesUtils.path_join(current_path, folder_name))) {
+ if (!gocryptfsVolume.mkdir(PathUtils.path_join(currentDirectoryPath, folder_name))) {
ColoredAlertDialog(this)
.setTitle(R.string.error)
.setMessage(R.string.error_mkdir)
.setPositiveButton(R.string.ok, null)
.show()
} else {
- setCurrentPath(current_path)
+ setCurrentPath(currentDirectoryPath)
invalidateOptionsMenu()
}
}
@@ -254,14 +252,14 @@ open class BaseExplorerActivity : BaseActivity() {
if (new_name.isEmpty()) {
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
} else {
- if (!gocryptfsVolume.rename(FilesUtils.path_join(current_path, old_name), FilesUtils.path_join(current_path, new_name))) {
+ if (!gocryptfsVolume.rename(PathUtils.path_join(currentDirectoryPath, old_name), PathUtils.path_join(currentDirectoryPath, new_name))) {
ColoredAlertDialog(this)
.setTitle(R.string.error)
.setMessage(getString(R.string.rename_failed, old_name))
.setPositiveButton(R.string.ok, null)
.show()
} else {
- setCurrentPath(current_path)
+ setCurrentPath(currentDirectoryPath)
invalidateOptionsMenu()
}
}
@@ -272,7 +270,7 @@ open class BaseExplorerActivity : BaseActivity() {
if (usf_open){
menu.findItem(R.id.explorer_menu_external_open)?.isVisible = false
}
- val selectedItems = explorer_adapter.selectedItems
+ val selectedItems = explorerAdapter.selectedItems
if (selectedItems.isEmpty()){
toolbar.navigationIcon = null
menu.findItem(R.id.explorer_menu_close).isVisible = true
@@ -283,7 +281,7 @@ open class BaseExplorerActivity : BaseActivity() {
menu.findItem(R.id.explorer_menu_sort).isVisible = false
if (selectedItems.size == 1) {
menu.findItem(R.id.explorer_menu_rename).isVisible = true
- if (usf_open && explorer_elements[selectedItems[0]].isRegularFile) {
+ if (usf_open && explorerElements[selectedItems[0]].isRegularFile) {
menu.findItem(R.id.explorer_menu_external_open)?.isVisible = true
}
}
@@ -293,39 +291,39 @@ open class BaseExplorerActivity : BaseActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
- explorer_adapter.unSelectAll()
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
true
}
R.id.explorer_menu_sort -> {
ColoredAlertDialog(this)
.setTitle(R.string.sort_order)
- .setSingleChoiceItems(sort_modes_entries, current_sort_mode_index) { dialog, which ->
- current_sort_mode_index = which
- setCurrentPath(current_path)
+ .setSingleChoiceItems(sortModesEntries, currentSortModeIndex) { dialog, which ->
+ currentSortModeIndex = which
+ setCurrentPath(currentDirectoryPath)
dialog.dismiss()
}.show()
true
}
R.id.explorer_menu_rename -> {
- val dialog_edit_text_view = layoutInflater.inflate(R.layout.dialog_edit_text, null)
- val old_name = explorer_elements[explorer_adapter.selectedItems[0]].name
- val dialog_edit_text = dialog_edit_text_view.findViewById(R.id.dialog_edit_text)
- dialog_edit_text.setText(old_name)
- dialog_edit_text.selectAll()
+ val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
+ val oldName = explorerElements[explorerAdapter.selectedItems[0]].name
+ val dialogEditText = dialogEditTextView.findViewById(R.id.dialog_edit_text)
+ dialogEditText.setText(oldName)
+ dialogEditText.selectAll()
val dialog = ColoredAlertDialog(this)
- .setView(dialog_edit_text_view)
+ .setView(dialogEditTextView)
.setTitle(R.string.rename_title)
.setPositiveButton(R.string.ok) { _, _ ->
- val new_name = dialog_edit_text.text.toString()
- rename(old_name, new_name)
+ val newName = dialogEditText.text.toString()
+ rename(oldName, newName)
}
.setNegativeButton(R.string.cancel, null)
.create()
- dialog_edit_text.setOnEditorActionListener { _, _, _ ->
- val new_name = dialog_edit_text.text.toString()
+ dialogEditText.setOnEditorActionListener { _, _, _ ->
+ val newName = dialogEditText.text.toString()
dialog.dismiss()
- rename(old_name, new_name)
+ rename(oldName, newName)
true
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
@@ -334,8 +332,8 @@ open class BaseExplorerActivity : BaseActivity() {
}
R.id.explorer_menu_external_open -> {
if (usf_open){
- ExternalProvider.open(this, gocryptfsVolume, FilesUtils.path_join(current_path, explorer_elements[explorer_adapter.selectedItems[0]].name))
- explorer_adapter.unSelectAll()
+ ExternalProvider.open(this, gocryptfsVolume, PathUtils.path_join(currentDirectoryPath, explorerElements[explorerAdapter.selectedItems[0]].name))
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
}
true
@@ -357,6 +355,6 @@ open class BaseExplorerActivity : BaseActivity() {
override fun onResume() {
super.onResume()
- ExternalProvider.clear_cache(this)
+ ExternalProvider.removeFiles(this)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt
index cad7990..2d098a2 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt
@@ -14,7 +14,7 @@ import kotlinx.android.synthetic.main.activity_explorer.*
import sushi.hardcore.droidfs.OpenActivity
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.ExternalProvider
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.Wiper
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
@@ -37,16 +37,16 @@ class ExplorerActivity : BaseExplorerActivity() {
if (fileName.isEmpty()) {
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
} else {
- val handleID = gocryptfsVolume.open_write_mode(FilesUtils.path_join(current_path, fileName))
+ val handleID = gocryptfsVolume.open_write_mode(PathUtils.path_join(currentDirectoryPath, fileName))
if (handleID == -1) {
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.file_creation_failed))
+ .setMessage(R.string.file_creation_failed)
.setPositiveButton(R.string.ok, null)
.show()
} else {
gocryptfsVolume.close_file(handleID)
- setCurrentPath(current_path)
+ setCurrentPath(currentDirectoryPath)
invalidateOptionsMenu()
}
}
@@ -110,7 +110,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (uris.isNotEmpty()){
var success = true
for (uri in uris) {
- val dstPath = FilesUtils.path_join(current_path, FilesUtils.getFilenameFromURI(this, uri))
+ val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
contentResolver.openInputStream(uri)?.let {
success = gocryptfsVolume.import_file(it, dstPath)
}
@@ -154,32 +154,32 @@ class ExplorerActivity : BaseExplorerActivity() {
.setNegativeButton(getString(R.string.no), null)
.show()
}
- setCurrentPath(current_path)
+ setCurrentPath(currentDirectoryPath)
}
}
} else if (requestCode == PICK_DIRECTORY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK && data != null) {
val uri = data.data
- val output_dir = FilesUtils.getFullPathFromTreeUri(uri, this)
- var failed_item: String? = null
- for (i in explorer_adapter.selectedItems) {
- val element = explorer_adapter.getItem(i)
- val full_path = FilesUtils.path_join(current_path, element.name)
- failed_item = if (element.isDirectory) {
- recursive_export_directory(full_path, output_dir)
+ val outputDir = PathUtils.getFullPathFromTreeUri(uri, this)
+ var failedItem: String? = null
+ for (i in explorerAdapter.selectedItems) {
+ val element = explorerAdapter.getItem(i)
+ val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
+ failedItem = if (element.isDirectory) {
+ recursiveExportDirectory(fullPath, outputDir)
} else {
- if (gocryptfsVolume.export_file(full_path, FilesUtils.path_join(output_dir, element.name))) null else full_path
+ if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
}
- if (failed_item != null) {
+ if (failedItem != null) {
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.export_failed, failed_item))
+ .setMessage(getString(R.string.export_failed, failedItem))
.setPositiveButton(R.string.ok, null)
.show()
break
}
}
- if (failed_item == null) {
+ if (failedItem == null) {
ColoredAlertDialog(this)
.setTitle(R.string.success_export)
.setMessage(R.string.success_export_msg)
@@ -187,33 +187,33 @@ class ExplorerActivity : BaseExplorerActivity() {
.show()
}
}
- explorer_adapter.unSelectAll()
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
} else if (requestCode == PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK && data != null) {
- val remote_sessionID = data.getIntExtra("sessionID", -1)
- val remote_gocryptfsVolume = GocryptfsVolume(remote_sessionID)
+ val remoteSessionID = data.getIntExtra("sessionID", -1)
+ val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
val path = data.getStringExtra("path")
- var failed_item: String? = null
+ var failedItem: String? = null
if (path == null) {
val paths = data.getStringArrayListExtra("paths")
val types = data.getIntegerArrayListExtra("types")
if (types != null && paths != null){
for (i in paths.indices) {
- failed_item = if (types[i] == 0) { //directory
- recursive_import_directory_from_other_volume(remote_gocryptfsVolume, paths[i], current_path)
+ failedItem = if (types[i] == 0) { //directory
+ recursiveImportDirectoryFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)
} else {
- if (import_file_from_other_volume(remote_gocryptfsVolume, paths[i], current_path)) null else paths[i]
+ if (importFileFromOtherVolume(remoteGocryptfsVolume, paths[i], currentDirectoryPath)) null else paths[i]
}
- if (failed_item != null) {
+ if (failedItem != null) {
break
}
}
}
} else {
- failed_item = if (import_file_from_other_volume(remote_gocryptfsVolume, path, current_path)) null else path
+ failedItem = if (importFileFromOtherVolume(remoteGocryptfsVolume, path, currentDirectoryPath)) null else path
}
- if (failed_item == null) {
+ if (failedItem == null) {
ColoredAlertDialog(this)
.setTitle(R.string.success_import)
.setMessage(R.string.success_import_msg)
@@ -222,12 +222,12 @@ class ExplorerActivity : BaseExplorerActivity() {
} else {
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.import_failed, failed_item))
+ .setMessage(getString(R.string.import_failed, failedItem))
.setPositiveButton(R.string.ok, null)
.show()
}
- remote_gocryptfsVolume.close()
- setCurrentPath(current_path)
+ remoteGocryptfsVolume.close()
+ setCurrentPath(currentDirectoryPath)
}
}
}
@@ -238,14 +238,14 @@ class ExplorerActivity : BaseExplorerActivity() {
if (usf_share){
menu.findItem(R.id.explorer_menu_share).isVisible = false
}
- val any_item_selected = explorer_adapter.selectedItems.isNotEmpty()
- menu.findItem(R.id.explorer_menu_select_all).isVisible = any_item_selected
- menu.findItem(R.id.explorer_menu_delete).isVisible = any_item_selected
- menu.findItem(R.id.explorer_menu_decrypt).isVisible = any_item_selected && usf_decrypt
- if (any_item_selected && usf_share){
+ val anyItemSelected = explorerAdapter.selectedItems.isNotEmpty()
+ menu.findItem(R.id.explorer_menu_select_all).isVisible = anyItemSelected
+ menu.findItem(R.id.explorer_menu_delete).isVisible = anyItemSelected
+ menu.findItem(R.id.explorer_menu_decrypt).isVisible = anyItemSelected && usf_decrypt
+ if (anyItemSelected && usf_share){
var containsDir = false
- for (i in explorer_adapter.selectedItems) {
- if (explorer_elements[i].isDirectory) {
+ for (i in explorerAdapter.selectedItems) {
+ if (explorerElements[i].isDirectory) {
containsDir = true
break
}
@@ -260,32 +260,32 @@ class ExplorerActivity : BaseExplorerActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.explorer_menu_select_all -> {
- explorer_adapter.selectAll()
+ explorerAdapter.selectAll()
invalidateOptionsMenu()
true
}
R.id.explorer_menu_delete -> {
- val size = explorer_adapter.selectedItems.size
+ val size = explorerAdapter.selectedItems.size
val dialog = ColoredAlertDialog(this)
dialog.setTitle(R.string.warning)
- dialog.setPositiveButton(R.string.ok) { _, _ -> remove_selected_items() }
+ dialog.setPositiveButton(R.string.ok) { _, _ -> removeSelectedItems() }
dialog.setNegativeButton(R.string.cancel, null)
if (size > 1) {
- dialog.setMessage(getString(R.string.multiple_delete_confirm, explorer_adapter.selectedItems.size.toString()))
+ dialog.setMessage(getString(R.string.multiple_delete_confirm, explorerAdapter.selectedItems.size.toString()))
} else {
- dialog.setMessage(getString(R.string.single_delete_confirm, explorer_adapter.getItem(explorer_adapter.selectedItems[0]).name))
+ dialog.setMessage(getString(R.string.single_delete_confirm, explorerAdapter.getItem(explorerAdapter.selectedItems[0]).name))
}
dialog.show()
true
}
R.id.explorer_menu_share -> {
val paths: MutableList = ArrayList()
- for (i in explorer_adapter.selectedItems) {
- val e = explorer_elements[i]
- paths.add(FilesUtils.path_join(current_path, e.name))
+ for (i in explorerAdapter.selectedItems) {
+ val e = explorerElements[i]
+ paths.add(PathUtils.path_join(currentDirectoryPath, e.name))
}
ExternalProvider.share(this, gocryptfsVolume, paths)
- explorer_adapter.unSelectAll()
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
true
}
@@ -298,18 +298,18 @@ class ExplorerActivity : BaseExplorerActivity() {
}
}
- private fun import_file_from_other_volume(remote_gocryptfsVolume: GocryptfsVolume, full_path: String, output_dir: String): Boolean {
- val output_path = FilesUtils.path_join(output_dir, File(full_path).name)
+ private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, full_path: String, output_dir: String): Boolean {
+ val outputPath = PathUtils.path_join(output_dir, File(full_path).name)
var success = true
- val src_handleID = remote_gocryptfsVolume.open_read_mode(full_path)
- if (src_handleID != -1) {
- val dst_handleID = gocryptfsVolume.open_write_mode(output_path)
- if (dst_handleID != -1) {
+ val srcHandleID = remote_gocryptfsVolume.open_read_mode(full_path)
+ if (srcHandleID != -1) {
+ val dstHandleID = gocryptfsVolume.open_write_mode(outputPath)
+ if (dstHandleID != -1) {
var length: Int
- val io_buffer = ByteArray(GocryptfsVolume.DefaultBS)
+ val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
var offset: Long = 0
- while (remote_gocryptfsVolume.read_file(src_handleID, offset, io_buffer).also { length = it } > 0){
- val written = gocryptfsVolume.write_file(dst_handleID, offset, io_buffer, length).toLong()
+ while (remote_gocryptfsVolume.read_file(srcHandleID, offset, ioBuffer).also { length = it } > 0){
+ val written = gocryptfsVolume.write_file(dstHandleID, offset, ioBuffer, length).toLong()
if (written == length.toLong()) {
offset += length.toLong()
} else {
@@ -317,46 +317,46 @@ class ExplorerActivity : BaseExplorerActivity() {
break
}
}
- gocryptfsVolume.close_file(dst_handleID)
+ gocryptfsVolume.close_file(dstHandleID)
}
- remote_gocryptfsVolume.close_file(src_handleID)
+ remote_gocryptfsVolume.close_file(srcHandleID)
}
return success
}
- private fun recursive_import_directory_from_other_volume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, output_dir: String): String? {
- val directory_path = FilesUtils.path_join(output_dir, File(remote_directory_path).name)
- if (!gocryptfsVolume.path_exists(directory_path)) {
- if (!gocryptfsVolume.mkdir(directory_path)) {
- return directory_path
+ private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, output_dir: String): String? {
+ val directoryPath = PathUtils.path_join(output_dir, File(remote_directory_path).name)
+ if (!gocryptfsVolume.path_exists(directoryPath)) {
+ if (!gocryptfsVolume.mkdir(directoryPath)) {
+ return directoryPath
}
}
- val explorer_elements = remote_gocryptfsVolume.list_dir(remote_directory_path)
- for (e in explorer_elements) {
- val full_path = FilesUtils.path_join(remote_directory_path, e.name)
+ val explorerElements = remote_gocryptfsVolume.list_dir(remote_directory_path)
+ for (e in explorerElements) {
+ val fullPath = PathUtils.path_join(remote_directory_path, e.name)
if (e.isDirectory) {
- val failed_item = recursive_import_directory_from_other_volume(remote_gocryptfsVolume, full_path, directory_path)
- failed_item?.let { return it }
+ val failedItem = recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume, fullPath, directoryPath)
+ failedItem?.let { return it }
} else {
- if (!import_file_from_other_volume(remote_gocryptfsVolume, full_path, directory_path)) {
- return full_path
+ if (!importFileFromOtherVolume(remote_gocryptfsVolume, fullPath, directoryPath)) {
+ return fullPath
}
}
}
return null
}
- private fun recursive_export_directory(plain_directory_path: String, output_dir: String?): String? {
- if (File(FilesUtils.path_join(output_dir, plain_directory_path)).mkdir()) {
- val explorer_elements = gocryptfsVolume.list_dir(plain_directory_path)
- for (e in explorer_elements) {
- val full_path = FilesUtils.path_join(plain_directory_path, e.name)
+ private fun recursiveExportDirectory(plain_directory_path: String, output_dir: String?): String? {
+ if (File(PathUtils.path_join(output_dir, plain_directory_path)).mkdir()) {
+ val explorerElements = gocryptfsVolume.list_dir(plain_directory_path)
+ for (e in explorerElements) {
+ val fullPath = PathUtils.path_join(plain_directory_path, e.name)
if (e.isDirectory) {
- val failed_item = recursive_export_directory(full_path, output_dir)
- failed_item?.let { return it }
+ val failedItem = recursiveExportDirectory(fullPath, output_dir)
+ failedItem?.let { return it }
} else {
- if (!gocryptfsVolume.export_file(full_path, FilesUtils.path_join(output_dir, full_path))) {
- return full_path
+ if (!gocryptfsVolume.export_file(fullPath, PathUtils.path_join(output_dir, fullPath))) {
+ return fullPath
}
}
}
@@ -365,16 +365,16 @@ class ExplorerActivity : BaseExplorerActivity() {
return output_dir
}
- private fun recursive_remove_directory(plain_directory_path: String): String? {
- val explorer_elements = gocryptfsVolume.list_dir(plain_directory_path)
- for (e in explorer_elements) {
- val full_path = FilesUtils.path_join(plain_directory_path, e.name)
+ private fun recursiveRemoveDirectory(plain_directory_path: String): String? {
+ val explorerElements = gocryptfsVolume.list_dir(plain_directory_path)
+ for (e in explorerElements) {
+ val fullPath = PathUtils.path_join(plain_directory_path, e.name)
if (e.isDirectory) {
- val result = recursive_remove_directory(full_path)
+ val result = recursiveRemoveDirectory(fullPath)
result?.let { return it }
} else {
- if (!gocryptfsVolume.remove_file(full_path)) {
- return full_path
+ if (!gocryptfsVolume.remove_file(fullPath)) {
+ return fullPath
}
}
}
@@ -385,30 +385,30 @@ class ExplorerActivity : BaseExplorerActivity() {
}
}
- private fun remove_selected_items() {
- var failed_item: String? = null
- for (i in explorer_adapter.selectedItems) {
- val element = explorer_adapter.getItem(i)
- val full_path = FilesUtils.path_join(current_path, element.name)
+ private fun removeSelectedItems() {
+ var failedItem: String? = null
+ for (i in explorerAdapter.selectedItems) {
+ val element = explorerAdapter.getItem(i)
+ val fullPath = PathUtils.path_join(currentDirectoryPath, element.name)
if (element.isDirectory) {
- val result = recursive_remove_directory(full_path)
- result?.let{ failed_item = it }
+ val result = recursiveRemoveDirectory(fullPath)
+ result?.let{ failedItem = it }
} else {
- if (!gocryptfsVolume.remove_file(full_path)) {
- failed_item = full_path
+ if (!gocryptfsVolume.remove_file(fullPath)) {
+ failedItem = fullPath
}
}
- if (failed_item != null) {
+ if (failedItem != null) {
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.remove_failed, failed_item))
+ .setMessage(getString(R.string.remove_failed, failedItem))
.setPositiveButton(R.string.ok, null)
.show()
break
}
}
- explorer_adapter.unSelectAll()
+ explorerAdapter.unSelectAll()
invalidateOptionsMenu()
- setCurrentPath(current_path) //refresh
+ setCurrentPath(currentDirectoryPath) //refresh
}
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt
index 0888073..5a0d73e 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt
@@ -5,7 +5,7 @@ import android.net.Uri
import android.view.Menu
import android.view.MenuItem
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
class ExplorerActivityDrop : BaseExplorerActivity() {
@@ -16,7 +16,7 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.explorer_drop, menu)
handleMenuItems(menu)
- menu.findItem(R.id.explorer_menu_validate).isVisible = explorer_adapter.selectedItems.isEmpty()
+ menu.findItem(R.id.explorer_menu_validate).isVisible = explorerAdapter.selectedItems.isEmpty()
return true
}
@@ -31,13 +31,13 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
if (extras != null && extras.containsKey(Intent.EXTRA_STREAM)){
if (intent.action == Intent.ACTION_SEND) {
val uri = intent.getParcelableExtra(Intent.EXTRA_STREAM)
- val output_path = FilesUtils.path_join(current_path, FilesUtils.getFilenameFromURI(this, uri))
+ val output_path = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
error_msg = if (gocryptfsVolume.import_file(this, uri, output_path)) null else getString(R.string.import_failed, output_path)
} else if (intent.action == Intent.ACTION_SEND_MULTIPLE) {
val uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
if (uris != null){
for (uri in uris) {
- val output_path = FilesUtils.path_join(current_path, FilesUtils.getFilenameFromURI(this, uri))
+ val output_path = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
if (!gocryptfsVolume.import_file(this, uri, output_path)) {
error_msg = getString(R.string.import_failed, output_path)
break
diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt
index ff6120a..52f99c7 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityPick.kt
@@ -5,8 +5,8 @@ import android.content.Intent
import android.view.Menu
import android.view.MenuItem
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.provider.TemporaryFileProvider
-import sushi.hardcore.droidfs.util.FilesUtils
+import sushi.hardcore.droidfs.provider.RestrictedFileProvider
+import sushi.hardcore.droidfs.util.PathUtils
import java.util.*
class ExplorerActivityPick : BaseExplorerActivity() {
@@ -17,21 +17,21 @@ class ExplorerActivityPick : BaseExplorerActivity() {
}
override fun onExplorerItemClick(position: Int) {
- val wasSelecting = explorer_adapter.selectedItems.isNotEmpty()
- explorer_adapter.onItemClick(position)
- if (explorer_adapter.selectedItems.isEmpty()) {
+ val wasSelecting = explorerAdapter.selectedItems.isNotEmpty()
+ explorerAdapter.onItemClick(position)
+ if (explorerAdapter.selectedItems.isEmpty()) {
if (!wasSelecting) {
- val full_path = FilesUtils.path_join(current_path, explorer_elements[position].name)
+ val full_path = PathUtils.path_join(currentDirectoryPath, explorerElements[position].name)
when {
- explorer_elements[position].isDirectory -> {
+ explorerElements[position].isDirectory -> {
setCurrentPath(full_path)
}
- explorer_elements[position].isParentFolder -> {
- setCurrentPath(FilesUtils.get_parent_path(current_path))
+ explorerElements[position].isParentFolder -> {
+ setCurrentPath(PathUtils.get_parent_path(currentDirectoryPath))
}
else -> {
result_intent.putExtra("path", full_path)
- return_activity_result()
+ returnActivityResult()
}
}
}
@@ -42,7 +42,7 @@ class ExplorerActivityPick : BaseExplorerActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.explorer_pick, menu)
handleMenuItems(menu)
- val any_item_selected = explorer_adapter.selectedItems.isNotEmpty()
+ val any_item_selected = explorerAdapter.selectedItems.isNotEmpty()
menu.findItem(R.id.explorer_menu_select_all).isVisible = any_item_selected
menu.findItem(R.id.explorer_menu_validate).isVisible = any_item_selected
return true
@@ -51,35 +51,35 @@ class ExplorerActivityPick : BaseExplorerActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.explorer_menu_select_all -> {
- explorer_adapter.selectAll()
+ explorerAdapter.selectAll()
invalidateOptionsMenu()
true
}
R.id.explorer_menu_validate -> {
val paths = ArrayList()
val types = ArrayList()
- for (i in explorer_adapter.selectedItems) {
- val e = explorer_elements[i]
- paths.add(FilesUtils.path_join(current_path, e.name))
+ for (i in explorerAdapter.selectedItems) {
+ val e = explorerElements[i]
+ paths.add(PathUtils.path_join(currentDirectoryPath, e.name))
types.add(e.elementType.toInt())
}
result_intent.putStringArrayListExtra("paths", paths)
result_intent.putIntegerArrayListExtra("types", types)
- return_activity_result()
+ returnActivityResult()
true
}
else -> super.onOptionsItemSelected(item)
}
}
- private fun return_activity_result() {
+ private fun returnActivityResult() {
setResult(Activity.RESULT_OK, result_intent)
finish()
}
override fun closeVolumeOnDestroy() {
//don't close volume
- TemporaryFileProvider.wipeAll()
+ RestrictedFileProvider.wipeAll()
}
override fun closeVolumeOnUserExit() {
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/AudioPlayer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/AudioPlayer.kt
index a58a339..d96d535 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/AudioPlayer.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/AudioPlayer.kt
@@ -1,20 +1,13 @@
package sushi.hardcore.droidfs.file_viewers
-import android.media.MediaPlayer
-import android.os.Handler
-import android.widget.SeekBar
-import androidx.core.content.ContextCompat
+import com.google.android.exoplayer2.SimpleExoPlayer
import kotlinx.android.synthetic.main.activity_audio_player.*
-import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
import java.io.File
-import java.io.IOException
-class AudioPlayer: FileViewerActivity(){
- private lateinit var player: MediaPlayer
- private var isPrepared = false
+class AudioPlayer: MediaPlayer(){
override fun viewFile() {
+ super.viewFile()
setContentView(R.layout.activity_audio_player)
val filename = File(filePath).name
val pos = filename.lastIndexOf('.')
@@ -23,65 +16,9 @@ class AudioPlayer: FileViewerActivity(){
} else {
filename
}
- val tmpFileUri = exportFile(filePath)
- tmpFileUri?.let {
- player = MediaPlayer()
- player.setDataSource(this, tmpFileUri)
- try {
- player.prepare()
- isPrepared = true
- } catch (e: IOException){
- ColoredAlertDialog(this)
- .setTitle(R.string.error)
- .setMessage(getString(R.string.media_player_prepare_failed))
- .setCancelable(false)
- .setPositiveButton(R.string.ok) { _, _ -> finish() }
- .show()
- }
- if (isPrepared){
- player.isLooping = true
- button_pause.setOnClickListener {
- if (player.isPlaying) {
- player.pause()
- button_pause.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.icon_play))
- } else {
- player.start()
- button_pause.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.icon_pause))
- }
- }
- button_stop.setOnClickListener { finish() }
- seekbar.max = player.duration / ConstValues.seek_bar_inc
- val handler = Handler()
- runOnUiThread(object : Runnable {
- override fun run() {
- if (isPrepared) {
- seekbar.progress = player.currentPosition / ConstValues.seek_bar_inc
- }
- handler.postDelayed(this, ConstValues.seek_bar_inc.toLong())
- }
- })
- seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (::player.isInitialized && fromUser) {
- player.seekTo(progress * ConstValues.seek_bar_inc)
- }
- }
- override fun onStartTrackingTouch(seekBar: SeekBar) {}
- override fun onStopTrackingTouch(seekBar: SeekBar) {}
- })
- player.start()
- }
- }
}
- override fun onDestroy() {
- super.onDestroy()
- if (::player.isInitialized) {
- if (player.isPlaying) {
- player.stop()
- }
- isPrepared = false
- player.release()
- }
+ override fun bindPlayer(player: SimpleExoPlayer) {
+ audio_controller.player = player
}
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt
index c5876d8..80f0b68 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt
@@ -1,21 +1,13 @@
package sushi.hardcore.droidfs.file_viewers
-import android.net.Uri
import android.os.Bundle
import android.view.View
-import android.view.WindowManager
-import androidx.preference.PreferenceManager
import sushi.hardcore.droidfs.BaseActivity
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.provider.TemporaryFileProvider
import sushi.hardcore.droidfs.util.GocryptfsVolume
-import sushi.hardcore.droidfs.util.Wiper
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
-import java.io.File
-import java.util.ArrayList
abstract class FileViewerActivity: BaseActivity() {
- private var cachedFiles: MutableList = ArrayList()
lateinit var gocryptfsVolume: GocryptfsVolume
lateinit var filePath: String
override fun onCreate(savedInstanceState: Bundle?) {
@@ -23,15 +15,17 @@ abstract class FileViewerActivity: BaseActivity() {
filePath = intent.getStringExtra("path")!!
val sessionID = intent.getIntExtra("sessionID", -1)
gocryptfsVolume = GocryptfsVolume(sessionID)
- toggleFullscreen()
+ hideSystemUi()
viewFile()
}
- open fun toggleFullscreen(){
- var uiOptions = window.decorView.systemUiVisibility
- //uiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
- uiOptions = uiOptions xor View.SYSTEM_UI_FLAG_FULLSCREEN
- uiOptions = uiOptions xor View.SYSTEM_UI_FLAG_IMMERSIVE
- window.decorView.systemUiVisibility = uiOptions
+ open fun hideSystemUi(){
+ window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LOW_PROFILE or
+ View.SYSTEM_UI_FLAG_FULLSCREEN/* or
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION*/
}
abstract fun viewFile()
fun loadWholeFile(path: String): ByteArray? {
@@ -43,10 +37,10 @@ abstract class FileViewerActivity: BaseActivity() {
val handleID = gocryptfsVolume.open_read_mode(path)
if (handleID != -1) {
var offset: Long = 0
- val io_buffer = ByteArray(GocryptfsVolume.DefaultBS)
+ val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
var length: Int
- while (gocryptfsVolume.read_file(handleID, offset, io_buffer).also { length = it } > 0){
- System.arraycopy(io_buffer, 0, fileBuff, offset.toInt(), length)
+ while (gocryptfsVolume.read_file(handleID, offset, ioBuffer).also { length = it } > 0){
+ System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)
offset += length.toLong()
}
gocryptfsVolume.close_file(handleID)
@@ -65,7 +59,7 @@ abstract class FileViewerActivity: BaseActivity() {
} catch (e: OutOfMemoryError){
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.outofmemoryerror_msg))
+ .setMessage(R.string.outofmemoryerror_msg)
.setCancelable(false)
.setPositiveButton(getString(R.string.ok)) { _, _ -> finish() }
.show()
@@ -81,30 +75,4 @@ abstract class FileViewerActivity: BaseActivity() {
}
return null
}
- fun exportFile(path: String): Uri? {
- val tmpFileUri = TemporaryFileProvider.createFile(this, File(path).name)
- cachedFiles.add(tmpFileUri)
- return if (gocryptfsVolume.export_file(this, path, tmpFileUri)) {
- tmpFileUri
- } else {
- ColoredAlertDialog(this)
- .setTitle(R.string.error)
- .setMessage(getString(R.string.export_failed, path))
- .setCancelable(false)
- .setPositiveButton(R.string.ok) { _, _ -> finish() }
- .show()
- null
- }
- }
-
- override fun onDestroy() {
- super.onDestroy()
- Thread{
- for (uri in cachedFiles) {
- if (Wiper.wipe(this, uri)){
- cachedFiles.remove(uri)
- }
- }
- }.start()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt
new file mode 100644
index 0000000..ff2cd61
--- /dev/null
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/GocryptfsDataSource.kt
@@ -0,0 +1,53 @@
+package sushi.hardcore.droidfs.file_viewers
+
+import android.net.Uri
+import com.google.android.exoplayer2.upstream.*
+import sushi.hardcore.droidfs.ConstValues
+import sushi.hardcore.droidfs.util.GocryptfsVolume
+
+class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private val filePath: String): DataSource {
+ private var handleID = -1
+ private var fileSize: Long = -1
+ private var fileOffset: Long = 0
+ override fun open(dataSpec: DataSpec?): Long {
+ dataSpec?.let {
+ fileOffset = dataSpec.position
+ }
+ handleID = gocryptfsVolume.open_read_mode(filePath)
+ fileSize = gocryptfsVolume.get_size(filePath)
+ return fileSize
+ }
+
+ override fun getUri(): Uri {
+ return ConstValues.fakeUri
+ }
+
+ override fun close() {
+ gocryptfsVolume.close_file(handleID)
+ }
+
+ override fun addTransferListener(transferListener: TransferListener?) {
+ //too lazy to implement this
+ }
+
+ override fun read(buffer: ByteArray, offset: Int, readLength: Int): Int {
+ if (fileOffset >= fileSize){
+ return -1
+ }
+ val tmpBuff = if (fileOffset+readLength > fileSize){
+ ByteArray((fileSize-fileOffset).toInt())
+ } else {
+ ByteArray(readLength)
+ }
+ val read = gocryptfsVolume.read_file(handleID, fileOffset, tmpBuff)
+ fileOffset += read
+ System.arraycopy(tmpBuff, 0, buffer, offset, read)
+ return read
+ }
+
+ class Factory(private val gocryptfsVolume: GocryptfsVolume, private val filePath: String): DataSource.Factory{
+ override fun createDataSource(): DataSource {
+ return GocryptfsDataSource(gocryptfsVolume, filePath)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt
new file mode 100644
index 0000000..54a6047
--- /dev/null
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt
@@ -0,0 +1,64 @@
+package sushi.hardcore.droidfs.file_viewers
+
+import androidx.appcompat.app.AlertDialog
+import com.google.android.exoplayer2.ExoPlaybackException
+import com.google.android.exoplayer2.Player
+import com.google.android.exoplayer2.SimpleExoPlayer
+import com.google.android.exoplayer2.source.LoopingMediaSource
+import com.google.android.exoplayer2.source.ProgressiveMediaSource
+import sushi.hardcore.droidfs.ConstValues
+import sushi.hardcore.droidfs.R
+import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
+
+abstract class MediaPlayer: FileViewerActivity() {
+ private lateinit var player: SimpleExoPlayer
+ private var currentWindow = 0
+ private var playbackPosition: Long = 0
+ private lateinit var errorDialog: AlertDialog.Builder
+
+ override fun viewFile() {
+ errorDialog = ColoredAlertDialog(this)
+ .setTitle(R.string.error)
+ .setMessage(R.string.playing_failed)
+ .setCancelable(false)
+ .setPositiveButton(R.string.ok) { _, _ -> finish() }
+ }
+
+ abstract fun bindPlayer(player: SimpleExoPlayer)
+
+ private fun initializePlayer(){
+ player = SimpleExoPlayer.Builder(this).build()
+ bindPlayer(player)
+ val dataSourceFactory = GocryptfsDataSource.Factory(gocryptfsVolume, filePath)
+ val mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(ConstValues.fakeUri)
+ player.seekTo(currentWindow, playbackPosition)
+ player.playWhenReady = true
+ player.addListener(object : Player.EventListener{
+ override fun onPlayerError(error: ExoPlaybackException) {
+ if (error.type == ExoPlaybackException.TYPE_SOURCE){
+ errorDialog.show()
+ }
+ }
+ })
+ player.prepare(LoopingMediaSource(mediaSource), false, false)
+ }
+
+ private fun releasePlayer(){
+ if (::player.isInitialized) {
+ playbackPosition = player.currentPosition
+ currentWindow = player.currentWindowIndex
+ player.release()
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ hideSystemUi()
+ initializePlayer()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ releasePlayer()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt
index 5f45c6f..191617a 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt
@@ -21,8 +21,8 @@ class TextEditor: FileViewerActivity() {
private lateinit var titleText: TextView
private var changedSinceLastSave = false
private var wordWrap = true
- override fun toggleFullscreen() {
- //don't toggle fullscreen
+ override fun hideSystemUi() {
+ //don't hide system ui
}
override fun viewFile() {
loadWholeFile(filePath)?.let {
@@ -32,7 +32,7 @@ class TextEditor: FileViewerActivity() {
} catch (e: OutOfMemoryError){
ColoredAlertDialog(this)
.setTitle(R.string.error)
- .setMessage(getString(R.string.outofmemoryerror_msg))
+ .setMessage(R.string.outofmemoryerror_msg)
.setCancelable(false)
.setPositiveButton(getString(R.string.ok)) { _, _ -> finish() }
.show()
@@ -100,7 +100,7 @@ class TextEditor: FileViewerActivity() {
if (changedSinceLastSave){
ColoredAlertDialog(this)
.setTitle(R.string.warning)
- .setMessage(getString(R.string.ask_save))
+ .setMessage(R.string.ask_save)
.setPositiveButton(getString(R.string.save)) { _, _ ->
if (save()){
finish()
diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/VideoPlayer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/VideoPlayer.kt
index 7afa081..69f9240 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/VideoPlayer.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/VideoPlayer.kt
@@ -1,27 +1,16 @@
package sushi.hardcore.droidfs.file_viewers
-import android.widget.MediaController
+import com.google.android.exoplayer2.SimpleExoPlayer
import kotlinx.android.synthetic.main.activity_video_player.*
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
-class VideoPlayer: FileViewerActivity() {
+class VideoPlayer: MediaPlayer() {
override fun viewFile() {
- val mc = MediaController(this)
+ super.viewFile()
setContentView(R.layout.activity_video_player)
- mc.setAnchorView(video_player)
- video_player.setOnErrorListener { _, _, _ ->
- ColoredAlertDialog(this)
- .setTitle(R.string.error)
- .setMessage(getString(R.string.video_play_failed))
- .setCancelable(false)
- .setPositiveButton(R.string.ok) { _, _ -> finish() }
- .show()
- true
- }
- val tmpFileUri = exportFile(filePath)
- video_player.setVideoURI(tmpFileUri)
- video_player.setMediaController(mc)
- video_player.start()
+ }
+
+ override fun bindPlayer(player: SimpleExoPlayer) {
+ video_player.player = player
}
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt b/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt
new file mode 100644
index 0000000..7cbe02d
--- /dev/null
+++ b/app/src/main/java/sushi/hardcore/droidfs/provider/RestrictedFileProvider.kt
@@ -0,0 +1,114 @@
+package sushi.hardcore.droidfs.provider
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.database.Cursor
+import android.database.MatrixCursor
+import android.net.Uri
+import android.os.ParcelFileDescriptor
+import android.provider.MediaStore
+import sushi.hardcore.droidfs.BuildConfig
+import sushi.hardcore.droidfs.util.Wiper
+import java.io.File
+import java.util.*
+import java.util.regex.Pattern
+
+class RestrictedFileProvider: ContentProvider() {
+ companion object {
+ private const val AUTHORITY = BuildConfig.APPLICATION_ID + ".temporary_provider"
+ private val CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY")
+ const val TEMPORARY_FILES_DIR_NAME = "temp"
+ private val UUID_PATTERN = Pattern.compile("[a-fA-F0-9-]+")
+
+ private lateinit var tempFilesDir: File
+ private val tempFiles = mutableMapOf()
+
+ class TemporaryFile(val fileName: String, val file: File)
+
+ fun newFile(fileName: String): Uri? {
+ val uuid = UUID.randomUUID().toString()
+ val file = File(tempFilesDir, uuid)
+ return if (file.createNewFile()){
+ tempFiles[uuid] = TemporaryFile(fileName, file)
+ Uri.withAppendedPath(CONTENT_URI, uuid)
+ } else {
+ null
+ }
+ }
+
+ fun wipeAll() {
+ tempFilesDir.listFiles()?.let{
+ for (file in it) {
+ Wiper.wipe(file)
+ }
+ }
+ }
+
+ private fun getFileFromUri(uri: Uri): TemporaryFile? {
+ val uuid = uri.lastPathSegment
+ if (uuid != null) {
+ if (UUID_PATTERN.matcher(uuid).matches()) {
+ return tempFiles[uuid]
+ }
+ }
+ return null
+ }
+ }
+
+ override fun onCreate(): Boolean {
+ context?.let {
+ tempFilesDir = File(it.cacheDir, TEMPORARY_FILES_DIR_NAME)
+ return tempFilesDir.mkdirs()
+ }
+ return false
+ }
+
+ override fun insert(uri: Uri, values: ContentValues?): Uri? {
+ throw RuntimeException("Operation not supported")
+ }
+
+ override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int {
+ throw RuntimeException("Operation not supported")
+ }
+
+ override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? {
+ val temporaryFile = getFileFromUri(uri)
+ if (temporaryFile != null) {
+ val cursor = MatrixCursor(
+ arrayOf(
+ MediaStore.MediaColumns.DISPLAY_NAME,
+ MediaStore.MediaColumns.SIZE
+ )
+ )
+ cursor.newRow()
+ .add(temporaryFile.fileName)
+ .add(temporaryFile.file.length())
+ return cursor
+ }
+ return null
+ }
+
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
+ val temporaryFile = getFileFromUri(uri)
+ if (temporaryFile != null) {
+ Wiper.wipe(temporaryFile.file)
+ tempFiles.remove(uri.lastPathSegment)
+ }
+ return 1
+ }
+
+ override fun getType(uri: Uri): String {
+ return "application/octet-stream"
+ }
+
+ override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
+ if (("w" in mode && callingPackage == BuildConfig.APPLICATION_ID) || "w" !in mode) {
+ getFileFromUri(uri)?.let{
+ return ParcelFileDescriptor.open(it.file, ParcelFileDescriptor.parseMode(mode))
+ }
+ } else {
+ throw SecurityException("Read-only access")
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/provider/TemporaryFileProvider.java b/app/src/main/java/sushi/hardcore/droidfs/provider/TemporaryFileProvider.java
deleted file mode 100644
index 94a173d..0000000
--- a/app/src/main/java/sushi/hardcore/droidfs/provider/TemporaryFileProvider.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package sushi.hardcore.droidfs.provider;
-
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import android.annotation.SuppressLint;
-import android.app.Application;
-import android.content.ClipDescription;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.net.Uri;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.provider.MediaStore;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import sushi.hardcore.droidfs.BuildConfig;
-
-import sushi.hardcore.droidfs.util.DatabaseUtil;
-import sushi.hardcore.droidfs.util.Wiper;
-
-/**
- * Borrowed from OpenKeyChain
- * I removed the scheduled cleanup because it requires unwanted permissions and doesn't work very well.
- * But don't panic ! The "clear_cache" function from ExternalProvider do the same job when needed.
- **/
-
-
-/**
- * TemporaryStorageProvider stores decrypted files inside the app's cache directory previously to
- * sharing them with other applications.
- *
- * Security:
- * - It is writable by OpenKeychain only (see Manifest), but exported for reading files
- * - It uses UUIDs as identifiers which makes predicting files from outside impossible
- * - Querying a number of files is not allowed, only querying single files
- * -> You can only open a file if you know the Uri containing the precise UUID, this Uri is only
- * revealed when the user shares a decrypted file with another app.
- *
- * Why is support lib's FileProvider not used?
- * Because granting Uri permissions temporarily does not work correctly. See
- * - https://code.google.com/p/android/issues/detail?id=76683
- * - https://github.com/nmr8acme/FileProvider-permission-bug
- * - http://stackoverflow.com/q/24467696
- * - http://stackoverflow.com/q/18249007
- * - Comments at http://www.blogc.at/2014/03/23/share-private-files-with-other-apps-fileprovider/
- */
-public class TemporaryFileProvider extends ContentProvider {
-
- private static final int TEMPFILE_TTL = 10 * 60 * 1000; // 10 minutes
-
- private static final String DB_NAME = "tempstorage.db";
- private static final String TABLE_FILES = "files";
- public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".tempstorage";
- public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
- private static final int DB_VERSION = 3;
-
- interface TemporaryFileColumns {
- String COLUMN_UUID = "id";
- String COLUMN_NAME = "name";
- String COLUMN_TIME = "time";
- String COLUMN_TYPE = "mimetype";
- }
-
- private static final String TEMP_FILES_DIR = "temp";
- private static File tempFilesDir;
-
- private static Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9-]+");
-
- public static void wipeAll(){
- for (File f: tempFilesDir.listFiles()){
- Wiper.wipe(f);
- }
- }
-
- public static Uri createFile(Context context, String targetName, String mimeType) {
- ContentResolver contentResolver = context.getContentResolver();
-
- ContentValues contentValues = new ContentValues();
- contentValues.put(TemporaryFileColumns.COLUMN_NAME, targetName);
- contentValues.put(TemporaryFileColumns.COLUMN_TYPE, mimeType);
- contentValues.put(TemporaryFileColumns.COLUMN_TIME, System.currentTimeMillis());
- Uri resultUri = contentResolver.insert(CONTENT_URI, contentValues);
-
- //scheduleCleanupAfterTtl(context);
- return resultUri;
- }
-
- public static Uri createFile(Context context, String targetName) {
- return createFile(context, targetName, null);
- }
-
- public static Uri createFile(Context context) {
- ContentValues contentValues = new ContentValues();
- return context.getContentResolver().insert(CONTENT_URI, contentValues);
- }
-
- public static int setName(Context context, Uri uri, String name) {
- ContentValues values = new ContentValues();
- values.put(TemporaryFileColumns.COLUMN_NAME, name);
- return context.getContentResolver().update(uri, values, null, null);
- }
-
- public static int setMimeType(Context context, Uri uri, String mimetype) {
- ContentValues values = new ContentValues();
- values.put(TemporaryFileColumns.COLUMN_TYPE, mimetype);
- return context.getContentResolver().update(uri, values, null, null);
- }
-
- private static class TemporaryStorageDatabase extends SQLiteOpenHelper {
-
- public TemporaryStorageDatabase(Context context) {
- super(context, DB_NAME, null, DB_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" +
- TemporaryFileColumns.COLUMN_UUID + " TEXT PRIMARY KEY, " +
- TemporaryFileColumns.COLUMN_NAME + " TEXT, " +
- TemporaryFileColumns.COLUMN_TYPE + " TEXT, " +
- TemporaryFileColumns.COLUMN_TIME + " INTEGER" +
- ");");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
- switch (oldVersion) {
- case 1:
- db.execSQL("DROP TABLE IF EXISTS files");
- db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" +
- TemporaryFileColumns.COLUMN_UUID + " TEXT PRIMARY KEY, " +
- TemporaryFileColumns.COLUMN_NAME + " TEXT, " +
- TemporaryFileColumns.COLUMN_TIME + " INTEGER" +
- ");");
- case 2:
- db.execSQL("ALTER TABLE files ADD COLUMN " + TemporaryFileColumns.COLUMN_TYPE + " TEXT");
- }
- }
- }
-
- private static TemporaryStorageDatabase db;
-
- private File getFile(Uri uri) throws FileNotFoundException {
- try {
- return getFile(uri.getLastPathSegment());
- } catch (NumberFormatException e) {
- throw new FileNotFoundException();
- }
- }
-
- private File getFile(String id) {
- Matcher m = UUID_PATTERN.matcher(id);
- if (!m.matches()) {
- throw new SecurityException("Can only open temporary files with UUIDs!");
- }
-
- return new File(tempFilesDir, id);
- }
-
- @Override
- public boolean onCreate() {
- db = new TemporaryStorageDatabase(getContext());
- tempFilesDir = new File(getContext().getCacheDir(), TEMP_FILES_DIR);
- return tempFilesDir.mkdirs();
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- if (uri.getLastPathSegment() == null) {
- throw new SecurityException("Listing temporary files is not allowed, only querying single files.");
- }
-
- File file;
- try {
- file = getFile(uri);
- } catch (FileNotFoundException e) {
- return null;
- }
-
- Cursor fileName = db.getReadableDatabase().query(TABLE_FILES,
- new String[]{TemporaryFileColumns.COLUMN_NAME},
- TemporaryFileColumns.COLUMN_UUID + "=?",
- new String[]{uri.getLastPathSegment()}, null, null, null);
- if (fileName != null) {
- if (fileName.moveToNext()) {
- MatrixCursor cursor = new MatrixCursor(new String[]{
- MediaStore.MediaColumns.DISPLAY_NAME,
- MediaStore.MediaColumns.SIZE,
- MediaStore.MediaColumns.DATA,
- });
- cursor.newRow()
- .add(fileName.getString(0))
- .add(file.length())
- .add(file.getAbsolutePath());
- fileName.close();
- return cursor;
- }
- fileName.close();
- }
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- Cursor cursor = db.getReadableDatabase().query(TABLE_FILES,
- new String[]{TemporaryFileColumns.COLUMN_TYPE},
- TemporaryFileColumns.COLUMN_UUID + "=?",
- new String[]{uri.getLastPathSegment()}, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToNext()) {
- if (!cursor.isNull(0)) {
- return cursor.getString(0);
- }
- }
- } finally {
- cursor.close();
- }
- }
- return "application/octet-stream";
- }
-
- @Override
- public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
- String type = getType(uri);
- if (ClipDescription.compareMimeTypes(type, mimeTypeFilter)) {
- return new String[]{type};
- }
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- String uuid = UUID.randomUUID().toString();
- values.put(TemporaryFileColumns.COLUMN_UUID, uuid);
- int insert = (int) db.getWritableDatabase().insert(TABLE_FILES, null, values);
- if (insert == -1) {
- return null;
- }
- try {
- getFile(uuid).createNewFile();
- } catch (IOException e) {
- return null;
- }
- return Uri.withAppendedPath(CONTENT_URI, uuid);
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- if (uri == null) {
- return 0;
- }
-
- String fileUuidFromUri = uri.getLastPathSegment();
- if (fileUuidFromUri != null) {
- selection = DatabaseUtil.concatenateWhere(selection, TemporaryFileColumns.COLUMN_UUID + "=?");
- selectionArgs = DatabaseUtil.appendSelectionArgs(selectionArgs, new String[]{ fileUuidFromUri });
- }
-
- Cursor files = db.getReadableDatabase().query(TABLE_FILES, new String[]{TemporaryFileColumns.COLUMN_UUID}, selection,
- selectionArgs, null, null, null);
- if (files != null) {
- while (files.moveToNext()) {
- getFile(files.getString(0)).delete();
- }
- files.close();
- return db.getWritableDatabase().delete(TABLE_FILES, selection, selectionArgs);
- }
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- if (values.size() != 1) {
- throw new UnsupportedOperationException("Update supported only for one field at a time!");
- }
- if (!values.containsKey(TemporaryFileColumns.COLUMN_NAME) && !values.containsKey(TemporaryFileColumns.COLUMN_TYPE)) {
- throw new UnsupportedOperationException("Update supported only for name and type field!");
- }
- if (selection != null || selectionArgs != null) {
- throw new UnsupportedOperationException("Update supported only for plain uri!");
- }
- return db.getWritableDatabase().update(TABLE_FILES, values,
- TemporaryFileColumns.COLUMN_UUID + " = ?", new String[]{uri.getLastPathSegment()});
- }
-
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- return openFileHelper(uri, mode);
- }
-}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/DatabaseUtil.java b/app/src/main/java/sushi/hardcore/droidfs/util/DatabaseUtil.java
deleted file mode 100644
index 73cc501..0000000
--- a/app/src/main/java/sushi/hardcore/droidfs/util/DatabaseUtil.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2017 Schürmann & Breitmoser GbR
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package sushi.hardcore.droidfs.util;
-
-
-import androidx.sqlite.db.SupportSQLiteDatabase;
-import android.database.Cursor;
-import android.text.TextUtils;
-
-
-/**
- * Borrowed from OpenKeyChain
- */
-
-
-/**
- * Shamelessly copied from android.database.DatabaseUtils
- */
-public class DatabaseUtil {
- /**
- * Concatenates two SQL WHERE clauses, handling empty or null values.
- */
- public static String concatenateWhere(String a, String b) {
- if (TextUtils.isEmpty(a)) {
- return b;
- }
- if (TextUtils.isEmpty(b)) {
- return a;
- }
-
- return "(" + a + ") AND (" + b + ")";
- }
-
- /**
- * Appends one set of selection args to another. This is useful when adding a selection
- * argument to a user provided set.
- */
- public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) {
- if (originalValues == null || originalValues.length == 0) {
- return newValues;
- }
- String[] result = new String[originalValues.length + newValues.length ];
- System.arraycopy(originalValues, 0, result, 0, originalValues.length);
- System.arraycopy(newValues, 0, result, originalValues.length, newValues.length);
- return result;
- }
-
- public static void explainQuery(SupportSQLiteDatabase db, String sql) {
- Cursor explainCursor = db.query("EXPLAIN QUERY PLAN " + sql, new String[0]);
-
- // this is a debugging feature, we can be a little careless
- explainCursor.moveToFirst();
-
- StringBuilder line = new StringBuilder();
- for (int i = 0; i < explainCursor.getColumnCount(); i++) {
- line.append(explainCursor.getColumnName(i)).append(", ");
- }
-
- while (!explainCursor.isAfterLast()) {
- line = new StringBuilder();
- for (int i = 0; i < explainCursor.getColumnCount(); i++) {
- line.append(explainCursor.getString(i)).append(", ");
- }
- explainCursor.moveToNext();
- }
-
- explainCursor.close();
- }
-}
diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt b/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt
index e1da99c..fea972b 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/util/ExternalProvider.kt
@@ -3,9 +3,8 @@ package sushi.hardcore.droidfs.util
import android.content.Context
import android.content.Intent
import android.net.Uri
-import androidx.appcompat.app.AlertDialog
import sushi.hardcore.droidfs.R
-import sushi.hardcore.droidfs.provider.TemporaryFileProvider
+import sushi.hardcore.droidfs.provider.RestrictedFileProvider
import sushi.hardcore.droidfs.widgets.ColoredAlertDialog
import java.io.File
import java.net.URLConnection
@@ -13,51 +12,53 @@ import java.util.*
object ExternalProvider {
private const val content_type_all = "*/*"
- private var cached_files: MutableList = ArrayList()
- private fun get_content_type(filename: String, previous_content_type: String?): String? {
+ private var storedFiles: MutableList = ArrayList()
+ private fun getContentType(filename: String, previous_content_type: String?): String? {
if (content_type_all != previous_content_type) {
- var content_type = URLConnection.guessContentTypeFromName(filename)
- if (content_type == null) {
- content_type = content_type_all
+ var contentType = URLConnection.guessContentTypeFromName(filename)
+ if (contentType == null) {
+ contentType = content_type_all
}
if (previous_content_type == null) {
- return content_type
- } else if (previous_content_type != content_type) {
+ return contentType
+ } else if (previous_content_type != contentType) {
return content_type_all
}
}
return previous_content_type
}
- private fun export_file(context: Context, gocryptfsVolume: GocryptfsVolume, file_path: String, previous_content_type: String?): Export_file_result {
- val filename = File(file_path).name
- val tmp_file_uri = TemporaryFileProvider.createFile(context, filename)
- cached_files.add(tmp_file_uri)
- if (gocryptfsVolume.export_file(context, file_path, tmp_file_uri)) {
- return Export_file_result(tmp_file_uri, get_content_type(filename, previous_content_type))
+ private fun exportFile(context: Context, gocryptfsVolume: GocryptfsVolume, file_path: String, previous_content_type: String?): Pair {
+ val fileName = File(file_path).name
+ val tmpFileUri = RestrictedFileProvider.newFile(fileName)
+ if (tmpFileUri != null){
+ storedFiles.add(tmpFileUri)
+ if (gocryptfsVolume.export_file(context, file_path, tmpFileUri)) {
+ return Pair(tmpFileUri, getContentType(fileName, previous_content_type))
+ }
}
ColoredAlertDialog(context)
.setTitle(R.string.error)
.setMessage(context.getString(R.string.export_failed, file_path))
.setPositiveButton(R.string.ok, null)
.show()
- return Export_file_result(null, null)
+ return Pair(null, null)
}
fun share(context: Context, gocryptfsVolume: GocryptfsVolume, file_paths: List) {
- var content_type: String? = null
+ var contentType: String? = null
val uris = ArrayList()
for (path in file_paths) {
- val result = export_file(context, gocryptfsVolume, path, content_type)
- content_type = if (result.uri == null) {
- return
+ val result = exportFile(context, gocryptfsVolume, path, contentType)
+ contentType = if (result.first != null) {
+ uris.add(result.first!!)
+ result.second
} else {
- uris.add(result.uri!!)
- result.content_type
+ return
}
}
val shareIntent = Intent()
- shareIntent.type = content_type
+ shareIntent.type = contentType
if (uris.size == 1) {
shareIntent.action = Intent.ACTION_SEND
shareIntent.putExtra(Intent.EXTRA_STREAM, uris[0])
@@ -69,24 +70,22 @@ object ExternalProvider {
}
fun open(context: Context, gocryptfsVolume: GocryptfsVolume, file_path: String) {
- val result = export_file(context, gocryptfsVolume, file_path, null)
- result.uri?.let {
+ val result = exportFile(context, gocryptfsVolume, file_path, null)
+ result.first?.let {
val openIntent = Intent()
openIntent.action = Intent.ACTION_VIEW
- openIntent.setDataAndType(result.uri, result.content_type)
+ openIntent.setDataAndType(result.first, result.second)
context.startActivity(openIntent)
}
}
- fun clear_cache(context: Context) {
+ fun removeFiles(context: Context) {
Thread{
- for (uri in cached_files) {
+ for (uri in storedFiles) {
if (Wiper.wipe(context, uri)){
- cached_files.remove(uri)
+ storedFiles.remove(uri)
}
}
}.start()
}
-
- private class Export_file_result(var uri: Uri?, var content_type: String?)
}
\ No newline at end of file
diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt b/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt
index d8e6271..13f8a7a 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt
+++ b/app/src/main/java/sushi/hardcore/droidfs/util/GocryptfsVolume.kt
@@ -26,7 +26,6 @@ class GocryptfsVolume(var sessionID: Int) {
const val KeyLen = 32
const val ScryptDefaultLogN = 16
const val DefaultBS = 4096
- //external fun scrypt_hash(data: CharArray, logN: Int): ByteArray
external fun create_volume(root_cipher_dir: String, password: CharArray, logN: Int, creator: String): Boolean
external fun init(root_cipher_dir: String, password: CharArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int
external fun change_password(root_cipher_dir: String, old_password: CharArray?, givenHash: ByteArray?, new_password: CharArray, returnedHash: ByteArray?): Boolean
diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/FilesUtils.java b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java
similarity index 87%
rename from app/src/main/java/sushi/hardcore/droidfs/util/FilesUtils.java
rename to app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java
index ffaa6c1..8647394 100644
--- a/app/src/main/java/sushi/hardcore/droidfs/util/FilesUtils.java
+++ b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.java
@@ -1,42 +1,18 @@
package sushi.hardcore.droidfs.util;
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
-import android.provider.MediaStore;
import android.provider.OpenableColumns;
-
import androidx.annotation.Nullable;
-
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
-import java.util.ArrayList;
-public final class FilesUtils {
-
- /*public static ArrayList recursive_get_files(File root_path){
- ArrayList results_files = new ArrayList<>();
- final File[] elements = root_path.listFiles();
- if (elements != null){
- for (File item : elements){
- if (item.isDirectory()){
- results_files.addAll(recursive_get_files(item));
- } else if (item.isFile()){
- results_files.add(item);
- }
- }
- }
- return results_files;
- }*/
+public class PathUtils {
public static String get_parent_path(String path){
if (path.endsWith("/")){
diff --git a/app/src/main/res/layout/activity_audio_player.xml b/app/src/main/res/layout/activity_audio_player.xml
index ccee3f8..6bd7538 100644
--- a/app/src/main/res/layout/activity_audio_player.xml
+++ b/app/src/main/res/layout/activity_audio_player.xml
@@ -2,6 +2,7 @@
@@ -14,33 +15,11 @@
android:textSize="18sp"
android:padding="10dp"/>
-
-
-
-
-
-
-
-
-
+ app:controller_layout_id="@layout/exo_custom_playback_control"
+ app:show_timeout="0"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_video_player.xml b/app/src/main/res/layout/activity_video_player.xml
index 60a3e52..43c399b 100644
--- a/app/src/main/res/layout/activity_video_player.xml
+++ b/app/src/main/res/layout/activity_video_player.xml
@@ -2,13 +2,15 @@
-
+ android:layout_gravity="center"
+ app:controller_layout_id="@layout/exo_custom_playback_control"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/exo_custom_playback_control.xml b/app/src/main/res/layout/exo_custom_playback_control.xml
new file mode 100644
index 0000000..cb50f5a
--- /dev/null
+++ b/app/src/main/res/layout/exo_custom_playback_control.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d242e2b..c1990f6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -109,7 +109,7 @@
Video
Audio
Failed to initialize the media player.
- Failed to play this video.
+ Failed to play this file.
Text
Save failed
File saved !
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 4230a74..72d4401 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -2,11 +2,8 @@