Improved READ_PHONE_STATE / READ_PHONE_NUMBERS permissions usage
This commit is contained in:
parent
c1dafcb9b9
commit
4337dd5da8
14 changed files with 125 additions and 27 deletions
|
@ -20,13 +20,13 @@
|
|||
|
||||
package org.linphone.activities.assistant.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.assistant.viewmodels.AbstractPhoneViewModel
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.PermissionHelper
|
||||
import org.linphone.utils.PhoneNumberUtils
|
||||
|
@ -41,19 +41,19 @@ abstract class AbstractPhoneFragment<T : ViewDataBinding> : GenericFragment<T>()
|
|||
) {
|
||||
if (requestCode == 0) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.i("[Assistant] READ_PHONE_STATE permission granted")
|
||||
Log.i("[Assistant] READ_PHONE_STATE/READ_PHONE_NUMBERS permission granted")
|
||||
updateFromDeviceInfo()
|
||||
} else {
|
||||
Log.w("[Assistant] READ_PHONE_STATE permission denied")
|
||||
Log.w("[Assistant] READ_PHONE_STATE/READ_PHONE_NUMBERS permission denied")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun checkPermission() {
|
||||
if (!resources.getBoolean(R.bool.isTablet)) {
|
||||
if (!PermissionHelper.get().hasReadPhoneState()) {
|
||||
Log.i("[Assistant] Asking for READ_PHONE_STATE permission")
|
||||
requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
|
||||
if (!PermissionHelper.get().hasReadPhoneStateOrPhoneNumbersPermission()) {
|
||||
Log.i("[Assistant] Asking for READ_PHONE_STATE/READ_PHONE_NUMBERS permission")
|
||||
Compatibility.requestReadPhoneStateOrNumbersPermission(requireActivity(), 0)
|
||||
} else {
|
||||
updateFromDeviceInfo()
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
|
|||
viewLifecycleOwner,
|
||||
{
|
||||
it.consume {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.i("[Controls Fragment] Asking for WRITE_EXTERNAL_STORAGE permission")
|
||||
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ class CallsViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
fun takeScreenshot() {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
askWriteExternalStoragePermissionEvent.value = Event(true)
|
||||
} else {
|
||||
currentCallViewModel.value?.takeScreenshot()
|
||||
|
|
|
@ -402,7 +402,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
}
|
||||
|
||||
binding.setAttachFileClickListener {
|
||||
if (PermissionHelper.get().hasReadExternalStorage() && PermissionHelper.get().hasCameraPermission()) {
|
||||
if (PermissionHelper.get().hasReadExternalStoragePermission() && PermissionHelper.get().hasCameraPermission()) {
|
||||
pickFile()
|
||||
} else {
|
||||
Log.i("[Chat Room] Asking for READ_EXTERNAL_STORAGE and CAMERA permissions")
|
||||
|
|
|
@ -70,7 +70,7 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() {
|
|||
return
|
||||
}
|
||||
|
||||
if (Version.sdkStrictlyBelow(Version.API29_ANDROID_10) && !PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (Version.sdkStrictlyBelow(Version.API29_ANDROID_10) && !PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
for (content in chatMessage.contents) {
|
||||
if (content.isFileTransfer) {
|
||||
Log.i("[Chat Messages] Android < 10 detected and WRITE_EXTERNAL_STORAGE permission isn't granted yet")
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
*/
|
||||
package org.linphone.activities.main.dialer.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Dialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
@ -44,9 +47,11 @@ import org.linphone.activities.navigateToConfigFileViewer
|
|||
import org.linphone.activities.navigateToContacts
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.DialerFragmentBinding
|
||||
import org.linphone.mediastream.Version
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.PermissionHelper
|
||||
|
||||
class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
||||
private lateinit var viewModel: DialerViewModel
|
||||
|
@ -164,6 +169,10 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
|||
viewModel.transferVisibility.value = sharedViewModel.pendingCallTransfer
|
||||
|
||||
checkForUpdate()
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) {
|
||||
checkPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
@ -185,6 +194,28 @@ class DialerFragment : SecureFragment<DialerFragmentBinding>() {
|
|||
viewModel.enteredUri.value = sharedViewModel.dialerUri
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
if (requestCode == 0) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.i("[Dialer] READ_PHONE_STATE permission has been granted")
|
||||
coreContext.initPhoneStateListener()
|
||||
}
|
||||
}
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
@TargetApi(Version.API23_MARSHMALLOW_60)
|
||||
private fun checkPermissions() {
|
||||
if (!PermissionHelper.get().hasReadPhoneStatePermission()) {
|
||||
Log.i("[Dialer] Asking for READ_PHONE_STATE permission")
|
||||
requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayDebugPopup() {
|
||||
val alertDialog = MaterialAlertDialogBuilder(requireContext())
|
||||
alertDialog.setTitle(getString(R.string.debug_popup_title))
|
||||
|
|
|
@ -69,7 +69,7 @@ class Api21Compatibility {
|
|||
}
|
||||
|
||||
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class Api21Compatibility {
|
|||
}
|
||||
|
||||
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class Api21Compatibility {
|
|||
}
|
||||
|
||||
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
|
||||
if (!PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (!PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
Log.e("[Media Store] Write external storage permission denied")
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
*/
|
||||
package org.linphone.compatibility
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.ContentValues
|
||||
|
@ -45,6 +47,20 @@ import org.linphone.utils.LinphoneUtils
|
|||
@TargetApi(29)
|
||||
class Api29Compatibility {
|
||||
companion object {
|
||||
fun hasReadPhoneStatePermission(context: Context): Boolean {
|
||||
val granted = Compatibility.hasPermission(context, Manifest.permission.READ_PHONE_STATE)
|
||||
if (granted) {
|
||||
Log.d("[Permission Helper] Permission READ_PHONE_STATE is granted")
|
||||
} else {
|
||||
Log.w("[Permission Helper] Permission READ_PHONE_STATE is denied")
|
||||
}
|
||||
return granted
|
||||
}
|
||||
|
||||
fun requestReadPhoneStatePermission(activity: Activity, code: Int) {
|
||||
activity.requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), code)
|
||||
}
|
||||
|
||||
fun createMessageChannel(
|
||||
context: Context,
|
||||
notificationManager: NotificationManagerCompat
|
||||
|
|
|
@ -19,15 +19,32 @@
|
|||
*/
|
||||
package org.linphone.compatibility
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.ShortcutManager
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
@TargetApi(30)
|
||||
class Api30Compatibility {
|
||||
companion object {
|
||||
fun hasReadPhoneNumbersPermission(context: Context): Boolean {
|
||||
val granted = Compatibility.hasPermission(context, Manifest.permission.READ_PHONE_NUMBERS)
|
||||
if (granted) {
|
||||
Log.d("[Permission Helper] Permission READ_PHONE_NUMBERS is granted")
|
||||
} else {
|
||||
Log.w("[Permission Helper] Permission READ_PHONE_NUMBERS is denied")
|
||||
}
|
||||
return granted
|
||||
}
|
||||
|
||||
fun requestReadPhoneNumbersPermission(activity: Activity, code: Int) {
|
||||
activity.requestPermissions(arrayOf(Manifest.permission.READ_PHONE_NUMBERS), code)
|
||||
}
|
||||
|
||||
fun removeChatRoomShortcut(context: Context, chatRoom: ChatRoom) {
|
||||
val peerAddress = chatRoom.peerAddress.asStringUriOnly()
|
||||
val localAddress = chatRoom.localAddress.asStringUriOnly()
|
||||
|
|
|
@ -44,6 +44,24 @@ class Compatibility {
|
|||
}
|
||||
}
|
||||
|
||||
// See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers
|
||||
fun hasReadPhoneStateOrNumbersPermission(context: Context): Boolean {
|
||||
return if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
|
||||
Api30Compatibility.hasReadPhoneNumbersPermission(context)
|
||||
} else {
|
||||
Api29Compatibility.hasReadPhoneStatePermission(context)
|
||||
}
|
||||
}
|
||||
|
||||
// See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers
|
||||
fun requestReadPhoneStateOrNumbersPermission(activity: Activity, code: Int) {
|
||||
if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) {
|
||||
Api30Compatibility.requestReadPhoneNumbersPermission(activity, code)
|
||||
} else {
|
||||
Api29Compatibility.requestReadPhoneStatePermission(activity, code)
|
||||
}
|
||||
}
|
||||
|
||||
fun getDeviceName(context: Context): String {
|
||||
return when (Version.sdkAboveOrEqual(Version.API25_NOUGAT_71)) {
|
||||
true -> Api25Compatibility.getDeviceName(context)
|
||||
|
|
|
@ -313,13 +313,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
|
||||
configureCore()
|
||||
|
||||
try {
|
||||
phoneStateListener =
|
||||
Compatibility.createPhoneListener(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
|
||||
} catch (exception: SecurityException) {
|
||||
val hasReadPhoneStatePermission = PermissionHelper.get().hasReadPhoneState()
|
||||
Log.e("[Context] Failed to create phone state listener: $exception, READ_PHONE_STATE permission status is $hasReadPhoneStatePermission")
|
||||
}
|
||||
initPhoneStateListener()
|
||||
|
||||
EmojiCompat.init(BundledEmojiCompatConfig(context))
|
||||
collator.strength = Collator.NO_DECOMPOSITION
|
||||
|
@ -410,6 +404,21 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
|
||||
/* Call related functions */
|
||||
|
||||
fun initPhoneStateListener() {
|
||||
if (PermissionHelper.get().hasReadPhoneStatePermission()) {
|
||||
try {
|
||||
phoneStateListener =
|
||||
Compatibility.createPhoneListener(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
|
||||
} catch (exception: SecurityException) {
|
||||
val hasReadPhoneStatePermission =
|
||||
PermissionHelper.get().hasReadPhoneStateOrPhoneNumbersPermission()
|
||||
Log.e("[Context] Failed to create phone state listener: $exception, READ_PHONE_STATE permission status is $hasReadPhoneStatePermission")
|
||||
}
|
||||
} else {
|
||||
Log.w("[Context] Can't create phone state listener, READ_PHONE_STATE permission isn't granted")
|
||||
}
|
||||
}
|
||||
|
||||
fun answerCallVideoUpdateRequest(call: Call, accept: Boolean) {
|
||||
val params = core.createCallParams(call)
|
||||
|
||||
|
@ -655,7 +664,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10) || PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10) || PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
for (content in message.contents) {
|
||||
if (content.isFile && content.filePath != null && content.userData == null) {
|
||||
addContentToMediaStore(content)
|
||||
|
@ -676,7 +685,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
|||
return
|
||||
}
|
||||
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10) || PermissionHelper.get().hasWriteExternalStorage()) {
|
||||
if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10) || PermissionHelper.get().hasWriteExternalStoragePermission()) {
|
||||
coroutineScope.launch {
|
||||
when (content.type) {
|
||||
"image" -> {
|
||||
|
|
|
@ -81,7 +81,7 @@ class TelecomHelper private constructor(context: Context) {
|
|||
@SuppressLint("MissingPermission")
|
||||
fun findExistingAccount(context: Context): PhoneAccount? {
|
||||
if (!PermissionHelper.exists()) PermissionHelper.create(context)
|
||||
if (PermissionHelper.get().hasReadPhoneState()) {
|
||||
if (PermissionHelper.get().hasReadPhoneStateOrPhoneNumbersPermission()) {
|
||||
var account: PhoneAccount? = null
|
||||
val phoneAccountHandleList: List<PhoneAccountHandle> =
|
||||
telecomManager.selfManagedPhoneAccounts
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.linphone.utils
|
|||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
|
@ -50,15 +52,19 @@ class PermissionHelper private constructor(private val context: Context) {
|
|||
return hasPermission(Manifest.permission.WRITE_CONTACTS)
|
||||
}
|
||||
|
||||
fun hasReadPhoneState(): Boolean {
|
||||
fun hasReadPhoneStatePermission(): Boolean {
|
||||
return hasPermission(Manifest.permission.READ_PHONE_STATE)
|
||||
}
|
||||
|
||||
fun hasReadExternalStorage(): Boolean {
|
||||
fun hasReadPhoneStateOrPhoneNumbersPermission(): Boolean {
|
||||
return Compatibility.hasReadPhoneStateOrNumbersPermission(context)
|
||||
}
|
||||
|
||||
fun hasReadExternalStoragePermission(): Boolean {
|
||||
return hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
fun hasWriteExternalStorage(): Boolean {
|
||||
fun hasWriteExternalStoragePermission(): Boolean {
|
||||
return hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
|
@ -70,6 +76,7 @@ class PermissionHelper private constructor(private val context: Context) {
|
|||
return hasPermission(Manifest.permission.RECORD_AUDIO)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
fun hasTelecomManagerPermissions(): Boolean {
|
||||
return hasPermission(Manifest.permission.READ_PHONE_NUMBERS) &&
|
||||
hasPermission(Manifest.permission.MANAGE_OWN_CALLS)
|
||||
|
|
|
@ -41,7 +41,7 @@ class PhoneNumberUtils {
|
|||
|
||||
@SuppressLint("MissingPermission", "HardwareIds")
|
||||
fun getDevicePhoneNumber(context: Context): String? {
|
||||
if (PermissionHelper.get().hasReadPhoneState()) {
|
||||
if (PermissionHelper.get().hasReadPhoneStateOrPhoneNumbersPermission()) {
|
||||
try {
|
||||
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
||||
return tm.line1Number
|
||||
|
|
Loading…
Reference in a new issue