[英]Android 11 - Notification media controls doesn't show on lock screen
[英]Android full screen notification won't show over the lock screen
我正在嘗試創建一個 android 全屏通知以在鎖定屏幕上顯示活動,例如鬧鍾。
通知總是發生,但活動永遠不會在鎖定屏幕上啟動; 如果手機關機,它只會響起並在鎖定屏幕上顯示通知圖標。 如果電話按預期開機,它會顯示提醒通知。 調試打印表明通知通道已按要求成功注冊為 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
下面是應用程序代碼的一個非常精簡的版本,一個帶有 1 個按鈕的活動,用於安排將來使用廣播接收器的通知,以便在屏幕鎖定后觸發。
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
全屏意圖的 android 文檔示例中缺少的部分是全屏意圖嘗試顯示的活動需要設置幾個 WindowManager.LayoutParams 標志:FLAG_SHOW_WHEN_LOCKED 和 FLAG_TURN_SCREEN_ON。
這是最終的最小測試應用程序代碼,我希望對嘗試做鬧鍾類型應用程序的其他人有用。 我在上面列出的 4 個操作系統版本上成功測試,目標 sdk 29 和最低 sdk 15。唯一需要的清單權限是 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);
}
}
}
}
//use the following code it will work
//也把它放在你的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);
根據此處發布的其他答案,FLAG_SHOW_WHEN_LOCKED 和 FLAG_TURN_SCREEN_ON 這兩個標志對於 OREO 以上的 Android 版本至關重要。
然而,文檔似乎建議最好在 AndroidManifest 中為該活動聲明它們:
When using the Window flag during activity startup, there may not be time
to add it before the system stops your activity for being behind the
lock-screen. This leads to a double life-cycle as it is then restarted.
對我來說,不是以編程方式添加標志,而是在 AndroidManifest 中添加它們更干凈,並且在我的測試中效果很好
<activity
android:name=".IncomingCallActivity"
android:showForAllUsers="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:theme="@style/AppTheme" />
不確定是否需要showForAllUsers
,但我在某處讀到最好包含它。
對我來說,幫助是Ranjith Kumar 在這個問題中的回答。
下面是相同的代碼,在 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);
}
我也有類似的問題,對我來說,問題不在於 window Flags 但在觸發通知時,通知通道應該具有 IMPORTANCE_HIGH 和具有 HIGH_PRIORITY 的通知,而且你正在使用 redmi,你必須在應用程序設置中明確設置權限
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.