mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-05-03 15:16:21 +00:00
Added export to PDF file received by chat to Android public storage
This commit is contained in:
parent
80b887c874
commit
b32007b1ca
4 changed files with 110 additions and 17 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
package org.linphone.ui.main.viewer.fragment
|
package org.linphone.ui.main.viewer.fragment
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
|
@ -21,6 +23,8 @@ import org.linphone.ui.main.viewer.viewmodel.FileViewModel
|
||||||
class FileViewerFragment : GenericFragment() {
|
class FileViewerFragment : GenericFragment() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "[File Viewer Fragment]"
|
private const val TAG = "[File Viewer Fragment]"
|
||||||
|
|
||||||
|
private const val EXPORT_PDF = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: FileViewerFragmentBinding
|
private lateinit var binding: FileViewerFragmentBinding
|
||||||
|
|
@ -73,6 +77,17 @@ class FileViewerFragment : GenericFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.exportPdfEvent.observe(viewLifecycleOwner) {
|
||||||
|
it.consume { name ->
|
||||||
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "application/pdf"
|
||||||
|
putExtra(Intent.EXTRA_TITLE, name)
|
||||||
|
}
|
||||||
|
startActivityForResult(intent, EXPORT_PDF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.isVideo.observe(viewLifecycleOwner) { isVideo ->
|
viewModel.isVideo.observe(viewLifecycleOwner) { isVideo ->
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
binding.videoPlayer.setVideoPath(path)
|
binding.videoPlayer.setVideoPath(path)
|
||||||
|
|
@ -134,6 +149,17 @@ class FileViewerFragment : GenericFragment() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
if (requestCode == EXPORT_PDF && resultCode == Activity.RESULT_OK) {
|
||||||
|
data?.data?.also { documentUri ->
|
||||||
|
Log.i("$TAG Exported PDF should be stored in URI [$documentUri]")
|
||||||
|
viewModel.copyPdfToUri(documentUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateScreenSize() {
|
private fun updateScreenSize() {
|
||||||
val displayMetrics = DisplayMetrics()
|
val displayMetrics = DisplayMetrics()
|
||||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,10 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val exportPdfEvent: MutableLiveData<Event<String>> by lazy {
|
||||||
|
MutableLiveData<Event<String>>()
|
||||||
|
}
|
||||||
|
|
||||||
val toggleVideoPlayPauseEvent: MutableLiveData<Event<Boolean>> by lazy {
|
val toggleVideoPlayPauseEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +71,7 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
||||||
|
|
||||||
var screenWidth: Int = 0
|
var screenWidth: Int = 0
|
||||||
var screenHeight: Int = 0
|
var screenHeight: Int = 0
|
||||||
var currentPdfPage: PdfRenderer.Page? = null
|
private var currentPdfPage: PdfRenderer.Page? = null
|
||||||
// End of PDF viewer required variables
|
// End of PDF viewer required variables
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
|
|
@ -180,22 +184,29 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
||||||
@UiThread
|
@UiThread
|
||||||
fun exportToMediaStore() {
|
fun exportToMediaStore() {
|
||||||
if (::filePath.isInitialized) {
|
if (::filePath.isInitialized) {
|
||||||
viewModelScope.launch {
|
if (isPdf.value == true) {
|
||||||
withContext(Dispatchers.IO) {
|
Log.i("$TAG Exporting PDF as document")
|
||||||
Log.i("$TAG Export file [$filePath] to Android's MediaStore")
|
exportPdfEvent.postValue(Event(fileName.value.orEmpty()))
|
||||||
val mediaStorePath = addContentToMediaStore(filePath)
|
} else {
|
||||||
if (mediaStorePath.isNotEmpty()) {
|
viewModelScope.launch {
|
||||||
Log.i("$TAG File [$filePath] has been successfully exported to MediaStore")
|
withContext(Dispatchers.IO) {
|
||||||
val message = AppUtils.getString(
|
Log.i("$TAG Export file [$filePath] to Android's MediaStore")
|
||||||
R.string.toast_file_successfully_exported_to_media_store
|
val mediaStorePath = addContentToMediaStore(filePath)
|
||||||
)
|
if (mediaStorePath.isNotEmpty()) {
|
||||||
showGreenToastEvent.postValue(Event(Pair(message, R.drawable.check)))
|
Log.i(
|
||||||
} else {
|
"$TAG File [$filePath] has been successfully exported to MediaStore"
|
||||||
Log.e("$TAG Failed to export file [$filePath] to MediaStore!")
|
)
|
||||||
val message = AppUtils.getString(
|
val message = AppUtils.getString(
|
||||||
R.string.toast_export_file_to_media_store_error
|
R.string.toast_file_successfully_exported_to_media_store
|
||||||
)
|
)
|
||||||
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
|
showGreenToastEvent.postValue(Event(Pair(message, R.drawable.check)))
|
||||||
|
} else {
|
||||||
|
Log.e("$TAG Failed to export file [$filePath] to MediaStore!")
|
||||||
|
val message = AppUtils.getString(
|
||||||
|
R.string.toast_export_file_to_media_store_error
|
||||||
|
)
|
||||||
|
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -204,6 +215,32 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
fun copyPdfToUri(dest: Uri) {
|
||||||
|
val source = Uri.parse(FileUtils.getProperFilePath(filePath))
|
||||||
|
Log.i("$TAG Copying file URI [$source] to [$dest]")
|
||||||
|
viewModelScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val result = FileUtils.copyFile(source, dest)
|
||||||
|
if (result) {
|
||||||
|
Log.i(
|
||||||
|
"$TAG File [$filePath] has been successfully exported to documents"
|
||||||
|
)
|
||||||
|
val message = AppUtils.getString(
|
||||||
|
R.string.toast_file_successfully_exported_to_documents
|
||||||
|
)
|
||||||
|
showGreenToastEvent.postValue(Event(Pair(message, R.drawable.check)))
|
||||||
|
} else {
|
||||||
|
Log.e("$TAG Failed to export file [$filePath] to documents!")
|
||||||
|
val message = AppUtils.getString(
|
||||||
|
R.string.toast_export_file_to_documents_error
|
||||||
|
)
|
||||||
|
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private suspend fun addContentToMediaStore(
|
private suspend fun addContentToMediaStore(
|
||||||
path: String
|
path: String
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import androidx.annotation.AnyThread
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileNotFoundException
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
@ -259,6 +260,33 @@ class FileUtils {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AnyThread
|
||||||
|
fun copyFile(from: Uri, to: Uri): Boolean {
|
||||||
|
try {
|
||||||
|
coreContext.context.contentResolver.openFileDescriptor(to, "w")?.use { fd ->
|
||||||
|
FileOutputStream(fd.fileDescriptor).use { outputStream ->
|
||||||
|
val fileDescriptor = coreContext.context.contentResolver.openFileDescriptor(
|
||||||
|
from,
|
||||||
|
"r"
|
||||||
|
)
|
||||||
|
val inputStream = FileInputStream(fileDescriptor?.fileDescriptor)
|
||||||
|
val buffer = ByteArray(4096)
|
||||||
|
var bytesRead: Int
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } >= 0) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
fileDescriptor?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
Log.e("$TAG Failed to find dest file: $e")
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e("$TAG Error copying file: $e")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun copyFileTo(filePath: String, outputStream: OutputStream?): Boolean {
|
suspend fun copyFileTo(filePath: String, outputStream: OutputStream?): Boolean {
|
||||||
if (outputStream == null) {
|
if (outputStream == null) {
|
||||||
Log.e("$TAG Can't copy file $filePath to given null output stream")
|
Log.e("$TAG Can't copy file $filePath to given null output stream")
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,8 @@
|
||||||
<string name="toast_default_account_connection_state_error">Connection error!</string>
|
<string name="toast_default_account_connection_state_error">Connection error!</string>
|
||||||
<string name="toast_file_successfully_exported_to_media_store">File has been exported to native gallery</string>
|
<string name="toast_file_successfully_exported_to_media_store">File has been exported to native gallery</string>
|
||||||
<string name="toast_export_file_to_media_store_error">Error trying to export file to native gallery</string>
|
<string name="toast_export_file_to_media_store_error">Error trying to export file to native gallery</string>
|
||||||
|
<string name="toast_file_successfully_exported_to_documents">File has been exported to documents</string>
|
||||||
|
<string name="toast_export_file_to_documents_error">Error trying to export file to documents</string>
|
||||||
<string name="toast_participant_added_to_conversation">Someone joined the conversation</string>
|
<string name="toast_participant_added_to_conversation">Someone joined the conversation</string>
|
||||||
<string name="toast_participant_removed_from_conversation">Someone left the conversation</string>
|
<string name="toast_participant_removed_from_conversation">Someone left the conversation</string>
|
||||||
<string name="toast_participant_has_been_granted_admin_rights">Someone is now admin</string>
|
<string name="toast_participant_has_been_granted_admin_rights">Someone is now admin</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue