Reputation: 241
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
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());
}
}
}
}
Upvotes: 11
Views: 16376
Reputation: 2574
As per other answers posted here, the two flags FLAG_SHOW_WHEN_LOCKED and FLAG_TURN_SCREEN_ON are crucial for Android version above OREO.
However seems like the docs suggests it is better to declare them in AndroidManifest for that activity instead:
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.
For me, instead of adding the flags programmatically, adding them in AndroidManifest is cleaner anyway, and it works well in my testing
<activity
android:name=".IncomingCallActivity"
android:showForAllUsers="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:theme="@style/AppTheme" />
Not sure if showForAllUsers
is needed, but I read somewhere that it is better to include it.
Upvotes: 1
Reputation: 161
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
Upvotes: 0
Reputation: 999
//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);
Upvotes: 3
Reputation: 3991
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);
}
Upvotes: 0
Reputation: 241
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);
}
}
}
}
Upvotes: 11