Fixed crash with media store on Android < 29

This commit is contained in:
Sylvain Berfini 2021-01-13 11:42:21 +01:00
parent bf8fe02981
commit 8e806faecd
4 changed files with 57 additions and 21 deletions

View file

@ -88,6 +88,15 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
}
})
callsViewModel.askWriteExternalStoragePermissionEvent.observe(viewLifecycleOwner, {
it.consume {
if (!PermissionHelper.get().hasWriteExternalStorage()) {
Log.i("[Controls Fragment] Asking for WRITE_EXTERNAL_STORAGE permission")
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
}
}
})
callsViewModel.callUpdateEvent.observe(viewLifecycleOwner, {
it.consume { call ->
if (call.state == Call.State.StreamsRunning) {
@ -196,6 +205,8 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
}
}
}
} else if (requestCode == 1 && grantResults[0] == PERMISSION_GRANTED) {
callsViewModel.takeScreenshot()
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
@ -206,12 +217,12 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
if (!PermissionHelper.get().hasRecordAudioPermission()) {
Log.i("[Controls Fragment] Asking for RECORD_AUDIO permission")
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
permissionsRequiredList.add(Manifest.permission.RECORD_AUDIO)
}
if (coreContext.isVideoCallOrConferenceActive() && !PermissionHelper.get().hasCameraPermission()) {
Log.i("[Controls Fragment] Asking for CAMERA permission")
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
permissionsRequiredList.add(Manifest.permission.CAMERA)
}
if (permissionsRequiredList.isNotEmpty()) {

View file

@ -26,6 +26,7 @@ import org.linphone.core.Call
import org.linphone.core.Core
import org.linphone.core.CoreListenerStub
import org.linphone.utils.Event
import org.linphone.utils.PermissionHelper
class CallsViewModel : ViewModel() {
val currentCallViewModel = MutableLiveData<CallViewModel>()
@ -46,6 +47,10 @@ class CallsViewModel : ViewModel() {
MutableLiveData<Event<Call>>()
}
val askWriteExternalStoragePermissionEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
private val listener = object : CoreListenerStub() {
override fun onCallStateChanged(
core: Core,
@ -147,7 +152,11 @@ class CallsViewModel : ViewModel() {
}
fun takeScreenshot() {
currentCallViewModel.value?.takeScreenshot()
if (!PermissionHelper.get().hasWriteExternalStorage()) {
askWriteExternalStoragePermissionEvent.value = Event(true)
} else {
currentCallViewModel.value?.takeScreenshot()
}
}
private fun addCallToPausedList(call: Call) {

View file

@ -35,6 +35,7 @@ import org.linphone.core.Content
import org.linphone.core.tools.Log
import org.linphone.utils.AppUtils
import org.linphone.utils.FileUtils
import org.linphone.utils.PermissionHelper
@Suppress("DEPRECATION")
@TargetApi(21)
@ -65,9 +66,14 @@ class Api21Compatibility {
}
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
if (!PermissionHelper.get().hasWriteExternalStorage()) {
Log.e("[Media Store] Write external storage permission denied")
return false
}
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -75,7 +81,7 @@ class Api21Compatibility {
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
@ -85,7 +91,7 @@ class Api21Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}
@ -101,9 +107,14 @@ class Api21Compatibility {
}
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
if (!PermissionHelper.get().hasWriteExternalStorage()) {
Log.e("[Media Store] Write external storage permission denied")
return false
}
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -111,7 +122,7 @@ class Api21Compatibility {
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Video.Media.TITLE, fileName)
@ -122,7 +133,7 @@ class Api21Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}
@ -138,9 +149,14 @@ class Api21Compatibility {
}
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
if (!PermissionHelper.get().hasWriteExternalStorage()) {
Log.e("[Media Store] Write external storage permission denied")
return false
}
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -148,7 +164,7 @@ class Api21Compatibility {
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Audio.Media.TITLE, fileName)
@ -159,7 +175,7 @@ class Api21Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}

View file

@ -36,7 +36,7 @@ class Api29Compatibility {
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -44,7 +44,7 @@ class Api29Compatibility {
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding image $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
@ -56,7 +56,7 @@ class Api29Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}
@ -78,7 +78,7 @@ class Api29Compatibility {
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -86,7 +86,7 @@ class Api29Compatibility {
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding video $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Video.Media.TITLE, fileName)
@ -99,7 +99,7 @@ class Api29Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}
@ -121,7 +121,7 @@ class Api29Compatibility {
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
Log.e("[Media Store] Content doesn't have a file path!")
return false
}
@ -129,7 +129,7 @@ class Api29Compatibility {
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
val fileName = content.name
val mime = "${content.type}/${content.subtype}"
Log.i("[Chat Message] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
Log.i("[Media Store] Adding audio $filePath to Media Store with name $fileName and MIME $mime, asking to be stored in $relativePath")
val values = ContentValues().apply {
put(MediaStore.Audio.Media.TITLE, fileName)
@ -142,7 +142,7 @@ class Api29Compatibility {
val fileUri = context.contentResolver.insert(collection, values)
if (fileUri == null) {
Log.e("[Chat Message] Failed to get a URI to where store the file, aborting")
Log.e("[Media Store] Failed to get a URI to where store the file, aborting")
return false
}