forked from hardcoresushi/DroidFS
Update dependencies & Fix some bugs
This commit is contained in:
parent
11cc15536f
commit
8f5afca823
10
BUILD.md
10
BUILD.md
@ -45,16 +45,16 @@ $ git clone --depth=1 https://git.ffmpeg.org/ffmpeg.git
|
|||||||
If you want Gocryptfs support, you need to download OpenSSL:
|
If you want Gocryptfs support, you need to download OpenSSL:
|
||||||
```
|
```
|
||||||
$ cd ../libgocryptfs
|
$ cd ../libgocryptfs
|
||||||
$ wget https://www.openssl.org/source/openssl-1.1.1p.tar.gz
|
$ wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz
|
||||||
```
|
```
|
||||||
Verify OpenSSL signature:
|
Verify OpenSSL signature:
|
||||||
```
|
```
|
||||||
$ wget https://www.openssl.org/source/openssl-1.1.1p.tar.gz.asc
|
$ wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz.asc
|
||||||
$ gpg --verify openssl-1.1.1p.tar.gz.asc openssl-1.1.1p.tar.gz
|
$ gpg --verify openssl-1.1.1q.tar.gz.asc openssl-1.1.1q.tar.gz
|
||||||
```
|
```
|
||||||
Continue **ONLY** if the signature is **VALID**.
|
Continue **ONLY** if the signature is **VALID**.
|
||||||
```
|
```
|
||||||
$ tar -xzf openssl-1.1.1p.tar.gz
|
$ tar -xzf openssl-1.1.1q.tar.gz
|
||||||
```
|
```
|
||||||
If you want CryFS support, initialize libcryfs:
|
If you want CryFS support, initialize libcryfs:
|
||||||
```
|
```
|
||||||
@ -76,7 +76,7 @@ $ ./build.sh ffmpeg
|
|||||||
This step is only required if you want Gocryptfs support.
|
This step is only required if you want Gocryptfs support.
|
||||||
```
|
```
|
||||||
$ cd app/libgocryptfs
|
$ cd app/libgocryptfs
|
||||||
$ OPENSSL_PATH="./openssl-1.1.1p" ./build.sh
|
$ OPENSSL_PATH="./openssl-1.1.1q" ./build.sh
|
||||||
```
|
```
|
||||||
## Compile APKs
|
## Compile APKs
|
||||||
Gradle build libgocryptfs and libcryfs by default.
|
Gradle build libgocryptfs and libcryfs by default.
|
||||||
|
@ -14,9 +14,10 @@ if (hasProperty("disableGocryptfs")) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 33
|
||||||
buildToolsVersion "31"
|
buildToolsVersion "33.0.0"
|
||||||
ndkVersion "23.1.7779620"
|
ndkVersion "25.1.8937393"
|
||||||
|
namespace "sushi.hardcore.droidfs"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
@ -86,24 +87,25 @@ dependencies {
|
|||||||
implementation project(":libpdfviewer:app")
|
implementation project(":libpdfviewer:app")
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation "androidx.appcompat:appcompat:1.4.1"
|
implementation "androidx.appcompat:appcompat:1.5.1"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
|
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
|
||||||
|
|
||||||
implementation "androidx.sqlite:sqlite-ktx:2.2.0"
|
implementation "androidx.sqlite:sqlite-ktx:2.2.0"
|
||||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.6.1'
|
||||||
implementation "com.github.bumptech.glide:glide:4.12.0"
|
implementation "com.github.bumptech.glide:glide:4.13.2"
|
||||||
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha04"
|
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05"
|
||||||
|
|
||||||
def exoplayer_version = "2.17.1"
|
def exoplayer_version = "2.18.1"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
||||||
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
||||||
|
|
||||||
implementation "androidx.concurrent:concurrent-futures:1.1.0"
|
implementation "androidx.concurrent:concurrent-futures:1.1.0"
|
||||||
|
|
||||||
def camerax_version = "1.1.0-beta03"
|
def camerax_version = "1.2.0-beta02"
|
||||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||||
implementation "androidx.camera:camera-view:$camerax_version"
|
implementation "androidx.camera:camera-view:$camerax_version"
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c5be03ad3abea3aef5b0fcc5aa3af8cba2befdd1
|
Subproject commit c0600c262480f6fb3d31e2b500ba04714f1ff342
|
@ -1 +1 @@
|
|||||||
Subproject commit e6e4c201dbf3834de1a49a8b67b4b54239d24249
|
Subproject commit 27232cbdb7257be13a12545b71fa32ee193cb11b
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="sushi.hardcore.droidfs"
|
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<permission
|
<permission
|
||||||
@ -51,7 +50,7 @@
|
|||||||
<activity android:name=".explorers.ExplorerActivityDrop"/>
|
<activity android:name=".explorers.ExplorerActivityDrop"/>
|
||||||
<activity android:name=".file_viewers.ImageViewer" android:configChanges="screenSize|orientation" /> <!-- don't reload content on configuration change -->
|
<activity android:name=".file_viewers.ImageViewer" android:configChanges="screenSize|orientation" /> <!-- don't reload content on configuration change -->
|
||||||
<activity android:name=".file_viewers.VideoPlayer" android:configChanges="screenSize|orientation" />
|
<activity android:name=".file_viewers.VideoPlayer" android:configChanges="screenSize|orientation" />
|
||||||
<activity android:name=".file_viewers.PdfViewer" android:configChanges="screenSize|orientation" />
|
<activity android:name=".file_viewers.PdfViewer" android:configChanges="screenSize|orientation" android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".file_viewers.AudioPlayer" android:configChanges="screenSize|orientation" />
|
<activity android:name=".file_viewers.AudioPlayer" android:configChanges="screenSize|orientation" />
|
||||||
<activity android:name=".file_viewers.TextEditor" android:configChanges="screenSize|orientation" />
|
<activity android:name=".file_viewers.TextEditor" android:configChanges="screenSize|orientation" />
|
||||||
<activity android:name=".CameraActivity" android:screenOrientation="nosensor" />
|
<activity android:name=".CameraActivity" android:screenOrientation="nosensor" />
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
package sushi.hardcore.droidfs
|
package sushi.hardcore.droidfs
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
|
||||||
open class BaseActivity: AppCompatActivity() {
|
open class BaseActivity: AppCompatActivity() {
|
||||||
protected lateinit var sharedPrefs: SharedPreferences
|
protected lateinit var sharedPrefs: SharedPreferences
|
||||||
|
protected var applyCustomTheme: Boolean = true
|
||||||
lateinit var themeValue: String
|
lateinit var themeValue: String
|
||||||
private var shouldCheckTheme = true
|
private var shouldCheckTheme = true
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
|
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
if (shouldCheckTheme) {
|
if (shouldCheckTheme && applyCustomTheme) {
|
||||||
themeValue = sharedPrefs.getString("theme", ConstValues.DEFAULT_THEME_VALUE)!!
|
themeValue = sharedPrefs.getString("theme", ConstValues.DEFAULT_THEME_VALUE)!!
|
||||||
when (themeValue) {
|
when (themeValue) {
|
||||||
"black_green" -> setTheme(R.style.BlackGreen)
|
"black_green" -> setTheme(R.style.BlackGreen)
|
||||||
@ -28,8 +32,6 @@ open class BaseActivity: AppCompatActivity() {
|
|||||||
"dark_purple" -> setTheme(R.style.DarkPurple)
|
"dark_purple" -> setTheme(R.style.DarkPurple)
|
||||||
"black_purple" -> setTheme(R.style.BlackPurple)
|
"black_purple" -> setTheme(R.style.BlackPurple)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
shouldCheckTheme = true
|
|
||||||
}
|
}
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if (!sharedPrefs.getBoolean("usf_screenshot", false)){
|
if (!sharedPrefs.getBoolean("usf_screenshot", false)){
|
||||||
@ -37,12 +39,7 @@ open class BaseActivity: AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
// must not be called if applyCustomTheme is false
|
||||||
super.onStart()
|
|
||||||
val newThemeValue = sharedPrefs.getString("theme", "dark_green")!!
|
|
||||||
onThemeChanged(newThemeValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onThemeChanged(newThemeValue: String) {
|
fun onThemeChanged(newThemeValue: String) {
|
||||||
if (newThemeValue != themeValue) {
|
if (newThemeValue != themeValue) {
|
||||||
themeValue = newThemeValue
|
themeValue = newThemeValue
|
||||||
@ -50,4 +47,13 @@ open class BaseActivity: AppCompatActivity() {
|
|||||||
recreate()
|
recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T: Parcelable> getParcelableExtra(intent: Intent, name: String): T? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
intent.getParcelableExtra(name, T::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("Deprecation")
|
||||||
|
intent.getParcelableExtra(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ import android.view.animation.RotateAnimation
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.camera.camera2.interop.Camera2CameraInfo
|
import androidx.camera.camera2.interop.Camera2CameraInfo
|
||||||
import androidx.camera.core.*
|
import androidx.camera.core.*
|
||||||
@ -94,7 +95,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
binding = ActivityCameraBinding.inflate(layoutInflater)
|
binding = ActivityCameraBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
encryptedVolume = intent.getParcelableExtra("volume")!!
|
encryptedVolume = getParcelableExtra(intent, "volume")!!
|
||||||
outputDirectory = intent.getStringExtra("path")!!
|
outputDirectory = intent.getStringExtra("path")!!
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
@ -278,6 +279,11 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
isFinishingIntentionally = true
|
||||||
|
isEnabled = false
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
@ -506,11 +512,6 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
sensorOrientationListener.addListener(this)
|
sensorOrientationListener.addListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
super.onBackPressed()
|
|
||||||
isFinishingIntentionally = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOrientationChange(newOrientation: Int) {
|
override fun onOrientationChange(newOrientation: Int) {
|
||||||
val realOrientation = when (newOrientation) {
|
val realOrientation = when (newOrientation) {
|
||||||
Surface.ROTATION_0 -> 0f
|
Surface.ROTATION_0 -> 0f
|
||||||
|
@ -27,7 +27,7 @@ class ChangePasswordActivity: BaseActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
volume = intent.getParcelableExtra("volume")!!
|
volume = getParcelableExtra(intent, "volume")!!
|
||||||
binding = ActivityChangePasswordBinding.inflate(layoutInflater)
|
binding = ActivityChangePasswordBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
title = getString(R.string.change_password)
|
title = getString(R.string.change_password)
|
||||||
|
@ -15,6 +15,7 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -134,6 +135,16 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
|
|||||||
unsetDefaultVolume()
|
unsetDefaultVolume()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
if (volumeAdapter.selectedItems.isNotEmpty()) {
|
||||||
|
unselectAll()
|
||||||
|
} else {
|
||||||
|
if (pickMode)
|
||||||
|
shouldCloseVolume = false
|
||||||
|
isEnabled = false
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
Intent(this, FileOperationService::class.java).also {
|
Intent(this, FileOperationService::class.java).also {
|
||||||
bindService(it, object : ServiceConnection {
|
bindService(it, object : ServiceConnection {
|
||||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||||
@ -146,6 +157,9 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
// refresh theme if changed in SettingsActivity
|
||||||
|
val newThemeValue = sharedPrefs.getString("theme", ConstValues.DEFAULT_THEME_VALUE)!!
|
||||||
|
onThemeChanged(newThemeValue)
|
||||||
// refresh this in case another instance of MainActivity changes its value
|
// refresh this in case another instance of MainActivity changes its value
|
||||||
defaultVolumeName = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null)
|
defaultVolumeName = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null)
|
||||||
}
|
}
|
||||||
@ -619,7 +633,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
|
|||||||
explorerIntent.putExtras(intent.extras!!) //forward extras
|
explorerIntent.putExtras(intent.extras!!) //forward extras
|
||||||
} else if (pickMode) {
|
} else if (pickMode) {
|
||||||
explorerIntent = Intent(this, ExplorerActivityPick::class.java)
|
explorerIntent = Intent(this, ExplorerActivityPick::class.java)
|
||||||
explorerIntent.putExtra("destinationVolume", intent.getParcelableExtra<EncryptedVolume>("volume")!!)
|
explorerIntent.putExtra("destinationVolume", getParcelableExtra<EncryptedVolume>(intent, "volume")!!)
|
||||||
explorerIntent.flags = Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
explorerIntent.flags = Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
||||||
}
|
}
|
||||||
if (explorerIntent == null) {
|
if (explorerIntent == null) {
|
||||||
@ -634,22 +648,12 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
if (volumeAdapter.selectedItems.isNotEmpty()) {
|
|
||||||
unselectAll()
|
|
||||||
} else {
|
|
||||||
if (pickMode)
|
|
||||||
shouldCloseVolume = false
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
if (pickMode && !usfKeepOpen) {
|
if (pickMode && !usfKeepOpen) {
|
||||||
finish()
|
finish()
|
||||||
if (shouldCloseVolume) {
|
if (shouldCloseVolume) {
|
||||||
intent.getParcelableExtra<EncryptedVolume>("volume")?.close()
|
getParcelableExtra<EncryptedVolume>(intent, "volume")?.close()
|
||||||
RestrictedFileProvider.wipeAll(this)
|
RestrictedFileProvider.wipeAll(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class SettingsActivity : BaseActivity() {
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId){
|
return when (item.itemId){
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
onBackPressed() //return to the previous fragment rather than the activity
|
onBackPressedDispatcher.onBackPressed() //return to the previous fragment rather than the activity
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
@ -41,6 +41,7 @@ class ExplorerElementAdapter(
|
|||||||
}
|
}
|
||||||
var isUsingListLayout = true
|
var isUsingListLayout = true
|
||||||
private var thumbnailsCache: LruCache<String, Bitmap>? = null
|
private var thumbnailsCache: LruCache<String, Bitmap>? = null
|
||||||
|
var loadThumbnails = true
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (encryptedVolume != null) {
|
if (encryptedVolume != null) {
|
||||||
@ -159,7 +160,7 @@ class ExplorerElementAdapter(
|
|||||||
if (thumbnail != null) {
|
if (thumbnail != null) {
|
||||||
icon.setImageBitmap(thumbnail)
|
icon.setImageBitmap(thumbnail)
|
||||||
setDefaultIcon = false
|
setDefaultIcon = false
|
||||||
} else {
|
} else if (adapter.loadThumbnails) {
|
||||||
loadThumbnail(fullPath, adapter)
|
loadThumbnail(fullPath, adapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
usf_open = sharedPrefs.getBoolean("usf_open", false)
|
usf_open = sharedPrefs.getBoolean("usf_open", false)
|
||||||
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
||||||
volumeName = intent.getStringExtra("volume_name") ?: ""
|
volumeName = intent.getStringExtra("volume_name") ?: ""
|
||||||
encryptedVolume = intent.getParcelableExtra("volume")!!
|
encryptedVolume = getParcelableExtra(intent, "volume")!!
|
||||||
sortOrderEntries = resources.getStringArray(R.array.sort_orders_entries)
|
sortOrderEntries = resources.getStringArray(R.array.sort_orders_entries)
|
||||||
sortOrderValues = resources.getStringArray(R.array.sort_orders_values)
|
sortOrderValues = resources.getStringArray(R.array.sort_orders_values)
|
||||||
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
||||||
|
@ -35,7 +35,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
private val pickFromOtherVolumes = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
private val pickFromOtherVolumes = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
result.data?.let { resultIntent ->
|
result.data?.let { resultIntent ->
|
||||||
val remoteEncryptedVolume = resultIntent.getParcelableExtra<EncryptedVolume>("volume")!!
|
val remoteEncryptedVolume = getParcelableExtra<EncryptedVolume>(resultIntent, "volume")!!
|
||||||
val path = resultIntent.getStringExtra("path")
|
val path = resultIntent.getStringExtra("path")
|
||||||
val operationFiles = ArrayList<OperationFile>()
|
val operationFiles = ArrayList<OperationFile>()
|
||||||
if (path == null){ //multiples elements
|
if (path == null){ //multiples elements
|
||||||
@ -63,6 +63,8 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
if (items == null) {
|
if (items == null) {
|
||||||
remoteEncryptedVolume.close()
|
remoteEncryptedVolume.close()
|
||||||
} else {
|
} else {
|
||||||
|
// stop loading thumbnails while writing files
|
||||||
|
explorerAdapter.loadThumbnails = false
|
||||||
taskScope.launch {
|
taskScope.launch {
|
||||||
val failedItem = fileOperationService.copyElements(items, remoteEncryptedVolume)
|
val failedItem = fileOperationService.copyElements(items, remoteEncryptedVolume)
|
||||||
if (failedItem == null) {
|
if (failedItem == null) {
|
||||||
@ -74,6 +76,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
.setPositiveButton(R.string.ok, null)
|
.setPositiveButton(R.string.ok, null)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
explorerAdapter.loadThumbnails = true
|
||||||
setCurrentPath(currentDirectoryPath)
|
setCurrentPath(currentDirectoryPath)
|
||||||
remoteEncryptedVolume.close()
|
remoteEncryptedVolume.close()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package sushi.hardcore.droidfs.explorers
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
@ -33,7 +34,7 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
|
|||||||
val errorMsg: String? = if (extras != null && extras.containsKey(Intent.EXTRA_STREAM)) {
|
val errorMsg: String? = if (extras != null && extras.containsKey(Intent.EXTRA_STREAM)) {
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_SEND -> {
|
Intent.ACTION_SEND -> {
|
||||||
val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
|
val uri = getParcelableExtra<Uri>(intent, Intent.EXTRA_STREAM)
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
getString(R.string.share_intent_parsing_failed)
|
getString(R.string.share_intent_parsing_failed)
|
||||||
} else {
|
} else {
|
||||||
@ -42,7 +43,12 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Intent.ACTION_SEND_MULTIPLE -> {
|
Intent.ACTION_SEND_MULTIPLE -> {
|
||||||
val uris = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)
|
val uris: List<Uri>? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)
|
||||||
|
} else {
|
||||||
|
@Suppress("Deprecation")
|
||||||
|
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
|
||||||
|
}
|
||||||
if (uris != null) {
|
if (uris != null) {
|
||||||
importFilesFromUris(uris, ::onImported)
|
importFilesFromUris(uris, ::onImported)
|
||||||
null
|
null
|
||||||
|
@ -83,7 +83,7 @@ class ExplorerActivityPick : BaseExplorerActivity() {
|
|||||||
|
|
||||||
override fun closeVolumeOnDestroy() {
|
override fun closeVolumeOnDestroy() {
|
||||||
if (!isFinishingIntentionally && !usf_keep_open){
|
if (!isFinishingIntentionally && !usf_keep_open){
|
||||||
intent.getParcelableExtra<EncryptedVolume>("destinationVolume")?.close()
|
getParcelableExtra<EncryptedVolume>(intent, "destinationVolume")?.close()
|
||||||
super.closeVolumeOnDestroy()
|
super.closeVolumeOnDestroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package sushi.hardcore.droidfs.file_viewers
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import sushi.hardcore.droidfs.BaseActivity
|
import sushi.hardcore.droidfs.BaseActivity
|
||||||
@ -33,13 +34,18 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
filePath = intent.getStringExtra("path")!!
|
filePath = intent.getStringExtra("path")!!
|
||||||
originalParentPath = PathUtils.getParentPath(filePath)
|
originalParentPath = PathUtils.getParentPath(filePath)
|
||||||
encryptedVolume = intent.getParcelableExtra("volume")!!
|
encryptedVolume = getParcelableExtra(intent, "volume")!!
|
||||||
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
||||||
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
||||||
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
||||||
windowInsetsController.addOnControllableInsetsChangedListener { _, typeMask ->
|
windowInsetsController.addOnControllableInsetsChangedListener { _, typeMask ->
|
||||||
windowTypeMask = typeMask
|
windowTypeMask = typeMask
|
||||||
}
|
}
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
isFinishingIntentionally = true
|
||||||
|
isEnabled = false
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
hideSystemUi()
|
hideSystemUi()
|
||||||
viewFile()
|
viewFile()
|
||||||
}
|
}
|
||||||
@ -75,7 +81,8 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
when (result.second) {
|
when (result.second) {
|
||||||
1 -> dialog.setMessage(R.string.get_size_failed)
|
1 -> dialog.setMessage(R.string.get_size_failed)
|
||||||
2 -> dialog.setMessage(R.string.outofmemoryerror_msg)
|
2 -> dialog.setMessage(R.string.outofmemoryerror_msg)
|
||||||
else -> dialog.setMessage(R.string.read_file_failed)
|
3 -> dialog.setMessage(R.string.read_file_failed)
|
||||||
|
4 -> dialog.setMessage(R.string.io_error)
|
||||||
}
|
}
|
||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
@ -145,9 +152,4 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
super.onBackPressed()
|
|
||||||
isFinishingIntentionally = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package sushi.hardcore.droidfs.file_viewers
|
package sushi.hardcore.droidfs.file_viewers
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@ -11,7 +9,7 @@ import android.view.MotionEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.activity.addCallback
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.RequestBuilder
|
import com.bumptech.glide.RequestBuilder
|
||||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
||||||
@ -35,7 +33,6 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
|
|
||||||
private lateinit var fileName: String
|
private lateinit var fileName: String
|
||||||
private lateinit var handler: Handler
|
private lateinit var handler: Handler
|
||||||
private var bitmap: Bitmap? = null
|
|
||||||
private var requestBuilder: RequestBuilder<Drawable>? = null
|
private var requestBuilder: RequestBuilder<Drawable>? = null
|
||||||
private var x1 = 0F
|
private var x1 = 0F
|
||||||
private var x2 = 0F
|
private var x2 = 0F
|
||||||
@ -151,53 +148,26 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
rotationAngle -= 90
|
rotationAngle -= 90
|
||||||
rotateImage()
|
rotateImage()
|
||||||
}
|
}
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
if (slideshowActive) {
|
||||||
|
stopSlideshow()
|
||||||
|
} else {
|
||||||
|
askSaveRotation {
|
||||||
|
isEnabled = false
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
loadImage()
|
loadImage()
|
||||||
handler.postDelayed(hideUI, hideDelay)
|
handler.postDelayed(hideUI, hideDelay)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadImage(){
|
private fun loadImage(){
|
||||||
bitmap = null
|
|
||||||
requestBuilder = null
|
requestBuilder = null
|
||||||
loadWholeFile(filePath)?.let {
|
loadWholeFile(filePath)?.let {
|
||||||
val displayWithGlide = if (it.size < 5_000_000) {
|
originalOrientation = 0f
|
||||||
true
|
requestBuilder = Glide.with(this).load(it)
|
||||||
} else {
|
requestBuilder?.into(binding.imageViewer)
|
||||||
bitmap = BitmapFactory.decodeByteArray(it, 0, it.size)
|
|
||||||
if (bitmap == null) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
val orientation = ExifInterface(ByteArrayInputStream(it)).getAttributeInt(
|
|
||||||
ExifInterface.TAG_ORIENTATION,
|
|
||||||
ExifInterface.ORIENTATION_NORMAL
|
|
||||||
)
|
|
||||||
originalOrientation = when (orientation) {
|
|
||||||
ExifInterface.ORIENTATION_ROTATE_90 -> 90f
|
|
||||||
ExifInterface.ORIENTATION_ROTATE_180 -> 180f
|
|
||||||
ExifInterface.ORIENTATION_ROTATE_270 -> 270f
|
|
||||||
else -> 0f
|
|
||||||
}
|
|
||||||
val displayMetrics = Resources.getSystem().displayMetrics
|
|
||||||
if (displayMetrics.widthPixels < bitmap!!.width || displayMetrics.heightPixels < bitmap!!.height) {
|
|
||||||
val newWidth: Int
|
|
||||||
val newHeight: Int
|
|
||||||
if (displayMetrics.widthPixels > displayMetrics.heightPixels) {
|
|
||||||
newWidth = displayMetrics.widthPixels
|
|
||||||
newHeight = bitmap!!.height*displayMetrics.widthPixels/bitmap!!.width
|
|
||||||
} else {
|
|
||||||
newHeight = displayMetrics.heightPixels
|
|
||||||
newWidth = bitmap!!.width*displayMetrics.heightPixels/bitmap!!.height
|
|
||||||
}
|
|
||||||
bitmap = Bitmap.createScaledBitmap(bitmap!!, newWidth, newHeight, false)
|
|
||||||
}
|
|
||||||
Glide.with(this).load(bitmap).transform(OrientationTransformation(originalOrientation)).into(binding.imageViewer)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (displayWithGlide) {
|
|
||||||
originalOrientation = 0f
|
|
||||||
requestBuilder = Glide.with(this).load(it)
|
|
||||||
requestBuilder?.into(binding.imageViewer)
|
|
||||||
}
|
|
||||||
fileName = File(filePath).name
|
fileName = File(filePath).name
|
||||||
binding.textFilename.text = fileName
|
binding.textFilename.text = fileName
|
||||||
rotationAngle = originalOrientation
|
rotationAngle = originalOrientation
|
||||||
@ -227,14 +197,6 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
if (slideshowActive){
|
|
||||||
stopSlideshow()
|
|
||||||
} else {
|
|
||||||
askSaveRotation { super.onBackPressed() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OrientationTransformation(private val orientation: Float): BitmapTransformation() {
|
class OrientationTransformation(private val orientation: Float): BitmapTransformation() {
|
||||||
|
|
||||||
lateinit var bitmap: Bitmap
|
lateinit var bitmap: Bitmap
|
||||||
@ -255,7 +217,7 @@ class ImageViewer: FileViewerActivity() {
|
|||||||
private fun rotateImage(){
|
private fun rotateImage(){
|
||||||
binding.imageViewer.restoreZoomNormal()
|
binding.imageViewer.restoreZoomNormal()
|
||||||
orientationTransformation = OrientationTransformation(rotationAngle)
|
orientationTransformation = OrientationTransformation(rotationAngle)
|
||||||
(requestBuilder ?: Glide.with(this).load(bitmap)).transform(orientationTransformation).into(binding.imageViewer)
|
requestBuilder?.transform(orientationTransformation)?.into(binding.imageViewer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun askSaveRotation(callback: () -> Unit){
|
private fun askSaveRotation(callback: () -> Unit){
|
||||||
|
@ -59,11 +59,10 @@ abstract class MediaPlayer: FileViewerActivity() {
|
|||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onPositionDiscontinuity(reason: Int) {
|
|
||||||
if (player.currentMediaItemIndex != currentPlaylistIndex) {
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
||||||
playlistNext(player.currentMediaItemIndex == (currentPlaylistIndex+1) % mappedPlaylist.size)
|
playlistNext(player.currentMediaItemIndex == (currentPlaylistIndex+1) % mappedPlaylist.size)
|
||||||
refreshFileName()
|
refreshFileName()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
player.prepare()
|
player.prepare()
|
||||||
|
@ -7,6 +7,9 @@ import java.io.ByteArrayInputStream
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class PdfViewer: FileViewerActivity() {
|
class PdfViewer: FileViewerActivity() {
|
||||||
|
init {
|
||||||
|
applyCustomTheme = false
|
||||||
|
}
|
||||||
private lateinit var pdfViewer: PdfViewer
|
private lateinit var pdfViewer: PdfViewer
|
||||||
|
|
||||||
override fun hideSystemUi() {
|
override fun hideSystemUi() {
|
||||||
@ -37,6 +40,11 @@ class PdfViewer: FileViewerActivity() {
|
|||||||
pdfViewer.onResume()
|
pdfViewer.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
pdfViewer.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
||||||
return pdfViewer.onPrepareOptionsMenu(menu)
|
return pdfViewer.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package sushi.hardcore.droidfs.file_viewers
|
|||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import com.google.android.exoplayer2.ExoPlayer
|
import com.google.android.exoplayer2.ExoPlayer
|
||||||
|
import com.google.android.exoplayer2.ui.StyledPlayerView
|
||||||
import sushi.hardcore.droidfs.databinding.ActivityVideoPlayerBinding
|
import sushi.hardcore.droidfs.databinding.ActivityVideoPlayerBinding
|
||||||
|
|
||||||
class VideoPlayer: MediaPlayer() {
|
class VideoPlayer: MediaPlayer() {
|
||||||
@ -16,9 +17,9 @@ class VideoPlayer: MediaPlayer() {
|
|||||||
binding = ActivityVideoPlayerBinding.inflate(layoutInflater)
|
binding = ActivityVideoPlayerBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
binding.videoPlayer.doubleTapOverlay = binding.doubleTapOverlay
|
binding.videoPlayer.doubleTapOverlay = binding.doubleTapOverlay
|
||||||
binding.videoPlayer.setControllerVisibilityListener { visibility ->
|
binding.videoPlayer.setControllerVisibilityListener(StyledPlayerView.ControllerVisibilityListener { visibility ->
|
||||||
binding.topBar.visibility = visibility
|
binding.topBar.visibility = visibility
|
||||||
}
|
})
|
||||||
binding.rotateButton.setOnClickListener {
|
binding.rotateButton.setOnClickListener {
|
||||||
requestedOrientation =
|
requestedOrientation =
|
||||||
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
@ -185,7 +185,7 @@ object PathUtils {
|
|||||||
return rootDirectory.delete()
|
return rootDirectory.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri>, context: Context, themeValue: String) {
|
fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri?>, context: Context, themeValue: String) {
|
||||||
try {
|
try {
|
||||||
directoryPicker.launch(null)
|
directoryPicker.launch(null)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
@ -28,6 +28,7 @@ import static androidx.camera.core.impl.UseCaseConfig.OPTION_DEFAULT_CAPTURE_CON
|
|||||||
import static androidx.camera.core.impl.UseCaseConfig.OPTION_DEFAULT_SESSION_CONFIG;
|
import static androidx.camera.core.impl.UseCaseConfig.OPTION_DEFAULT_SESSION_CONFIG;
|
||||||
import static androidx.camera.core.impl.UseCaseConfig.OPTION_SESSION_CONFIG_UNPACKER;
|
import static androidx.camera.core.impl.UseCaseConfig.OPTION_SESSION_CONFIG_UNPACKER;
|
||||||
import static androidx.camera.core.impl.UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
|
import static androidx.camera.core.impl.UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
|
||||||
|
import static androidx.camera.core.impl.UseCaseConfig.OPTION_ZSL_DISABLED;
|
||||||
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_BIT_RATE;
|
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_BIT_RATE;
|
||||||
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_CHANNEL_COUNT;
|
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_CHANNEL_COUNT;
|
||||||
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_MIN_BUFFER_SIZE;
|
import static androidx.camera.core.impl.VideoCaptureConfig.OPTION_AUDIO_MIN_BUFFER_SIZE;
|
||||||
@ -121,6 +122,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
|
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
|
||||||
|
@RestrictTo(Scope.LIBRARY_GROUP)
|
||||||
public final class VideoCapture extends UseCase {
|
public final class VideoCapture extends UseCase {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -1123,6 +1125,7 @@ public final class VideoCapture extends UseCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Set audio record parameters by CamcorderProfile */
|
/** Set audio record parameters by CamcorderProfile */
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private void setAudioParametersByCamcorderProfile(Size currentResolution, String cameraId) {
|
private void setAudioParametersByCamcorderProfile(Size currentResolution, String cameraId) {
|
||||||
CamcorderProfile profile;
|
CamcorderProfile profile;
|
||||||
boolean isCamcorderProfileFound = false;
|
boolean isCamcorderProfileFound = false;
|
||||||
@ -1732,6 +1735,14 @@ public final class VideoCapture extends UseCase {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@RestrictTo(Scope.LIBRARY_GROUP)
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Builder setZslDisabled(boolean disabled) {
|
||||||
|
getMutableConfig().insertOption(OPTION_ZSL_DISABLED, disabled);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,8 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package sushi.hardcore.droidfs.video_recording;
|
package sushi.hardcore.droidfs.video_recording;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.camera.core.impl.Config;
|
import androidx.camera.core.impl.Config;
|
||||||
import androidx.camera.core.impl.ImageFormatConstants;
|
import androidx.camera.core.impl.ImageFormatConstants;
|
||||||
import androidx.camera.core.impl.ImageOutputConfig;
|
import androidx.camera.core.impl.ImageOutputConfig;
|
||||||
@ -15,7 +30,7 @@ import androidx.camera.core.internal.ThreadConfig;
|
|||||||
*
|
*
|
||||||
* <p>In the earlier stage, the VideoCapture is deprioritized.
|
* <p>In the earlier stage, the VideoCapture is deprioritized.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("RestrictedApi")
|
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
|
||||||
public final class VideoCaptureConfig
|
public final class VideoCaptureConfig
|
||||||
implements UseCaseConfig<VideoCapture>,
|
implements UseCaseConfig<VideoCapture>,
|
||||||
ImageOutputConfig,
|
ImageOutputConfig,
|
||||||
|
@ -146,16 +146,16 @@ internal class CircleClipTapView(context: Context, attrs: AttributeSet): View(co
|
|||||||
}
|
}
|
||||||
|
|
||||||
addListener(object : Animator.AnimatorListener {
|
addListener(object : Animator.AnimatorListener {
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
override fun onAnimationStart(animation: Animator) {
|
||||||
visibility = VISIBLE
|
visibility = VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAnimationEnd(animation: Animator?) {
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
if (!forceReset) performAtEnd()
|
if (!forceReset) performAtEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAnimationRepeat(animation: Animator?) {}
|
override fun onAnimationRepeat(animation: Animator) {}
|
||||||
override fun onAnimationCancel(animation: Animator?) {}
|
override fun onAnimationCancel(animation: Animator) {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class DoubleTapPlayerView @JvmOverloads constructor(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
|
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||||
if (!isDoubleTapping)
|
if (!isDoubleTapping)
|
||||||
performClick()
|
performClick()
|
||||||
return true
|
return true
|
||||||
|
@ -18,7 +18,7 @@ int write_packet(void* opaque, uint8_t* buff, int buff_size) {
|
|||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
(*muxer->jvm)->GetEnv(muxer->jvm, (void **) &env, JNI_VERSION_1_6);
|
(*muxer->jvm)->GetEnv(muxer->jvm, (void **) &env, JNI_VERSION_1_6);
|
||||||
jbyteArray jarray = (*env)->NewByteArray(env, buff_size);
|
jbyteArray jarray = (*env)->NewByteArray(env, buff_size);
|
||||||
(*env)->SetByteArrayRegion(env, jarray, 0, buff_size, buff);
|
(*env)->SetByteArrayRegion(env, jarray, 0, buff_size, (const signed char*)buff);
|
||||||
(*env)->CallVoidMethod(env, muxer->thiz, muxer->write_packet_method_id, jarray, buff_size);
|
(*env)->CallVoidMethod(env, muxer->thiz, muxer->write_packet_method_id, jarray, buff_size);
|
||||||
return buff_size;
|
return buff_size;
|
||||||
}
|
}
|
||||||
@ -52,8 +52,7 @@ Java_sushi_hardcore_droidfs_video_1recording_MediaMuxer_addAudioTrack(JNIEnv *en
|
|||||||
const AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_AAC);
|
const AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_AAC);
|
||||||
AVStream* stream = avformat_new_stream((AVFormatContext *) format_context, NULL);
|
AVStream* stream = avformat_new_stream((AVFormatContext *) format_context, NULL);
|
||||||
AVCodecContext* codec_context = avcodec_alloc_context3(encoder);
|
AVCodecContext* codec_context = avcodec_alloc_context3(encoder);
|
||||||
codec_context->channels = channel_count;
|
av_channel_layout_default(&codec_context->ch_layout, channel_count);
|
||||||
codec_context->channel_layout = av_get_default_channel_layout(channel_count);
|
|
||||||
codec_context->sample_rate = sample_rate;
|
codec_context->sample_rate = sample_rate;
|
||||||
codec_context->sample_fmt = encoder->sample_fmts[0];
|
codec_context->sample_fmt = encoder->sample_fmts[0];
|
||||||
codec_context->bit_rate = bitrate;
|
codec_context->bit_rate = bitrate;
|
||||||
@ -105,8 +104,8 @@ Java_sushi_hardcore_droidfs_video_1recording_MediaMuxer_writePacket(JNIEnv *env,
|
|||||||
r.den = 1000000;
|
r.den = 1000000;
|
||||||
av_packet_rescale_ts(packet, r, ((AVFormatContext *)format_context)->streams[stream_index]->time_base);
|
av_packet_rescale_ts(packet, r, ((AVFormatContext *)format_context)->streams[stream_index]->time_base);
|
||||||
}
|
}
|
||||||
unsigned char* buff = malloc(size);
|
uint8_t* buff = malloc(size);
|
||||||
(*env)->GetByteArrayRegion(env, buffer, 0, size, buff);
|
(*env)->GetByteArrayRegion(env, buffer, 0, size, (signed char*)buff);
|
||||||
packet->data = buff;
|
packet->data = buff;
|
||||||
if (is_key_frame) {
|
if (is_key_frame) {
|
||||||
packet->flags = AV_PKT_FLAG_KEY;
|
packet->flags = AV_PKT_FLAG_KEY;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
tools:context=".CameraActivity"
|
tools:context=".CameraActivity"
|
||||||
android:background="#000000">
|
android:background="@color/fullScreenBackgroundColor">
|
||||||
|
|
||||||
<androidx.camera.view.PreviewView
|
<androidx.camera.view.PreviewView
|
||||||
android:id="@+id/camera_preview"
|
android:id="@+id/camera_preview"
|
||||||
|
@ -248,4 +248,5 @@
|
|||||||
<string name="file_op_delete_msg">Deleting files…</string>
|
<string name="file_op_delete_msg">Deleting files…</string>
|
||||||
<string name="volume_type">(%s)</string>
|
<string name="volume_type">(%s)</string>
|
||||||
<string name="volume_type_read_only">(%s, read-only)</string>
|
<string name="volume_type_read_only">(%s, read-only)</string>
|
||||||
|
<string name="io_error">I/O Error.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.6.10"
|
ext.kotlin_version = "1.7.10"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.1'
|
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Wed Sep 01 11:25:55 UTC 2021
|
#Wed Sep 01 11:25:55 UTC 2021
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 8fe8b2f4b3aecd3ad210478fd99df9f260503db8
|
Subproject commit 06e54dbb03098c0d0d113ed7b3fc93d74050f590
|
Loading…
Reference in New Issue
Block a user