In-call audio/camera permissions improvements

This commit is contained in:
Sylvain Berfini 2020-09-10 11:19:38 +02:00
parent 1ad5d31426
commit 19fe8dd57b
5 changed files with 108 additions and 33 deletions

View file

@ -19,9 +19,11 @@
*/
package org.linphone.activities.call
import android.Manifest
import android.annotation.TargetApi
import android.app.KeyguardManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
@ -113,10 +115,12 @@ class IncomingCallActivity : GenericActivity() {
Log.i("[Incoming Call Activity] Asking for RECORD_AUDIO permission")
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
}
if (viewModel.call.currentParams.videoEnabled() && !PermissionHelper.get().hasCameraPermission()) {
Log.i("[Incoming Call Activity] Asking for CAMERA permission")
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
}
if (permissionsRequiredList.isNotEmpty()) {
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
permissionsRequiredList.toArray(permissionsRequired)
@ -124,6 +128,26 @@ class IncomingCallActivity : GenericActivity() {
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == 0) {
for (i in permissions.indices) {
when (permissions[i]) {
Manifest.permission.RECORD_AUDIO -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Incoming Call Activity] RECORD_AUDIO permission has been granted")
}
Manifest.permission.CAMERA -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Incoming Call Activity] CAMERA permission has been granted")
coreContext.core.reloadVideoDevices()
}
}
}
}
}
private fun findIncomingCall(): Call? {
for (call in coreContext.core.calls) {
if (call.state == Call.State.IncomingReceived ||

View file

@ -19,7 +19,9 @@
*/
package org.linphone.activities.call
import android.Manifest
import android.annotation.TargetApi
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.WindowManager
import androidx.databinding.DataBindingUtil
@ -64,22 +66,6 @@ class OutgoingCallActivity : ProximitySensorActivity() {
controlsViewModel = ViewModelProvider(this).get(ControlsViewModel::class.java)
binding.controlsViewModel = controlsViewModel
binding.setTerminateCallClickListener {
viewModel.terminateCall()
}
binding.setToggleMicrophoneClickListener {
if (PermissionHelper.get().hasRecordAudioPermission()) {
controlsViewModel.toggleMuteMicrophone()
} else {
checkPermissions()
}
}
binding.setToggleSpeakerClickListener {
controlsViewModel.toggleSpeaker()
}
viewModel.callEndedEvent.observe(this, {
it.consume {
Log.i("[Outgoing Call Activity] Call ended, finish activity")
@ -98,6 +84,12 @@ class OutgoingCallActivity : ProximitySensorActivity() {
enableProximitySensor(!it)
})
controlsViewModel.askPermissionEvent.observe(this, {
it.consume { permission ->
requestPermissions(arrayOf(permission), 0)
}
})
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
checkPermissions()
}
@ -131,6 +123,27 @@ class OutgoingCallActivity : ProximitySensorActivity() {
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == 0) {
for (i in permissions.indices) {
when (permissions[i]) {
Manifest.permission.RECORD_AUDIO -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Outgoing Call Activity] RECORD_AUDIO permission has been granted")
controlsViewModel.updateMuteMicState()
}
Manifest.permission.CAMERA -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Outgoing Call Activity] CAMERA permission has been granted")
coreContext.core.reloadVideoDevices()
}
}
}
}
}
private fun findOutgoingCall(): Call? {
for (call in coreContext.core.calls) {
if (call.state == Call.State.OutgoingInit ||

View file

@ -19,13 +19,15 @@
*/
package org.linphone.activities.call.fragments
import android.Manifest
import android.annotation.TargetApi
import android.app.Dialog
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Bundle
import android.os.SystemClock
import androidx.lifecycle.ViewModelProvider
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R
import org.linphone.activities.GenericFragment
import org.linphone.activities.call.viewmodels.CallsViewModel
@ -122,6 +124,13 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
}
})
controlsViewModel.askPermissionEvent.observe(viewLifecycleOwner, {
it.consume { permission ->
Log.i("[Controls Fragment] Asking for $permission permission")
requestPermissions(arrayOf(permission), 0)
}
})
controlsViewModel.somethingClickedEvent.observe(viewLifecycleOwner, {
it.consume {
sharedViewModel.resetHiddenInterfaceTimerInVideoCallEvent.value = Event(true)
@ -138,9 +147,19 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("[Controls Fragment] RECORD_AUDIO permission has been granted")
controlsViewModel.updateMuteMicState()
if (requestCode == 0) {
for (i in permissions.indices) {
when (permissions[i]) {
Manifest.permission.RECORD_AUDIO -> if (grantResults[i] == PERMISSION_GRANTED) {
Log.i("[Controls Fragment] RECORD_AUDIO permission has been granted")
controlsViewModel.updateMuteMicState()
}
Manifest.permission.CAMERA -> if (grantResults[i] == PERMISSION_GRANTED) {
Log.i("[Controls Fragment] CAMERA permission has been granted")
coreContext.core.reloadVideoDevices()
}
}
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
@ -148,10 +167,17 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
@TargetApi(Version.API23_MARSHMALLOW_60)
private fun checkPermissions() {
val permissionsRequiredList = arrayListOf<String>()
if (!PermissionHelper.get().hasRecordAudioPermission()) {
Log.i("[Controls Fragment] Asking for RECORD_AUDIO permission")
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
}
if (coreContext.isVideoCallOrConferenceActive() && !PermissionHelper.get().hasCameraPermission()) {
Log.i("[Controls Fragment] Asking for CAMERA permission")
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
}
if (permissionsRequiredList.isNotEmpty()) {
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
permissionsRequiredList.toArray(permissionsRequired)

View file

@ -19,6 +19,7 @@
*/
package org.linphone.activities.call.viewmodels
import android.Manifest
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlin.math.max
@ -74,6 +75,10 @@ class ControlsViewModel : ViewModel() {
MutableLiveData<Event<Boolean>>()
}
val askPermissionEvent: MutableLiveData<Event<String>> by lazy {
MutableLiveData<Event<String>>()
}
val somethingClickedEvent = MutableLiveData<Event<Boolean>>()
val onKeyClick: NumpadDigitListener = object : NumpadDigitListener {
@ -105,6 +110,10 @@ class ControlsViewModel : ViewModel() {
) {
if (state == Call.State.StreamsRunning) isVideoUpdateInProgress.value = false
if (coreContext.isVideoCallOrConferenceActive() && !PermissionHelper.get().hasCameraPermission()) {
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
}
updateUI()
}
@ -147,6 +156,11 @@ class ControlsViewModel : ViewModel() {
}
fun toggleMuteMicrophone() {
if (!PermissionHelper.get().hasRecordAudioPermission()) {
askPermissionEvent.value = Event(Manifest.permission.RECORD_AUDIO)
return
}
somethingClickedEvent.value = Event(true)
val micEnabled = coreContext.core.micEnabled()
coreContext.core.enableMic(!micEnabled)
@ -178,6 +192,11 @@ class ControlsViewModel : ViewModel() {
}
fun toggleVideo() {
if (!PermissionHelper.get().hasCameraPermission()) {
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
return
}
val core = coreContext.core
val currentCall = core.currentCall
val conference = core.conference
@ -314,6 +333,7 @@ class ControlsViewModel : ViewModel() {
fun updateMuteMicState() {
isMicrophoneMuted.value = !PermissionHelper.get().hasRecordAudioPermission() || !coreContext.core.micEnabled()
isMuteMicrophoneEnabled.value = coreContext.core.currentCall != null || coreContext.core.isInConference
}
private fun updateSpeakerState() {
@ -349,7 +369,8 @@ class ControlsViewModel : ViewModel() {
}
private fun updateVideoEnabled() {
isVideoEnabled.value = coreContext.isVideoCallOrConferenceActive()
val enabled = coreContext.isVideoCallOrConferenceActive()
isVideoEnabled.value = enabled
}
private fun updateConferenceState() {

View file

@ -5,15 +5,6 @@
<data>
<import type="android.view.View" />
<variable
name="toggleMicrophoneClickListener"
type="android.view.View.OnClickListener" />
<variable
name="toggleSpeakerClickListener"
type="android.view.View.OnClickListener" />
<variable
name="terminateCallClickListener"
type="android.view.View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.activities.call.viewmodels.CallViewModel" />
@ -99,7 +90,7 @@
android:orientation="horizontal">
<ImageView
android:onClick="@{toggleMicrophoneClickListener}"
android:onClick="@{() -> controlsViewModel.toggleMuteMicrophone()}"
android:selected="@{controlsViewModel.isMicrophoneMuted}"
android:contentDescription="@{controlsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
android:layout_width="match_parent"
@ -110,7 +101,7 @@
android:src="@drawable/micro" />
<ImageView
android:onClick="@{toggleSpeakerClickListener}"
android:onClick="@{() -> controlsViewModel.toggleSpeaker()}"
android:selected="@{controlsViewModel.isSpeakerSelected}"
android:contentDescription="@{controlsViewModel.isSpeakerSelected ? @string/content_description_disable_speaker : @string/content_description_enable_speaker}"
android:layout_width="match_parent"
@ -121,7 +112,7 @@
android:src="@drawable/speaker" />
<ImageView
android:onClick="@{terminateCallClickListener}"
android:onClick="@{() -> viewModel.terminateCall()}"
android:contentDescription="@string/content_description_terminate_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"