mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +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
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
|
|
@ -21,6 +23,8 @@ import org.linphone.ui.main.viewer.viewmodel.FileViewModel
|
|||
class FileViewerFragment : GenericFragment() {
|
||||
companion object {
|
||||
private const val TAG = "[File Viewer Fragment]"
|
||||
|
||||
private const val EXPORT_PDF = 10
|
||||
}
|
||||
|
||||
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 ->
|
||||
if (isVideo) {
|
||||
binding.videoPlayer.setVideoPath(path)
|
||||
|
|
@ -134,6 +149,17 @@ class FileViewerFragment : GenericFragment() {
|
|||
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() {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val exportPdfEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
val toggleVideoPlayPauseEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
|
@ -67,7 +71,7 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
var screenWidth: Int = 0
|
||||
var screenHeight: Int = 0
|
||||
var currentPdfPage: PdfRenderer.Page? = null
|
||||
private var currentPdfPage: PdfRenderer.Page? = null
|
||||
// End of PDF viewer required variables
|
||||
|
||||
override fun onCleared() {
|
||||
|
|
@ -180,22 +184,29 @@ class FileViewModel @UiThread constructor() : ViewModel() {
|
|||
@UiThread
|
||||
fun exportToMediaStore() {
|
||||
if (::filePath.isInitialized) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
Log.i("$TAG Export file [$filePath] to Android's MediaStore")
|
||||
val mediaStorePath = addContentToMediaStore(filePath)
|
||||
if (mediaStorePath.isNotEmpty()) {
|
||||
Log.i("$TAG File [$filePath] has been successfully exported to MediaStore")
|
||||
val message = AppUtils.getString(
|
||||
R.string.toast_file_successfully_exported_to_media_store
|
||||
)
|
||||
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)))
|
||||
if (isPdf.value == true) {
|
||||
Log.i("$TAG Exporting PDF as document")
|
||||
exportPdfEvent.postValue(Event(fileName.value.orEmpty()))
|
||||
} else {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
Log.i("$TAG Export file [$filePath] to Android's MediaStore")
|
||||
val mediaStorePath = addContentToMediaStore(filePath)
|
||||
if (mediaStorePath.isNotEmpty()) {
|
||||
Log.i(
|
||||
"$TAG File [$filePath] has been successfully exported to MediaStore"
|
||||
)
|
||||
val message = AppUtils.getString(
|
||||
R.string.toast_file_successfully_exported_to_media_store
|
||||
)
|
||||
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
|
||||
private suspend fun addContentToMediaStore(
|
||||
path: String
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import androidx.annotation.AnyThread
|
|||
import androidx.core.content.FileProvider
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
|
@ -259,6 +260,33 @@ class FileUtils {
|
|||
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 {
|
||||
if (outputStream == null) {
|
||||
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_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_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_removed_from_conversation">Someone left the conversation</string>
|
||||
<string name="toast_participant_has_been_granted_admin_rights">Someone is now admin</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue