Fixed crash with media store on Android < 29
This commit is contained in:
parent
bf8fe02981
commit
8e806faecd
4 changed files with 57 additions and 21 deletions
|
@ -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()) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue