9
votes

I'm trying to create an android full screen notification to show an activity over the lock screen, like an alarm clock.

The notification always occurs, but the activity is never started over the lock screen; it just rings and shows a notification icon on the lock screen if the phone is off. It shows a heads up notification if the phone is on as expected. A debug print indicates the notification channel is successfully registered at importance level HIGH/4 as requested.

I've tried it on 5 different android device versions: Android 10, 8.0.0, 6.0.1, 5.1.1

I've followed the android developers documentation linked below. I also linked a couple similar stack overflow questions.

https://developer.android.com/training/notify-user/time-sensitive

https://developer.android.com/training/notify-user/build-notification#urgent-message

Full screen intent not starting the activity but do show a notification on android 10

FullScreen Notification

Below is a very minimal version of the application code, an activity with 1 button to schedule the notification in the future with a broadcast receiver so it fires after the screen is locked.

    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    minSdkVersion 25
    targetSdkVersion 29

    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />

public class AppReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (FullscreenActivity.FULL_SCREEN_ACTION.equals(intent.getAction()))
            FullscreenActivity.CreateFullScreenNotification(context);
    }
}

public class FullscreenActivity extends AppCompatActivity {

    private static final String CHANNEL_ID = "my_channel";
    static final String FULL_SCREEN_ACTION = "FullScreenAction";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_fullscreen);
        createNotificationChannel(this);
    }

    /**
     * Use button to set alarm manager with a pending intent to create the full screen notification
     * after use has time to shut off device to test with the lock screen showing
     */
    public void buttonClick(View view) {
        Intent intent = new Intent(this, AppReceiver.class);
        intent.setAction(FULL_SCREEN_ACTION);
        PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (am != null) {
            am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 15000, pi);
        }
    }

    static void CreateFullScreenNotification(Context context) {
        Intent fullScreenIntent = new Intent(context, FullscreenActivity.class);
        fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);//?
        PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(context, 0,
                fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(context, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_launcher_background)
                        .setContentTitle("Full Screen Alarm Test")
                        .setContentText("This is a test")
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setCategory(NotificationCompat.CATEGORY_CALL)
                        .setDefaults(NotificationCompat.DEFAULT_ALL) //?
                        .setFullScreenIntent(fullScreenPendingIntent, true);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
        notificationManager.notify(1, notificationBuilder.build());
    }

    private static void createNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = context.getSystemService(NotificationManager.class);

            if (notificationManager != null && notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);
                channel.setDescription("channel_description");
                notificationManager.createNotificationChannel(channel);
            }

            //DEBUG print registered channel importance
            if (notificationManager != null && notificationManager.getNotificationChannel(CHANNEL_ID) != null) {
                Log.d("FullScreenActivity", "notification channel importance is " + notificationManager.getNotificationChannel(CHANNEL_ID).getImportance());
            }
        }
    }
}
4

4 Answers

9
votes

I was finally able to get this to work after finding this answer for an incoming call: https://stackoverflow.com/a/53192049/13008865

The part missing from the android document examples for full screen intents was that the activity the full screen intent tries to show needs a couple WindowManager.LayoutParams flags set: FLAG_SHOW_WHEN_LOCKED and FLAG_TURN_SCREEN_ON.

Here's the final minimal test app code I hope is useful for others trying to do an alarm clock type app. I tested successfully on the 4 OS versions listed above with target sdk 29 and minimum sdk 15. The only manifest permission needed was USE_FULL_SCREEN_INTENT and only for devices running android Q/29 and above.

public class AppReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (FullscreenActivity.FULL_SCREEN_ACTION.equals(intent.getAction()))
            FullscreenActivity.CreateFullScreenNotification(context);
    }
}

public class FullscreenActivity extends AppCompatActivity {

    private static final String CHANNEL_ID = "my_channel";
    static final String FULL_SCREEN_ACTION = "full_screen_action";
    static final int NOTIFICATION_ID = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_fullscreen);
        createNotificationChannel(this);

        //set flags so activity is showed when phone is off (on lock screen)
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    /**
     * Use button to set alarm manager with a pending intent to create the full screen notification
     * after use has time to shut off device to test with the lock screen showing
     */
    public void buttonClick(View view) {
        Intent intent = new Intent(FULL_SCREEN_ACTION, null, this, AppReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (alarmManager != null) {
            alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 15000, pendingIntent);
        }

        NotificationManagerCompat.from(this).cancel(NOTIFICATION_ID); //cancel last notification for repeated tests
    }

    static void CreateFullScreenNotification(Context context) {
        Intent intent = new Intent(context, FullscreenActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(context, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_launcher_background)
                        .setContentTitle("Full Screen Alarm Test")
                        .setContentText("This is a test")
                        .setPriority(NotificationCompat.PRIORITY_MAX)
                        .setCategory(NotificationCompat.CATEGORY_ALARM)
                        .setContentIntent(pendingIntent)
                        .setFullScreenIntent(pendingIntent, true);
        NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notificationBuilder.build());
    }

    private static void createNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

            if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) {
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);
                channel.setDescription("channel_description");
                notificationManager.createNotificationChannel(channel);
            }
        }
    }
}
1
votes
//use the following code it will work

//also put this in your Manifest.xml

 <uses-permission android:name="android.permission.WAKE_LOCK"/>
//put this in manifest in your specific activity you want to show on lock 
//screen
  android:showWhenLocked="true"

  getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    getWindow().addFlags(AccessibilityEventCompat.TYPE_WINDOWS_CHANGED);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
0
votes

For me, what helped was Ranjith Kumar's answer in this question.

Below is the same code, in Java:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
    // For newer than Android Oreo: call setShowWhenLocked, setTurnScreenOn
    setShowWhenLocked(true);
    setTurnScreenOn(true);

    // If you want to display the keyguard to prompt the user to unlock the phone:
    KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    keyguardManager.requestDismissKeyguard(this, null);
} else {
    // For older versions, do it as you did before.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
0
votes

I also had a similar issue, for me the problem was not with window Flags but when triggering notification both the notification channel should have IMPORTANCE_HIGH and notification with HIGH_PRIORITY and also of you are using redmi you have to set permission explicitly on app settings