diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 77eeaac0..e269fd9e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,26 +6,10 @@
-
-
-
+
= Build.VERSION_CODES.Q) {
+ MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
+ } else {
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI
+ }
- var animationCount = 0
- animator.frames(context) { bitmap, count ->
+ val gifDetails = ContentValues().apply {
+ put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
+ put(MediaStore.Images.Media.MIME_TYPE, "image/gif")
+ }
- when {
- count > 10 -> {
- writer.writeFrame(os, bitmap, count * 8)
- animationCount = 0
- }
- else -> {
- if (animationCount % 2 == 0) {
- writer.writeFrame(os, bitmap)
+ val uri = resolver.insert(videoCollection, gifDetails)
+
+ if (uri != null) {
+ val os = resolver.openOutputStream(uri)
+
+ val writer = AnimatedGIFWriter(false)
+ writer.prepareForWrite(os, width, height)
+
+ val drawer = TableDrawer()
+ drawer.configurePaints(context, animator)
+
+ var animationCount = 0
+ animator.frames(context) { bitmap, count ->
+
+ when {
+ count > 10 -> {
+ writer.writeFrame(os, bitmap, count * 8)
+ animationCount = 0
+ }
+ else -> {
+ if (animationCount % 2 == 0) {
+ writer.writeFrame(os, bitmap)
+ }
+ animationCount++
}
- animationCount++
}
+
}
+ writer.finishWrite(os)
+ realm.close()
+ notifyUser(uri, FileType.IMAGE)
}
- writer.finishWrite(os)
-
- realm.close()
- notifyUser(path)
-
}
c.await()
}
@@ -148,30 +168,79 @@ class ReplayExportService : Service() {
val tmpDir = animator.generateVideoContent(this@ReplayExportService)
val dpath = "${tmpDir.path}/$FFMPEG_DESCRIPTOR_FILE"
-// val directory = context.getExternalFilesDir(null) ?: throw PAIllegalStateException("File is invalid")
-// val output = "${directory.path}/video_${Date().dateTimeFileFormatted}.mp4"
-
val formattedDate = Date().dateTimeFileFormatted
- val output = File(
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
- "video_${formattedDate}.mp4"
- ).path
+ val fileName = "hand_${formattedDate}.mp4"
+// val output = File(
+// Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
+// fileName
+// ).path
+
+ val outputDirectory = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES) ?: throw PAIllegalStateException("File is invalid")
+ val output = "${outputDirectory.path}/$fileName"
- Environment.getExternalStorageState(tmpDir)
+// Environment.getExternalStorageState(tmpDir)
Timber.d("Assembling images for video...")
+
FFmpeg.executeAsync("-f concat -safe 0 -i $dpath -vb 20M -vsync vfr -s ${width}x${height} -pix_fmt yuv420p $output") { id, rc ->
- if (rc == RETURN_CODE_SUCCESS) {
- Timber.d("FFMPEG command execution completed successfully")
- } else if (rc == RETURN_CODE_CANCEL) {
- Timber.d("Command execution cancelled by user.")
- } else {
- Timber.d(String.format("Command execution failed with rc=%d and the output below.", rc))
+ when (rc) {
+ RETURN_CODE_SUCCESS -> {
+ Timber.d("FFMPEG command execution completed successfully")
+ }
+ RETURN_CODE_CANCEL -> {
+ Timber.d("Command execution cancelled by user.")
+ }
+ else -> {
+ Timber.d(String.format("Command execution failed with rc=%d and the output below.", rc))
+ }
}
+
tmpDir.delete()
- notifyUser(output)
+ val file = File(output)
+
+ val resolver = applicationContext.contentResolver
+ val videoCollection =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
+ } else {
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI
+ }
+
+ val fileDetails = ContentValues().apply {
+ Timber.d("set file details = $fileName")
+ put(MediaStore.Video.Media.DISPLAY_NAME, fileName)
+// put(MediaStore.Video.Media.CONTENT_TYPE, "video/mp4")
+ }
+
+ resolver.insert(videoCollection, fileDetails)?.let { uri ->
+
+ Timber.d("copy file at uri = $uri")
+
+ val os = resolver.openOutputStream(uri)
+ os?.write(file.readBytes())
+ os?.close()
+
+ file.delete()
+
+ notifyUser(uri, FileType.VIDEO)
+
+ } ?: run {
+ Timber.w("Resolver insert ended without uri...")
+ }
+
+
+// val uri = FileProvider.getUriForFile(
+// applicationContext,
+// applicationContext.packageName.toString() + ".fileprovider",
+// File(output)
+// )
+
+// Timber.d("File exported at $output")
+
+
+// notifyUser(output)
}
}
@@ -226,26 +295,26 @@ class ReplayExportService : Service() {
//
// }
- private fun notifyUser(path: String) {
-
- Timber.d("Show local notification")
+ private fun notifyUser(uri: Uri, type: FileType) {
val title = getString(R.string.video_available)
- val body = getString(R.string.video_retrieval_message) + ": " + path
+ val body = getString(R.string.video_retrieval_message) + ": " + uri.path
- val uri = FileProvider.getUriForFile(
- this,
- this.applicationContext.packageName.toString() + ".fileprovider",
- File(path)
- )
+ Timber.d("Show local notification, path of file: ${uri.path}")
- val type = when {
- path.contains("gif") -> "image/gif"
- else -> "video/*"
- }
+// val uri = FileProvider.getUriForFile(
+// this,
+// this.applicationContext.packageName.toString() + ".fileprovider",
+// File(path)
+// )
+//
+// val type = when {
+// path.contains("gif") -> "image/gif"
+// else -> "video/*"
+// }
val intent = Intent(Intent.ACTION_VIEW)
- intent.setDataAndType(uri, type)
+ intent.setDataAndType(uri, type.value)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
val chooser = Intent.createChooser(intent, getString(R.string.open_file_with))
diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/DateExtension.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/DateExtension.kt
index c80cc2ef..414d111d 100644
--- a/app/src/main/java/net/pokeranalytics/android/util/extensions/DateExtension.kt
+++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/DateExtension.kt
@@ -120,7 +120,7 @@ fun Date.getDayMonthYear(): String {
// Returns a file friendly date time string
val Date.dateTimeFileFormatted: String
get() {
- return SimpleDateFormat("yy_MM_dd_hh_mm_ss", Locale.getDefault()).format(this)
+ return SimpleDateFormat("yy_MM_dd-hh_mm_ss", Locale.getDefault()).format(this)
}
// Return the netDuration between two dates