Auto enable Telecom Manager feature when app starts, asking for permissions if needed

This commit is contained in:
Sylvain Berfini 2021-11-12 10:34:56 +01:00
parent 701c464882
commit 5d2c1cb5d1
11 changed files with 126 additions and 28 deletions

View file

@ -17,7 +17,7 @@ Group changes to describe their impact on the project, as follows:
- Voice recordings in chat feature
- Allow video recording in chat file sharing
- Unread messages indicator in chat conversation that separates read & unread messages
- Notify incoming/outgoing calls on bluetooth devices using self-managed connections from telecom manager API
- Notify incoming/outgoing calls on bluetooth devices using self-managed connections from telecom manager API (disables SDK audio focus)
- New video call UI on foldable device like Galaxy Z Fold
- Setting to automatically record all calls

View file

@ -23,6 +23,7 @@ import android.os.Bundle
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.snackbar.Snackbar
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.activities.GenericActivity
import org.linphone.activities.SnackBarActivity
@ -40,6 +41,8 @@ class AssistantActivity : GenericActivity(), SnackBarActivity {
sharedViewModel = ViewModelProvider(this)[SharedAssistantViewModel::class.java]
coordinator = findViewById(R.id.coordinator)
corePreferences.firstStart = false
}
override fun showSnackBar(resourceId: Int) {

View file

@ -148,7 +148,6 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
if (coreContext.core.accountList.isEmpty()) {
if (corePreferences.firstStart) {
corePreferences.firstStart = false
startActivity(Intent(this, AssistantActivity::class.java))
}
}

View file

@ -45,9 +45,11 @@ import org.linphone.activities.main.viewmodels.DialogViewModel
import org.linphone.activities.main.viewmodels.SharedMainViewModel
import org.linphone.activities.navigateToConfigFileViewer
import org.linphone.activities.navigateToContacts
import org.linphone.compatibility.Compatibility
import org.linphone.core.tools.Log
import org.linphone.databinding.DialerFragmentBinding
import org.linphone.mediastream.Version
import org.linphone.telecom.TelecomHelper
import org.linphone.utils.AppUtils
import org.linphone.utils.DialogUtils
import org.linphone.utils.Event
@ -108,25 +110,6 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
}
}
if (arguments?.containsKey("Transfer") == true) {
sharedViewModel.pendingCallTransfer = arguments?.getBoolean("Transfer") ?: false
Log.i("[Dialer] Is pending call transfer: ${sharedViewModel.pendingCallTransfer}")
}
if (arguments?.containsKey("URI") == true) {
val address = arguments?.getString("URI") ?: ""
Log.i("[Dialer] Found URI to call: $address")
val skipAutoCall = arguments?.getBoolean("SkipAutoCallStart") ?: false
if (corePreferences.callRightAway && !skipAutoCall) {
Log.i("[Dialer] Call right away setting is enabled, start the call to $address")
viewModel.directCall(address)
} else {
sharedViewModel.dialerUri = address
}
}
arguments?.clear()
viewModel.enteredUri.observe(
viewLifecycleOwner,
{
@ -166,6 +149,30 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
}
)
if (corePreferences.firstStart) {
Log.w("[Dialer] First start detected, wait for assistant to be finished to check for update & request permissions")
return
}
if (arguments?.containsKey("Transfer") == true) {
sharedViewModel.pendingCallTransfer = arguments?.getBoolean("Transfer") ?: false
Log.i("[Dialer] Is pending call transfer: ${sharedViewModel.pendingCallTransfer}")
}
if (arguments?.containsKey("URI") == true) {
val address = arguments?.getString("URI") ?: ""
Log.i("[Dialer] Found URI to call: $address")
val skipAutoCall = arguments?.getBoolean("SkipAutoCallStart") ?: false
if (corePreferences.callRightAway && !skipAutoCall) {
Log.i("[Dialer] Call right away setting is enabled, start the call to $address")
viewModel.directCall(address)
} else {
sharedViewModel.dialerUri = address
}
}
arguments?.clear()
Log.i("[Dialer] Pending call transfer mode = ${sharedViewModel.pendingCallTransfer}")
viewModel.transferVisibility.value = sharedViewModel.pendingCallTransfer
@ -205,18 +212,72 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
Log.i("[Dialer] READ_PHONE_STATE permission has been granted")
coreContext.initPhoneStateListener()
}
checkTelecomManagerPermissions()
} else if (requestCode == 1) {
var allGranted = true
for (result in grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false
}
}
if (allGranted) {
Log.i("[Dialer] Telecom Manager permission have been granted")
enableTelecomManager()
} else {
Log.w("[Dialer] Telecom Manager permission have been denied (at least one of them)")
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
@TargetApi(Version.API23_MARSHMALLOW_60)
private fun checkPermissions() {
checkReadPhoneStatePermission()
if (Version.sdkAboveOrEqual(Version.API26_O_80) && PermissionHelper.get().hasReadPhoneStatePermission()) {
// Don't check the following the previous permission is being asked
checkTelecomManagerPermissions()
}
}
@TargetApi(Version.API23_MARSHMALLOW_60)
private fun checkReadPhoneStatePermission() {
if (!PermissionHelper.get().hasReadPhoneStatePermission()) {
Log.i("[Dialer] Asking for READ_PHONE_STATE permission")
requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
}
}
@TargetApi(Version.API26_O_80)
private fun checkTelecomManagerPermissions() {
if (!corePreferences.useTelecomManager) {
Log.i("[Dialer] Telecom Manager feature is disabled")
if (corePreferences.manuallyDisabledTelecomManager) {
Log.w("[Dialer] User has manually disabled Telecom Manager feature")
} else {
if (PermissionHelper.get().hasTelecomManagerPermissions()) {
enableTelecomManager()
} else {
Log.i("[Dialer] Asking for Telecom Manager permissions")
Compatibility.requestTelecomManagerPermission(requireActivity(), 1)
}
}
} else {
Log.i("[Dialer] Telecom Manager feature is already enabled")
}
}
@TargetApi(Version.API26_O_80)
private fun enableTelecomManager() {
Log.i("[Dialer] Telecom Manager permissions granted")
if (!TelecomHelper.exists()) {
Log.i("[Dialer] Creating Telecom Helper")
TelecomHelper.create(requireContext())
} else {
Log.e("[Dialer] Telecom Manager was already created ?!")
}
corePreferences.useTelecomManager = true
}
private fun displayDebugPopup() {
val alertDialog = MaterialAlertDialogBuilder(requireContext())
alertDialog.setTitle(getString(R.string.debug_popup_title))

View file

@ -19,7 +19,6 @@
*/
package org.linphone.activities.main.settings.fragments
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
@ -95,11 +94,7 @@ class CallSettingsFragment : GenericSettingFragment<SettingsCallFragmentBinding>
{
it.consume {
if (!PermissionHelper.get().hasTelecomManagerPermissions()) {
val permissions = arrayOf(
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.MANAGE_OWN_CALLS
)
requestPermissions(permissions, 1)
Compatibility.requestTelecomManagerPermission(requireActivity(), 1)
} else if (!TelecomHelper.exists()) {
corePreferences.useTelecomManager = true
Log.w("[Telecom Helper] Doesn't exists yet, creating it")

View file

@ -73,6 +73,9 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
TelecomHelper.get().removeAccount()
TelecomHelper.get().destroy()
TelecomHelper.destroy()
Log.w("[Call Settings] Disabling Telecom Manager auto-enable")
prefs.manuallyDisabledTelecomManager = true
}
prefs.useTelecomManager = newValue
}

View file

@ -19,6 +19,7 @@
*/
package org.linphone.compatibility
import android.Manifest
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
@ -138,5 +139,15 @@ class Api26Compatibility {
fun changeAudioRouteForTelecomManager(connection: NativeCallWrapper, route: Int) {
connection.setAudioRoute(route)
}
fun requestTelecomManagerPermission(activity: Activity, code: Int) {
activity.requestPermissions(
arrayOf(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.MANAGE_OWN_CALLS
),
code
)
}
}
}

View file

@ -45,6 +45,16 @@ class Api30Compatibility {
activity.requestPermissions(arrayOf(Manifest.permission.READ_PHONE_NUMBERS), code)
}
fun requestTelecomManagerPermission(activity: Activity, code: Int) {
activity.requestPermissions(
arrayOf(
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.MANAGE_OWN_CALLS
),
code
)
}
fun removeChatRoomShortcut(context: Context, chatRoom: ChatRoom) {
val shortcutManager = context.getSystemService(ShortcutManager::class.java)
val id = LinphoneUtils.getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)

View file

@ -62,6 +62,14 @@ class Compatibility {
Api29Compatibility.requestReadPhoneStatePermission(activity, code)
}
}
// See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers
fun requestTelecomManagerPermission(activity: Activity, code: Int) {
if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
Api30Compatibility.requestTelecomManagerPermission(activity, code)
} else {
Api26Compatibility.requestTelecomManagerPermission(activity, code)
}
}
fun getDeviceName(context: Context): String {
return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) {

View file

@ -317,6 +317,13 @@ class CorePreferences constructor(private val context: Context) {
config.setBool("audio", "android_disable_audio_focus_requests", value)
}
// We will try to auto enable Telecom Manager feature, but in case user disables it don't try again
var manuallyDisabledTelecomManager: Boolean
get() = config.getBool("app", "user_disabled_self_managed_telecom_manager", false)
set(value) {
config.setBool("app", "user_disabled_self_managed_telecom_manager", value)
}
var fullScreenCallUI: Boolean
get() = config.getBool("app", "full_screen_call", true)
set(value) {

View file

@ -204,7 +204,8 @@
layout="@layout/settings_widget_switch"
linphone:title="@{@string/call_settings_pause_calls_lost_audio_focus_title}"
linphone:listener="@{viewModel.pauseCallsWhenAudioFocusIsLostListener}"
linphone:checked="@={viewModel.pauseCallsWhenAudioFocusIsLost}"/>
linphone:checked="@={viewModel.pauseCallsWhenAudioFocusIsLost}"
linphone:enabled="@{!viewModel.useTelecomManager}"/>
<include
layout="@layout/settings_widget_basic"