Android 全屏通知不会显示在锁定屏幕上

标签 android android-notifications android-alarms lockscreen

我正在尝试创建一个 android 全屏通知以在锁定屏幕上显示 Activity ,例如闹钟。

通知总是发生,但 Activity 永远不会在锁定屏幕上启动;如果手机关机,它只会响铃并在锁定屏幕上显示通知图标。如果手机按预期开机,它会显示提示通知。调试打印表明通知 channel 已按要求成功注册在重要性级别 HIGH/4。

我已经在 5 种不同的 Android 设备版本上进行了尝试:Android 10、8.0.0、6.0.1、5.1.1

我遵循了下面链接的 android 开发人员文档。我还链接了几个类似的堆栈溢出问题。

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

下面是应用程序代码的一个非常小的版本,一个带有 1 个按钮的 Activity ,用于在 future 使用广播接收器安排通知,以便在屏幕锁定后触发。

    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());
            }
        }
    }
}

最佳答案

在找到来电的答案后,我终于能够让它工作:
https://stackoverflow.com/a/53192049/13008865

全屏 Intent 的 android 文档示例中缺少的部分是全屏 Intent 尝试显示的 Activity 需要设置几个 WindowManager.LayoutParams 标志:
FLAG_SHOW_WHEN_LOCKED 和 FLAG_TURN_SCREEN_ON。

这是最终的最小测试应用程序代码,我希望对其他尝试做闹钟类型应用程序的人有用。我在上面列出的 4 个操作系统版本上成功测试了目标 sdk 29 和最低 sdk 15。唯一需要的 list 权限是 USE_FULL_SCREEN_INTENT 并且仅适用于运行 android Q/29 及更高版本的设备。

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);
            }
        }
    }
}

关于Android 全屏通知不会显示在锁定屏幕上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60535947/

相关文章:

android - 如何设置警报和通知?

android - 安卓报警应用

android - ADT 布局编辑器中的抽屉导航呈现错误

android - 如何将自定义对象的 arraylist 从一个 java 类传递到另一个 java 类?

android - 加载均匀矩阵 1104 GL_Invalid_Operation Android OpenGLES 2.0

flutter - 在 flutter 中如何清除栏中的通知?

android - 查看覆盖操作工具栏?

java - 从 Android 通知中读取 Google Pay 通知时出现问题

Android - 将用户发送到 Activity 的 GCM 推送通知不会导致 onCreate 调用

android - 广播 PendingIntent 和 AlarmManager.setAlarmClock() 会丢失额外的 Intent