Auto enable Telecom Manager feature when app starts, asking for permissions if needed
This commit is contained in:
parent
701c464882
commit
5d2c1cb5d1
11 changed files with 126 additions and 28 deletions
|
@ -17,7 +17,7 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Voice recordings in chat feature
|
- Voice recordings in chat feature
|
||||||
- Allow video recording in chat file sharing
|
- Allow video recording in chat file sharing
|
||||||
- Unread messages indicator in chat conversation that separates read & unread messages
|
- 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
|
- New video call UI on foldable device like Galaxy Z Fold
|
||||||
- Setting to automatically record all calls
|
- Setting to automatically record all calls
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.GenericActivity
|
import org.linphone.activities.GenericActivity
|
||||||
import org.linphone.activities.SnackBarActivity
|
import org.linphone.activities.SnackBarActivity
|
||||||
|
@ -40,6 +41,8 @@ class AssistantActivity : GenericActivity(), SnackBarActivity {
|
||||||
sharedViewModel = ViewModelProvider(this)[SharedAssistantViewModel::class.java]
|
sharedViewModel = ViewModelProvider(this)[SharedAssistantViewModel::class.java]
|
||||||
|
|
||||||
coordinator = findViewById(R.id.coordinator)
|
coordinator = findViewById(R.id.coordinator)
|
||||||
|
|
||||||
|
corePreferences.firstStart = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showSnackBar(resourceId: Int) {
|
override fun showSnackBar(resourceId: Int) {
|
||||||
|
|
|
@ -148,7 +148,6 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin
|
||||||
|
|
||||||
if (coreContext.core.accountList.isEmpty()) {
|
if (coreContext.core.accountList.isEmpty()) {
|
||||||
if (corePreferences.firstStart) {
|
if (corePreferences.firstStart) {
|
||||||
corePreferences.firstStart = false
|
|
||||||
startActivity(Intent(this, AssistantActivity::class.java))
|
startActivity(Intent(this, AssistantActivity::class.java))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,11 @@ import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||||
import org.linphone.activities.navigateToConfigFileViewer
|
import org.linphone.activities.navigateToConfigFileViewer
|
||||||
import org.linphone.activities.navigateToContacts
|
import org.linphone.activities.navigateToContacts
|
||||||
|
import org.linphone.compatibility.Compatibility
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.DialerFragmentBinding
|
import org.linphone.databinding.DialerFragmentBinding
|
||||||
import org.linphone.mediastream.Version
|
import org.linphone.mediastream.Version
|
||||||
|
import org.linphone.telecom.TelecomHelper
|
||||||
import org.linphone.utils.AppUtils
|
import org.linphone.utils.AppUtils
|
||||||
import org.linphone.utils.DialogUtils
|
import org.linphone.utils.DialogUtils
|
||||||
import org.linphone.utils.Event
|
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(
|
viewModel.enteredUri.observe(
|
||||||
viewLifecycleOwner,
|
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}")
|
Log.i("[Dialer] Pending call transfer mode = ${sharedViewModel.pendingCallTransfer}")
|
||||||
viewModel.transferVisibility.value = 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")
|
Log.i("[Dialer] READ_PHONE_STATE permission has been granted")
|
||||||
coreContext.initPhoneStateListener()
|
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)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||||
private fun checkPermissions() {
|
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()) {
|
if (!PermissionHelper.get().hasReadPhoneStatePermission()) {
|
||||||
Log.i("[Dialer] Asking for READ_PHONE_STATE permission")
|
Log.i("[Dialer] Asking for READ_PHONE_STATE permission")
|
||||||
requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
|
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() {
|
private fun displayDebugPopup() {
|
||||||
val alertDialog = MaterialAlertDialogBuilder(requireContext())
|
val alertDialog = MaterialAlertDialogBuilder(requireContext())
|
||||||
alertDialog.setTitle(getString(R.string.debug_popup_title))
|
alertDialog.setTitle(getString(R.string.debug_popup_title))
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.activities.main.settings.fragments
|
package org.linphone.activities.main.settings.fragments
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -95,11 +94,7 @@ class CallSettingsFragment : GenericSettingFragment<SettingsCallFragmentBinding>
|
||||||
{
|
{
|
||||||
it.consume {
|
it.consume {
|
||||||
if (!PermissionHelper.get().hasTelecomManagerPermissions()) {
|
if (!PermissionHelper.get().hasTelecomManagerPermissions()) {
|
||||||
val permissions = arrayOf(
|
Compatibility.requestTelecomManagerPermission(requireActivity(), 1)
|
||||||
Manifest.permission.READ_PHONE_NUMBERS,
|
|
||||||
Manifest.permission.MANAGE_OWN_CALLS
|
|
||||||
)
|
|
||||||
requestPermissions(permissions, 1)
|
|
||||||
} else if (!TelecomHelper.exists()) {
|
} else if (!TelecomHelper.exists()) {
|
||||||
corePreferences.useTelecomManager = true
|
corePreferences.useTelecomManager = true
|
||||||
Log.w("[Telecom Helper] Doesn't exists yet, creating it")
|
Log.w("[Telecom Helper] Doesn't exists yet, creating it")
|
||||||
|
|
|
@ -73,6 +73,9 @@ class CallSettingsViewModel : GenericSettingsViewModel() {
|
||||||
TelecomHelper.get().removeAccount()
|
TelecomHelper.get().removeAccount()
|
||||||
TelecomHelper.get().destroy()
|
TelecomHelper.get().destroy()
|
||||||
TelecomHelper.destroy()
|
TelecomHelper.destroy()
|
||||||
|
|
||||||
|
Log.w("[Call Settings] Disabling Telecom Manager auto-enable")
|
||||||
|
prefs.manuallyDisabledTelecomManager = true
|
||||||
}
|
}
|
||||||
prefs.useTelecomManager = newValue
|
prefs.useTelecomManager = newValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.compatibility
|
package org.linphone.compatibility
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
@ -138,5 +139,15 @@ class Api26Compatibility {
|
||||||
fun changeAudioRouteForTelecomManager(connection: NativeCallWrapper, route: Int) {
|
fun changeAudioRouteForTelecomManager(connection: NativeCallWrapper, route: Int) {
|
||||||
connection.setAudioRoute(route)
|
connection.setAudioRoute(route)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestTelecomManagerPermission(activity: Activity, code: Int) {
|
||||||
|
activity.requestPermissions(
|
||||||
|
arrayOf(
|
||||||
|
Manifest.permission.READ_PHONE_STATE,
|
||||||
|
Manifest.permission.MANAGE_OWN_CALLS
|
||||||
|
),
|
||||||
|
code
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,16 @@ class Api30Compatibility {
|
||||||
activity.requestPermissions(arrayOf(Manifest.permission.READ_PHONE_NUMBERS), code)
|
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) {
|
fun removeChatRoomShortcut(context: Context, chatRoom: ChatRoom) {
|
||||||
val shortcutManager = context.getSystemService(ShortcutManager::class.java)
|
val shortcutManager = context.getSystemService(ShortcutManager::class.java)
|
||||||
val id = LinphoneUtils.getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)
|
val id = LinphoneUtils.getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)
|
||||||
|
|
|
@ -62,6 +62,14 @@ class Compatibility {
|
||||||
Api29Compatibility.requestReadPhoneStatePermission(activity, code)
|
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 {
|
fun getDeviceName(context: Context): String {
|
||||||
return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) {
|
return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) {
|
||||||
|
|
|
@ -317,6 +317,13 @@ class CorePreferences constructor(private val context: Context) {
|
||||||
config.setBool("audio", "android_disable_audio_focus_requests", value)
|
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
|
var fullScreenCallUI: Boolean
|
||||||
get() = config.getBool("app", "full_screen_call", true)
|
get() = config.getBool("app", "full_screen_call", true)
|
||||||
set(value) {
|
set(value) {
|
||||||
|
|
|
@ -204,7 +204,8 @@
|
||||||
layout="@layout/settings_widget_switch"
|
layout="@layout/settings_widget_switch"
|
||||||
linphone:title="@{@string/call_settings_pause_calls_lost_audio_focus_title}"
|
linphone:title="@{@string/call_settings_pause_calls_lost_audio_focus_title}"
|
||||||
linphone:listener="@{viewModel.pauseCallsWhenAudioFocusIsLostListener}"
|
linphone:listener="@{viewModel.pauseCallsWhenAudioFocusIsLostListener}"
|
||||||
linphone:checked="@={viewModel.pauseCallsWhenAudioFocusIsLost}"/>
|
linphone:checked="@={viewModel.pauseCallsWhenAudioFocusIsLost}"
|
||||||
|
linphone:enabled="@{!viewModel.useTelecomManager}"/>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/settings_widget_basic"
|
layout="@layout/settings_widget_basic"
|
||||||
|
|
Loading…
Reference in a new issue