In-call audio/camera permissions improvements
This commit is contained in:
parent
1ad5d31426
commit
19fe8dd57b
5 changed files with 108 additions and 33 deletions
|
@ -19,9 +19,11 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.call
|
package org.linphone.activities.call
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.KeyguardManager
|
import android.app.KeyguardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
@ -113,10 +115,12 @@ class IncomingCallActivity : GenericActivity() {
|
||||||
Log.i("[Incoming Call Activity] Asking for RECORD_AUDIO permission")
|
Log.i("[Incoming Call Activity] Asking for RECORD_AUDIO permission")
|
||||||
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
|
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.call.currentParams.videoEnabled() && !PermissionHelper.get().hasCameraPermission()) {
|
if (viewModel.call.currentParams.videoEnabled() && !PermissionHelper.get().hasCameraPermission()) {
|
||||||
Log.i("[Incoming Call Activity] Asking for CAMERA permission")
|
Log.i("[Incoming Call Activity] Asking for CAMERA permission")
|
||||||
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
|
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permissionsRequiredList.isNotEmpty()) {
|
if (permissionsRequiredList.isNotEmpty()) {
|
||||||
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
|
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
|
||||||
permissionsRequiredList.toArray(permissionsRequired)
|
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? {
|
private fun findIncomingCall(): Call? {
|
||||||
for (call in coreContext.core.calls) {
|
for (call in coreContext.core.calls) {
|
||||||
if (call.state == Call.State.IncomingReceived ||
|
if (call.state == Call.State.IncomingReceived ||
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.call
|
package org.linphone.activities.call
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
|
@ -64,22 +66,6 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
controlsViewModel = ViewModelProvider(this).get(ControlsViewModel::class.java)
|
controlsViewModel = ViewModelProvider(this).get(ControlsViewModel::class.java)
|
||||||
binding.controlsViewModel = controlsViewModel
|
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, {
|
viewModel.callEndedEvent.observe(this, {
|
||||||
it.consume {
|
it.consume {
|
||||||
Log.i("[Outgoing Call Activity] Call ended, finish activity")
|
Log.i("[Outgoing Call Activity] Call ended, finish activity")
|
||||||
|
@ -98,6 +84,12 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
enableProximitySensor(!it)
|
enableProximitySensor(!it)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
controlsViewModel.askPermissionEvent.observe(this, {
|
||||||
|
it.consume { permission ->
|
||||||
|
requestPermissions(arrayOf(permission), 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||||
checkPermissions()
|
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? {
|
private fun findOutgoingCall(): Call? {
|
||||||
for (call in coreContext.core.calls) {
|
for (call in coreContext.core.calls) {
|
||||||
if (call.state == Call.State.OutgoingInit ||
|
if (call.state == Call.State.OutgoingInit ||
|
||||||
|
|
|
@ -19,13 +19,15 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.call.fragments
|
package org.linphone.activities.call.fragments
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.GenericFragment
|
import org.linphone.activities.GenericFragment
|
||||||
import org.linphone.activities.call.viewmodels.CallsViewModel
|
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, {
|
controlsViewModel.somethingClickedEvent.observe(viewLifecycleOwner, {
|
||||||
it.consume {
|
it.consume {
|
||||||
sharedViewModel.resetHiddenInterfaceTimerInVideoCallEvent.value = Event(true)
|
sharedViewModel.resetHiddenInterfaceTimerInVideoCallEvent.value = Event(true)
|
||||||
|
@ -138,20 +147,37 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
|
||||||
permissions: Array<out String>,
|
permissions: Array<out String>,
|
||||||
grantResults: IntArray
|
grantResults: IntArray
|
||||||
) {
|
) {
|
||||||
if (requestCode == 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
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")
|
Log.i("[Controls Fragment] RECORD_AUDIO permission has been granted")
|
||||||
controlsViewModel.updateMuteMicState()
|
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)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||||
private fun checkPermissions() {
|
private fun checkPermissions() {
|
||||||
val permissionsRequiredList = arrayListOf<String>()
|
val permissionsRequiredList = arrayListOf<String>()
|
||||||
|
|
||||||
if (!PermissionHelper.get().hasRecordAudioPermission()) {
|
if (!PermissionHelper.get().hasRecordAudioPermission()) {
|
||||||
Log.i("[Controls Fragment] Asking for RECORD_AUDIO permission")
|
Log.i("[Controls Fragment] Asking for RECORD_AUDIO permission")
|
||||||
permissionsRequiredList.add(android.Manifest.permission.RECORD_AUDIO)
|
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()) {
|
if (permissionsRequiredList.isNotEmpty()) {
|
||||||
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
|
val permissionsRequired = arrayOfNulls<String>(permissionsRequiredList.size)
|
||||||
permissionsRequiredList.toArray(permissionsRequired)
|
permissionsRequiredList.toArray(permissionsRequired)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.call.viewmodels
|
package org.linphone.activities.call.viewmodels
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
@ -74,6 +75,10 @@ class ControlsViewModel : ViewModel() {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val askPermissionEvent: MutableLiveData<Event<String>> by lazy {
|
||||||
|
MutableLiveData<Event<String>>()
|
||||||
|
}
|
||||||
|
|
||||||
val somethingClickedEvent = MutableLiveData<Event<Boolean>>()
|
val somethingClickedEvent = MutableLiveData<Event<Boolean>>()
|
||||||
|
|
||||||
val onKeyClick: NumpadDigitListener = object : NumpadDigitListener {
|
val onKeyClick: NumpadDigitListener = object : NumpadDigitListener {
|
||||||
|
@ -105,6 +110,10 @@ class ControlsViewModel : ViewModel() {
|
||||||
) {
|
) {
|
||||||
if (state == Call.State.StreamsRunning) isVideoUpdateInProgress.value = false
|
if (state == Call.State.StreamsRunning) isVideoUpdateInProgress.value = false
|
||||||
|
|
||||||
|
if (coreContext.isVideoCallOrConferenceActive() && !PermissionHelper.get().hasCameraPermission()) {
|
||||||
|
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
|
||||||
|
}
|
||||||
|
|
||||||
updateUI()
|
updateUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +156,11 @@ class ControlsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleMuteMicrophone() {
|
fun toggleMuteMicrophone() {
|
||||||
|
if (!PermissionHelper.get().hasRecordAudioPermission()) {
|
||||||
|
askPermissionEvent.value = Event(Manifest.permission.RECORD_AUDIO)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
somethingClickedEvent.value = Event(true)
|
somethingClickedEvent.value = Event(true)
|
||||||
val micEnabled = coreContext.core.micEnabled()
|
val micEnabled = coreContext.core.micEnabled()
|
||||||
coreContext.core.enableMic(!micEnabled)
|
coreContext.core.enableMic(!micEnabled)
|
||||||
|
@ -178,6 +192,11 @@ class ControlsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleVideo() {
|
fun toggleVideo() {
|
||||||
|
if (!PermissionHelper.get().hasCameraPermission()) {
|
||||||
|
askPermissionEvent.value = Event(Manifest.permission.CAMERA)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val core = coreContext.core
|
val core = coreContext.core
|
||||||
val currentCall = core.currentCall
|
val currentCall = core.currentCall
|
||||||
val conference = core.conference
|
val conference = core.conference
|
||||||
|
@ -314,6 +333,7 @@ class ControlsViewModel : ViewModel() {
|
||||||
|
|
||||||
fun updateMuteMicState() {
|
fun updateMuteMicState() {
|
||||||
isMicrophoneMuted.value = !PermissionHelper.get().hasRecordAudioPermission() || !coreContext.core.micEnabled()
|
isMicrophoneMuted.value = !PermissionHelper.get().hasRecordAudioPermission() || !coreContext.core.micEnabled()
|
||||||
|
isMuteMicrophoneEnabled.value = coreContext.core.currentCall != null || coreContext.core.isInConference
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSpeakerState() {
|
private fun updateSpeakerState() {
|
||||||
|
@ -349,7 +369,8 @@ class ControlsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateVideoEnabled() {
|
private fun updateVideoEnabled() {
|
||||||
isVideoEnabled.value = coreContext.isVideoCallOrConferenceActive()
|
val enabled = coreContext.isVideoCallOrConferenceActive()
|
||||||
|
isVideoEnabled.value = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateConferenceState() {
|
private fun updateConferenceState() {
|
||||||
|
|
|
@ -5,15 +5,6 @@
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<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
|
<variable
|
||||||
name="viewModel"
|
name="viewModel"
|
||||||
type="org.linphone.activities.call.viewmodels.CallViewModel" />
|
type="org.linphone.activities.call.viewmodels.CallViewModel" />
|
||||||
|
@ -99,7 +90,7 @@
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:onClick="@{toggleMicrophoneClickListener}"
|
android:onClick="@{() -> controlsViewModel.toggleMuteMicrophone()}"
|
||||||
android:selected="@{controlsViewModel.isMicrophoneMuted}"
|
android:selected="@{controlsViewModel.isMicrophoneMuted}"
|
||||||
android:contentDescription="@{controlsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
android:contentDescription="@{controlsViewModel.isMicrophoneMuted ? @string/content_description_disable_mic_mute : @string/content_description_enable_mic_mute}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -110,7 +101,7 @@
|
||||||
android:src="@drawable/micro" />
|
android:src="@drawable/micro" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:onClick="@{toggleSpeakerClickListener}"
|
android:onClick="@{() -> controlsViewModel.toggleSpeaker()}"
|
||||||
android:selected="@{controlsViewModel.isSpeakerSelected}"
|
android:selected="@{controlsViewModel.isSpeakerSelected}"
|
||||||
android:contentDescription="@{controlsViewModel.isSpeakerSelected ? @string/content_description_disable_speaker : @string/content_description_enable_speaker}"
|
android:contentDescription="@{controlsViewModel.isSpeakerSelected ? @string/content_description_disable_speaker : @string/content_description_enable_speaker}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -121,7 +112,7 @@
|
||||||
android:src="@drawable/speaker" />
|
android:src="@drawable/speaker" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:onClick="@{terminateCallClickListener}"
|
android:onClick="@{() -> viewModel.terminateCall()}"
|
||||||
android:contentDescription="@string/content_description_terminate_call"
|
android:contentDescription="@string/content_description_terminate_call"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
Loading…
Reference in a new issue