Using TelephonyListener instead of PhoneStateListener that has been deprecated starting API 31
This commit is contained in:
parent
e65957f047
commit
2f912828ee
5 changed files with 194 additions and 33 deletions
|
@ -26,6 +26,7 @@ import android.content.pm.PackageManager
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
@ -50,6 +51,14 @@ class Compatibility {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createPhoneListener(telephonyManager: TelephonyManager): PhoneStateInterface {
|
||||||
|
return if (Version.sdkStrictlyBelow(Version.API31_ANDROID_12)) {
|
||||||
|
PhoneStateListener(telephonyManager)
|
||||||
|
} else {
|
||||||
|
TelephonyListener(telephonyManager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* UI */
|
/* UI */
|
||||||
|
|
||||||
fun setShowWhenLocked(activity: Activity, enable: Boolean) {
|
fun setShowWhenLocked(activity: Activity, enable: Boolean) {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.compatibility
|
||||||
|
|
||||||
|
interface PhoneStateInterface {
|
||||||
|
fun destroy()
|
||||||
|
|
||||||
|
fun isInCall(): Boolean
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.compatibility
|
||||||
|
|
||||||
|
import android.telephony.PhoneStateListener
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
|
class PhoneStateListener(private val telephonyManager: TelephonyManager) : PhoneStateInterface {
|
||||||
|
private var gsmCallActive = false
|
||||||
|
private val phoneStateListener = object : PhoneStateListener() {
|
||||||
|
override fun onCallStateChanged(state: Int, phoneNumber: String?) {
|
||||||
|
gsmCallActive = when (state) {
|
||||||
|
TelephonyManager.CALL_STATE_OFFHOOK -> {
|
||||||
|
Log.i("[Context] Phone state is off hook")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
TelephonyManager.CALL_STATE_RINGING -> {
|
||||||
|
Log.i("[Context] Phone state is ringing")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
TelephonyManager.CALL_STATE_IDLE -> {
|
||||||
|
Log.i("[Context] Phone state is idle")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Log.w("[Context] Phone state is unexpected: $state")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
Log.i("[Phone State Listener] Registering phone state listener")
|
||||||
|
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun destroy() {
|
||||||
|
Log.i("[Phone State Listener] Unregistering phone state listener")
|
||||||
|
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isInCall(): Boolean {
|
||||||
|
return gsmCallActive
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.compatibility
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.telephony.TelephonyCallback
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import java.util.concurrent.Executor
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
|
|
||||||
|
@TargetApi(31)
|
||||||
|
class TelephonyListener(private val telephonyManager: TelephonyManager) : PhoneStateInterface {
|
||||||
|
private var gsmCallActive = false
|
||||||
|
|
||||||
|
private fun runOnUiThreadExecutor(): Executor {
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
return Executor() {
|
||||||
|
handler.post(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class TelephonyListener : TelephonyCallback(), TelephonyCallback.CallStateListener {
|
||||||
|
override fun onCallStateChanged(state: Int) {
|
||||||
|
gsmCallActive = when (state) {
|
||||||
|
TelephonyManager.CALL_STATE_OFFHOOK -> {
|
||||||
|
Log.i("[Context] Phone state is off hook")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
TelephonyManager.CALL_STATE_RINGING -> {
|
||||||
|
Log.i("[Context] Phone state is ringing")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
TelephonyManager.CALL_STATE_IDLE -> {
|
||||||
|
Log.i("[Context] Phone state is idle")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Log.w("[Context] Phone state is unexpected: $state")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private val telephonyListener = TelephonyListener()
|
||||||
|
|
||||||
|
init {
|
||||||
|
Log.i("[Telephony Listener] Registering telephony callback")
|
||||||
|
telephonyManager.registerTelephonyCallback(runOnUiThreadExecutor(), telephonyListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun destroy() {
|
||||||
|
Log.i("[Telephony Listener] Unregistering telephony callback")
|
||||||
|
telephonyManager.unregisterTelephonyCallback(telephonyListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isInCall(): Boolean {
|
||||||
|
return gsmCallActive
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,6 @@ import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.security.keystore.KeyGenParameterSpec
|
import android.security.keystore.KeyGenParameterSpec
|
||||||
import android.security.keystore.KeyProperties
|
import android.security.keystore.KeyProperties
|
||||||
import android.telephony.PhoneStateListener
|
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Pair
|
import android.util.Pair
|
||||||
|
@ -56,6 +55,7 @@ import org.linphone.activities.call.CallActivity
|
||||||
import org.linphone.activities.call.IncomingCallActivity
|
import org.linphone.activities.call.IncomingCallActivity
|
||||||
import org.linphone.activities.call.OutgoingCallActivity
|
import org.linphone.activities.call.OutgoingCallActivity
|
||||||
import org.linphone.compatibility.Compatibility
|
import org.linphone.compatibility.Compatibility
|
||||||
|
import org.linphone.compatibility.PhoneStateInterface
|
||||||
import org.linphone.contact.Contact
|
import org.linphone.contact.Contact
|
||||||
import org.linphone.contact.ContactsManager
|
import org.linphone.contact.ContactsManager
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
|
@ -99,37 +99,13 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loggingService = Factory.instance().loggingService
|
private val loggingService = Factory.instance().loggingService
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
|
|
||||||
private var gsmCallActive = false
|
|
||||||
private val phoneStateListener = object : PhoneStateListener() {
|
|
||||||
override fun onCallStateChanged(state: Int, phoneNumber: String?) {
|
|
||||||
gsmCallActive = when (state) {
|
|
||||||
TelephonyManager.CALL_STATE_OFFHOOK -> {
|
|
||||||
Log.i("[Context] Phone state is off hook")
|
|
||||||
true
|
|
||||||
}
|
|
||||||
TelephonyManager.CALL_STATE_RINGING -> {
|
|
||||||
Log.i("[Context] Phone state is ringing")
|
|
||||||
true
|
|
||||||
}
|
|
||||||
TelephonyManager.CALL_STATE_IDLE -> {
|
|
||||||
Log.i("[Context] Phone state is idle")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Log.w("[Context] Phone state is unexpected: $state")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var overlayX = 0f
|
private var overlayX = 0f
|
||||||
private var overlayY = 0f
|
private var overlayY = 0f
|
||||||
private var callOverlay: View? = null
|
private var callOverlay: View? = null
|
||||||
private var previousCallState = Call.State.Idle
|
private var previousCallState = Call.State.Idle
|
||||||
|
private lateinit var phoneStateListener: PhoneStateInterface
|
||||||
|
|
||||||
private val listener: CoreListenerStub = object : CoreListenerStub() {
|
private val listener: CoreListenerStub = object : CoreListenerStub() {
|
||||||
override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||||
|
@ -159,6 +135,11 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
) {
|
) {
|
||||||
Log.i("[Context] Call state changed [$state]")
|
Log.i("[Context] Call state changed [$state]")
|
||||||
if (state == Call.State.IncomingReceived || state == Call.State.IncomingEarlyMedia) {
|
if (state == Call.State.IncomingReceived || state == Call.State.IncomingEarlyMedia) {
|
||||||
|
var gsmCallActive = false
|
||||||
|
if (::phoneStateListener.isInitialized) {
|
||||||
|
gsmCallActive = phoneStateListener.isInCall()
|
||||||
|
}
|
||||||
|
|
||||||
if (gsmCallActive) {
|
if (gsmCallActive) {
|
||||||
Log.w("[Context] Refusing the call with reason busy because a GSM call is active")
|
Log.w("[Context] Refusing the call with reason busy because a GSM call is active")
|
||||||
call.decline(Reason.Busy)
|
call.decline(Reason.Busy)
|
||||||
|
@ -324,9 +305,13 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
|
|
||||||
configureCore()
|
configureCore()
|
||||||
|
|
||||||
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
try {
|
||||||
Log.i("[Context] Registering phone state listener")
|
phoneStateListener =
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
EmojiCompat.init(BundledEmojiCompatConfig(context))
|
EmojiCompat.init(BundledEmojiCompatConfig(context))
|
||||||
collator.strength = Collator.NO_DECOMPOSITION
|
collator.strength = Collator.NO_DECOMPOSITION
|
||||||
|
@ -336,10 +321,9 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
Log.i("[Context] Stopping")
|
Log.i("[Context] Stopping")
|
||||||
coroutineScope.cancel()
|
coroutineScope.cancel()
|
||||||
|
|
||||||
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
|
if (::phoneStateListener.isInitialized) {
|
||||||
Log.i("[Context] Unregistering phone state listener")
|
phoneStateListener.destroy()
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
|
}
|
||||||
|
|
||||||
notificationsManager.destroy()
|
notificationsManager.destroy()
|
||||||
contactsManager.destroy()
|
contactsManager.destroy()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue