I'm building a VoIP calling app on Android using the Self Managed Telecom Framework, but I've hit a wall with the incoming call notification when the device is locked/sleeping/whatever it is.
This is my onCreate method in my Activity that gets displayed on an incoming call:
class IncomingCallFullScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
// For newer than Android Oreo: call setShowWhenLocked, setTurnScreenOn
setShowWhenLocked(true)
setTurnScreenOn(true)
Log.d(TAG, "onCreate(): O_MR1 logic applied")
} else {
// For older versions, do it as you did before.
window.addFlags(
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
)
Log.d(TAG, "onCreate(): PRE O_MR1 logic applied")
}
with(getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager) {
Log.d(TAG, "onCreate(): Requesting keyguard dismissal")
requestDismissKeyguard(this@IncomingCallFullScreenActivity, object : KeyguardManager.KeyguardDismissCallback() {
override fun onDismissError() {
Log.d(TAG, "onCreate(): onDismissError")
}
override fun onDismissSucceeded() {
Log.d(TAG, "onCreate(): onDismissSucceeded")
}
override fun onDismissCancelled() {
Log.d(TAG, "onCreate(): onDismissCancelled")
}
})
}
setContentView(R.layout.incoming_call_ringer_screen)
hideSystemUI()
}
private fun hideSystemUI() {
// Enables sticky immersive mode.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
window.insetsController?.let {
it.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
it.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
} else {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
}
}
}
And this works, but in I'd say 20% of cases, the keyguard doesn't dismiss properly. Instead of just showing my incoming call intention, it'll show the keyguard on top of it. If I press "return to call" on it, it'll work fine - if it dismiss it it works fine. But in those about 20% of cases, it doesn't dismiss properly as expected.
I've done my majority of testing on an Android X device, but I've seen it happen on Android 11 as well.
I've tried calling the requestDismissKeyguard function a few different places, such as onStart, onAttachedToWindow - but all with the same results.
I've got a feeling it's because this method needs to be called at some other point in the life cycle, but really I'm at a loss for what to try at this point.
This never happens in the emulator. Only on physical devices (I've tested on a Samsung Galaxy S9 and S21 Ultra).
The Android docs states that if the activity is in a trusted state, the keyguard will dismiss immediately. I can only assume that this means that some times this activity isn't in a trusted state.
This seems to be more prone to happen if the device has been locked / screen turned off for a little while.
In 80% of cases, the incoming call notification displays a-ok!