Trying to prevent or understand issues with incoming call activity
This commit is contained in:
parent
fe8524da14
commit
b6934e02fd
10 changed files with 106 additions and 30 deletions
|
@ -101,14 +101,11 @@
|
||||||
|
|
||||||
<activity android:name=".activities.call.CallActivity"
|
<activity android:name=".activities.call.CallActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:showWhenLocked="true"
|
|
||||||
android:supportsPictureInPicture="true" />
|
android:supportsPictureInPicture="true" />
|
||||||
|
|
||||||
<activity android:name=".activities.call.IncomingCallActivity"
|
<activity android:name=".activities.call.IncomingCallActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:noHistory="true"
|
android:noHistory="true" />
|
||||||
android:showWhenLocked="true"
|
|
||||||
android:turnScreenOn="true" />
|
|
||||||
|
|
||||||
<activity android:name=".activities.call.OutgoingCallActivity"
|
<activity android:name=".activities.call.OutgoingCallActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
|
|
@ -49,6 +49,7 @@ class CallActivity : ProximitySensorActivity() {
|
||||||
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
Compatibility.setShowWhenLocked(this, true)
|
Compatibility.setShowWhenLocked(this, true)
|
||||||
|
Compatibility.setTurnScreenOn(this, true)
|
||||||
|
|
||||||
binding = DataBindingUtil.setContentView(this, R.layout.call_activity)
|
binding = DataBindingUtil.setContentView(this, R.layout.call_activity)
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.linphone.activities.call
|
||||||
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.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
|
@ -47,22 +48,16 @@ class IncomingCallActivity : GenericActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
Compatibility.setShowWhenLocked(this, true)
|
|
||||||
Compatibility.setTurnScreenOn(this, true)
|
Compatibility.setTurnScreenOn(this, true)
|
||||||
|
Compatibility.setShowWhenLocked(this, true)
|
||||||
|
Compatibility.requestDismissKeyguard(this)
|
||||||
|
|
||||||
binding = DataBindingUtil.setContentView(this, R.layout.call_incoming_activity)
|
binding = DataBindingUtil.setContentView(this, R.layout.call_incoming_activity)
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
var incomingCall: Call? = null
|
var incomingCall: Call? = findIncomingCall()
|
||||||
for (call in coreContext.core.calls) {
|
|
||||||
if (call.state == Call.State.IncomingReceived ||
|
|
||||||
call.state == Call.State.IncomingEarlyMedia) {
|
|
||||||
incomingCall = call
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (incomingCall == null) {
|
if (incomingCall == null) {
|
||||||
Log.e("[Incoming Call] Couldn't find call in state Incoming")
|
Log.e("[Incoming Call Activity] Couldn't find call in state Incoming")
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -75,6 +70,14 @@ class IncomingCallActivity : GenericActivity() {
|
||||||
|
|
||||||
viewModel.callEndedEvent.observe(this, Observer {
|
viewModel.callEndedEvent.observe(this, Observer {
|
||||||
it.consume {
|
it.consume {
|
||||||
|
Log.i("[Incoming Call Activity] Call ended, finish activity")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.callConnectedEvent.observe(this, Observer {
|
||||||
|
it.consume {
|
||||||
|
Log.i("[Incoming Call Activity] Call connected, finish activity")
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -89,15 +92,25 @@ class IncomingCallActivity : GenericActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
var incomingCall: Call? = findIncomingCall()
|
||||||
|
if (incomingCall == null) {
|
||||||
|
Log.e("[Incoming Call Activity] Couldn't find call in state Incoming")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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("[Incoming Call] 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] 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()) {
|
||||||
|
@ -106,4 +119,14 @@ class IncomingCallActivity : GenericActivity() {
|
||||||
requestPermissions(permissionsRequired, 0)
|
requestPermissions(permissionsRequired, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findIncomingCall(): Call? {
|
||||||
|
for (call in coreContext.core.calls) {
|
||||||
|
if (call.state == Call.State.IncomingReceived ||
|
||||||
|
call.state == Call.State.IncomingEarlyMedia) {
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,17 +49,9 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
binding = DataBindingUtil.setContentView(this, R.layout.call_outgoing_activity)
|
binding = DataBindingUtil.setContentView(this, R.layout.call_outgoing_activity)
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
var outgoingCall: Call? = null
|
var outgoingCall: Call? = findOutgoingCall()
|
||||||
for (call in coreContext.core.calls) {
|
|
||||||
if (call.state == Call.State.OutgoingInit ||
|
|
||||||
call.state == Call.State.OutgoingProgress ||
|
|
||||||
call.state == Call.State.OutgoingRinging) {
|
|
||||||
outgoingCall = call
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outgoingCall == null) {
|
if (outgoingCall == null) {
|
||||||
Log.e("[Outgoing Call] Couldn't find call in state Outgoing")
|
Log.e("[Outgoing Call Activity] Couldn't find call in state Outgoing")
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -91,6 +83,14 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
|
|
||||||
viewModel.callEndedEvent.observe(this, Observer {
|
viewModel.callEndedEvent.observe(this, Observer {
|
||||||
it.consume {
|
it.consume {
|
||||||
|
Log.i("[Outgoing Call Activity] Call ended, finish activity")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.callConnectedEvent.observe(this, Observer {
|
||||||
|
it.consume {
|
||||||
|
Log.i("[Outgoing Call Activity] Call connected, finish activity")
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -100,15 +100,25 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
var outgoingCall: Call? = findOutgoingCall()
|
||||||
|
if (outgoingCall == null) {
|
||||||
|
Log.e("[Outgoing Call Activity] Couldn't find call in state Outgoing")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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("[Outgoing Call] Asking for RECORD_AUDIO permission")
|
Log.i("[Outgoing 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("[Outgoing Call] Asking for CAMERA permission")
|
Log.i("[Outgoing Call Activity] Asking for CAMERA permission")
|
||||||
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
|
permissionsRequiredList.add(android.Manifest.permission.CAMERA)
|
||||||
}
|
}
|
||||||
if (permissionsRequiredList.isNotEmpty()) {
|
if (permissionsRequiredList.isNotEmpty()) {
|
||||||
|
@ -117,4 +127,15 @@ class OutgoingCallActivity : ProximitySensorActivity() {
|
||||||
requestPermissions(permissionsRequired, 0)
|
requestPermissions(permissionsRequired, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun findOutgoingCall(): Call? {
|
||||||
|
for (call in coreContext.core.calls) {
|
||||||
|
if (call.state == Call.State.OutgoingInit ||
|
||||||
|
call.state == Call.State.OutgoingProgress ||
|
||||||
|
call.state == Call.State.OutgoingRinging) {
|
||||||
|
return call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,10 @@ open class CallViewModel(val call: Call) : GenericContactViewModel(call.remoteAd
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val callConnectedEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
private val listener = object : CallListenerStub() {
|
private val listener = object : CallListenerStub() {
|
||||||
override fun onStateChanged(call: Call, state: Call.State, message: String) {
|
override fun onStateChanged(call: Call, state: Call.State, message: String) {
|
||||||
if (call != this@CallViewModel.call) return
|
if (call != this@CallViewModel.call) return
|
||||||
|
@ -62,6 +66,8 @@ open class CallViewModel(val call: Call) : GenericContactViewModel(call.remoteAd
|
||||||
if (state == Call.State.Error) {
|
if (state == Call.State.Error) {
|
||||||
Log.e("[Call View Model] Error state reason is ${call.reason}")
|
Log.e("[Call View Model] Error state reason is ${call.reason}")
|
||||||
}
|
}
|
||||||
|
} else if (call.state == Call.State.Connected) {
|
||||||
|
callConnectedEvent.value = Event(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,5 +169,9 @@ class Api21Compatibility {
|
||||||
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestDismissKeyguard(activity: Activity) {
|
||||||
|
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.linphone.compatibility
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.*
|
import android.app.*
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
@TargetApi(27)
|
@TargetApi(27)
|
||||||
class Api27Compatibility {
|
class Api27Compatibility {
|
||||||
|
@ -32,5 +33,10 @@ class Api27Compatibility {
|
||||||
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
|
fun setTurnScreenOn(activity: Activity, enable: Boolean) {
|
||||||
activity.setTurnScreenOn(enable)
|
activity.setTurnScreenOn(enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestDismissKeyguard(activity: Activity) {
|
||||||
|
val keyguardManager = activity.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
keyguardManager.requestDismissKeyguard(activity, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,14 @@ class Compatibility {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requestDismissKeyguard(activity: Activity) {
|
||||||
|
if (Version.sdkStrictlyBelow(Version.API27_OREO_81)) {
|
||||||
|
Api21Compatibility.requestDismissKeyguard(activity)
|
||||||
|
} else {
|
||||||
|
Api27Compatibility.requestDismissKeyguard(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
|
|
||||||
fun createNotificationChannels(
|
fun createNotificationChannels(
|
||||||
|
|
|
@ -30,7 +30,6 @@ import android.telephony.PhoneStateListener
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.activities.call.CallActivity
|
import org.linphone.activities.call.CallActivity
|
||||||
|
@ -435,6 +434,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
/* Start call related activities */
|
/* Start call related activities */
|
||||||
|
|
||||||
private fun onIncomingReceived() {
|
private fun onIncomingReceived() {
|
||||||
|
Log.i("[Context] Starting IncomingCallActivity")
|
||||||
val intent = Intent(context, IncomingCallActivity::class.java)
|
val intent = Intent(context, IncomingCallActivity::class.java)
|
||||||
// This flag is required to start an Activity from a Service context
|
// This flag is required to start an Activity from a Service context
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
@ -442,6 +442,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onOutgoingStarted() {
|
private fun onOutgoingStarted() {
|
||||||
|
Log.i("[Context] Starting OutgoingCallActivity")
|
||||||
val intent = Intent(context, OutgoingCallActivity::class.java)
|
val intent = Intent(context, OutgoingCallActivity::class.java)
|
||||||
// This flag is required to start an Activity from a Service context
|
// This flag is required to start an Activity from a Service context
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
@ -449,6 +450,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCallStarted() {
|
private fun onCallStarted() {
|
||||||
|
Log.i("[Context] Starting CallActivity")
|
||||||
val intent = Intent(context, CallActivity::class.java)
|
val intent = Intent(context, CallActivity::class.java)
|
||||||
// This flag is required to start an Activity from a Service context
|
// This flag is required to start an Activity from a Service context
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
||||||
|
|
|
@ -343,6 +343,11 @@ class NotificationsManager(private val context: Context) {
|
||||||
val address = call.remoteAddress.asStringUriOnly()
|
val address = call.remoteAddress.asStringUriOnly()
|
||||||
val notifiable = getNotifiableForCall(call)
|
val notifiable = getNotifiableForCall(call)
|
||||||
|
|
||||||
|
if (notifiable.notificationId == currentForegroundServiceNotificationId) {
|
||||||
|
Log.w("[Notifications Manager] Incoming call notification already displayed by foreground service, skipping")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
|
val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
|
||||||
val pictureUri = contact?.getContactThumbnailPictureUri()
|
val pictureUri = contact?.getContactThumbnailPictureUri()
|
||||||
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
|
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
|
||||||
|
@ -380,10 +385,13 @@ class NotificationsManager(private val context: Context) {
|
||||||
.addAction(getCallAnswerAction(notifiable.notificationId))
|
.addAction(getCallAnswerAction(notifiable.notificationId))
|
||||||
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
|
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
|
||||||
.build()
|
.build()
|
||||||
notify(notifiable.notificationId, notification)
|
|
||||||
|
|
||||||
if (useAsForeground) {
|
if (useAsForeground) {
|
||||||
|
Log.i("[Notifications Manager] Notifying incoming call notification for foreground service")
|
||||||
startForeground(notifiable.notificationId, notification)
|
startForeground(notifiable.notificationId, notification)
|
||||||
|
} else {
|
||||||
|
Log.i("[Notifications Manager] Notifying incoming call notification")
|
||||||
|
notify(notifiable.notificationId, notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue