diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4e2c5ab..2f83478 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,6 +27,8 @@
+
diff --git a/app/src/main/java/app/myzel394/alibi/helpers/AudioBatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/AudioBatchesFolder.kt
index b709f4f..21ba373 100644
--- a/app/src/main/java/app/myzel394/alibi/helpers/AudioBatchesFolder.kt
+++ b/app/src/main/java/app/myzel394/alibi/helpers/AudioBatchesFolder.kt
@@ -64,7 +64,7 @@ class AudioBatchesFolder(
val mediaUri = getOrCreateMediaFile(
name = getName(date, extension),
mimeType = "audio/$extension",
- relativePath = Environment.DIRECTORY_DCIM + "/" + MEDIA_SUBFOLDER_NAME,
+ relativePath = BASE_SCOPED_STORAGE_RELATIVE_PATH + "/" + MEDIA_SUBFOLDER_NAME,
)
return FFmpegKitConfig.getSafParameterForWrite(
@@ -146,8 +146,13 @@ class AudioBatchesFolder(
}
val MEDIA_RECORDINGS_SUBFOLDER = MEDIA_SUBFOLDER_NAME + "/audio_recordings"
+ val BASE_SCOPED_STORAGE_RELATIVE_PATH =
+ (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
+ Environment.DIRECTORY_RECORDINGS
+ else
+ Environment.DIRECTORY_PODCASTS)
val SCOPED_STORAGE_RELATIVE_PATH =
- Environment.DIRECTORY_DCIM + "/" + MEDIA_RECORDINGS_SUBFOLDER
+ BASE_SCOPED_STORAGE_RELATIVE_PATH + "/" + MEDIA_RECORDINGS_SUBFOLDER
// Parameters to be passed in descending order
// Those parameters first try to concatenate without re-encoding
diff --git a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt
index cb89243..5162795 100644
--- a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt
+++ b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt
@@ -250,11 +250,13 @@ abstract class BatchesFolder(
suspend fun concatenate(
recordingStart: LocalDateTime,
extension: String,
- disableCache: Boolean = false,
+ disableCache: Boolean? = null,
onNextParameterTry: (String) -> Unit = {},
durationPerBatchInMilliseconds: Long = 0,
onProgress: (Float?) -> Unit = {},
): String {
+ val disableCache = disableCache ?: (type != BatchType.INTERNAL)
+
if (!disableCache && checkIfOutputAlreadyExists(recordingStart, extension)) {
return getOutputFileForFFmpeg(
date = recordingStart,
@@ -462,7 +464,7 @@ abstract class BatchesFolder(
context.contentResolver.query(
scopedMediaContentUri,
arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME),
- "${MediaStore.MediaColumns.DISPLAY_NAME} = '$name'",
+ "${MediaStore.MediaColumns.DISPLAY_NAME} = '$name' AND ${Media.RELATIVE_PATH} = '$relativePath'",
null,
null,
)!!.use { cursor ->
@@ -482,27 +484,29 @@ abstract class BatchesFolder(
}
if (uri == null) {
- // Create empty output file to be able to write to it
- uri = context.contentResolver.insert(
- scopedMediaContentUri,
- ContentValues().apply {
- put(
- MediaStore.MediaColumns.DISPLAY_NAME,
- name
- )
- put(
- MediaStore.MediaColumns.MIME_TYPE,
- mimeType
- )
+ try {
+ // Create empty output file to be able to write to it
+ uri = context.contentResolver.insert(
+ scopedMediaContentUri,
+ ContentValues().apply {
+ put(
+ MediaStore.MediaColumns.DISPLAY_NAME,
+ name
+ )
+ put(
+ MediaStore.MediaColumns.MIME_TYPE,
+ mimeType
+ )
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(
Media.RELATIVE_PATH,
relativePath,
)
}
- }
- )!!
+ )!!
+ } catch (e: Exception) {
+ Log.e("Media", "Failed to create file", e)
+ }
}
return uri!!
diff --git a/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt
index 7517c45..20a69e4 100644
--- a/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt
+++ b/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt
@@ -7,6 +7,7 @@ import android.os.Build
import android.os.Environment
import android.os.ParcelFileDescriptor
import android.provider.MediaStore
+import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile
import app.myzel394.alibi.helpers.MediaConverter.Companion.concatenateVideoFiles
import app.myzel394.alibi.ui.MEDIA_SUBFOLDER_NAME
@@ -108,17 +109,16 @@ class VideoBatchesFolder(
}
}
+ @RequiresApi(Build.VERSION_CODES.Q)
fun asMediaGetScopedStorageContentValues(name: String) = ContentValues().apply {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- put(
- MediaStore.Video.Media.IS_PENDING,
- 1
- )
- put(
- MediaStore.Video.Media.RELATIVE_PATH,
- SCOPED_STORAGE_RELATIVE_PATH,
- )
- }
+ put(
+ MediaStore.Video.Media.IS_PENDING,
+ 1
+ )
+ put(
+ MediaStore.Video.Media.RELATIVE_PATH,
+ SCOPED_STORAGE_RELATIVE_PATH,
+ )
put(
MediaStore.Video.Media.DISPLAY_NAME,
diff --git a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
index 604ec98..ee39570 100644
--- a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
@@ -162,7 +162,7 @@ class AudioRecorderService :
}
private fun getNameForMediaFile() =
- "${batchesFolder.mediaPrefix}$counter.${settings.videoRecorderSettings.fileExtension}"
+ "${batchesFolder.mediaPrefix}$counter.${settings.audioRecorderSettings.fileExtension}"
// ==== Actual recording related ====
private fun createRecorder(): MediaRecorder {
diff --git a/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt
index d9f50a2..0dd9cd2 100644
--- a/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/VideoRecorderService.kt
@@ -25,6 +25,7 @@ import app.myzel394.alibi.db.RecordingInformation
import app.myzel394.alibi.enums.RecorderState
import app.myzel394.alibi.helpers.BatchesFolder
import app.myzel394.alibi.helpers.VideoBatchesFolder
+import app.myzel394.alibi.ui.SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
@@ -231,7 +232,7 @@ class VideoRecorderService :
private fun prepareVideoRecording() =
videoCapture!!.output
.let {
- if (batchesFolder.type == BatchesFolder.BatchType.CUSTOM && SUPPORTS_SCOPED_STORAGE) {
+ if (batchesFolder.type == BatchesFolder.BatchType.CUSTOM && SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS) {
it.prepareRecording(
this,
FileDescriptorOutputOptions.Builder(
diff --git a/app/src/main/java/app/myzel394/alibi/ui/Constants.kt b/app/src/main/java/app/myzel394/alibi/ui/Constants.kt
index 32e871b..68afb9d 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/Constants.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/Constants.kt
@@ -11,11 +11,14 @@ val SUPPORTS_DARK_MODE_NATIVELY = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
val MEDIA_SUBFOLDER_NAME = "alibi"
-val SUPPORTS_SCOPED_STORAGE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+val SUPPORTS_SCOPED_STORAGE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
+val SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
val MEDIA_RECORDINGS_PREFIX = "alibi-recording-"
val RECORDER_MEDIA_SELECTED_VALUE = "_'media"
val RECORDER_INTERNAL_SELECTED_VALUE = "_'internal"
+// TODO: Check API 24
+
// You are not allowed to change the constants below.
// If you do so, you will be blocked on GitHub.
const val REPO_URL = "https://github.com/Myzel394/Alibi"
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt
index 546d646..c24aa51 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt
@@ -55,6 +55,7 @@ import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE
import app.myzel394.alibi.ui.SHEET_BOTTOM_OFFSET
+import app.myzel394.alibi.ui.SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE
import app.myzel394.alibi.ui.components.atoms.MessageBox
import app.myzel394.alibi.ui.components.atoms.MessageType
@@ -256,7 +257,7 @@ fun SelectionSheet(
SUPPORTS_SCOPED_STORAGE ||
PermissionHelper.hasGranted(
context,
- Manifest.permission.READ_EXTERNAL_STORAGE
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) {
updateValue(RECORDER_MEDIA_SELECTED_VALUE)
@@ -276,7 +277,7 @@ fun SelectionSheet(
showCustomFolderWarning = true
},
)
- if (!SUPPORTS_SCOPED_STORAGE) {
+ if (!SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS) {
Column(
modifier = Modifier.padding(horizontal = 32.dp, vertical = 12.dp),
horizontalAlignment = Alignment.CenterHorizontally,