androidandroid-activityalarmmanagerandroid-notificationsandroid-doze

Android Alarm - Activity Sometimes Remains Black After Keyguard Dismissal


I have an alarm activity, that launches from a service as a Full-Screen Notification Intent. The problem is that sometimes, the activity will remains black until I turn it off and on again.

Now, although the screen is black, the views respond to the touch

If I try to take a screenshot, I suddenly see the activity, and if I turn the screen off and on again, everything is working as expected.

I can't seem to reproduce this on my debug build, but it does happen to me on the "production" build from time to time. (Let's say 1/5 times)

It will happen in the morning in between snoozes, but never on the first alarm. (as far as I noticed)

Any idea on what is causing this, or how to reproduce this would help immensely.

Videos of the weirdness:

Responsive black screen

Turn off, and on again

Trying to take a screenshot

This is basically how I launch the activity:

val builder = NotificationCompat.Builder(context, NotificationChannels.CHANNEL_ALARM_SERVICE)
...
// set intent
val alarmIntent = Intent(context, AlarmActivity::class.java)
alarmIntent.putExtra(IntentExtras.KEY_ID, alarm.id)
builder.setFullScreenIntent(PendingIntent.getActivity(context, RequestCodes.REQUEST_CODE_ALARM_ACTIVITY, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT), true)
...
startForeground(...)

This is how I unlock the screen in the Activity's onCreate() method

public class ScreenUnlockerUtil {

    public static void unlockScreen(BaseActivity activity) {

        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            // in addition to flags
            activity.setShowWhenLocked(true);
            activity.setTurnScreenOn(true);
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        }


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            KeyguardManager keyguardManager = (KeyguardManager) activity.getSystemService(KEYGUARD_SERVICE);
            if (keyguardManager != null) {
                keyguardManager.requestDismissKeyguard(activity, new KeyguardManager.KeyguardDismissCallback() {
                    @Override
                    public void onDismissError() {
                        super.onDismissError();
                        ExceptionHandlerWrapper.reportException(new Exception("Keyguard Dismiss Error"));
                    }

                    @Override
                    public void onDismissSucceeded() {
                        super.onDismissSucceeded();
                        Timber.d("Keyguard Dismiss Success");
                    }

                    @Override
                    public void onDismissCancelled() {
                        super.onDismissCancelled();
                        ExceptionHandlerWrapper.reportException(new Exception("Keyguard Dismiss Cancelled"));
                    }
                });
            }
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
        }


    }
}

Edit 1: I'm not seeing any reports from my device regarding keyguard dismissal cancellation or error.

Edit 2: This is all happening on a Pixel 2 XL. Not some random crappy phone.


Solution

  • A very strange problem, I couldn't find the exact reason for it. But I could come up with a very stable solution, just add the following parameters to your manifest file and it should work. I have tried it like 15 times and never had the problem again, while I had it 1 out of 5 times with the code solution.

    Don't forget to delete the code lines in your onCreate.

        <activity android:name=".AlertActivity"
            android:showWhenLocked="true"
            android:turnScreenOn="true">
        </activity>