29

I have been banging my head against the table with this problem for 3 days now, please tell me where I have strayed.

When I am getting an incoming VoIP call, I am trying to show a full screen notification, just like the PhoneApp does. I am ok with heads up, if the user is in an immersive activity. However, I am getting only a heads up notification, and never getting a full screen. I need to notification to ignore the lock screen as well.

Here is what I am doing:

String callJson = call.toJson(uber).toString();
uber.requestWakeState(UberVoice.WAKE_STATE_FULL);

final Notification.Builder builder = new Notification.Builder(uber);
builder.setSmallIcon(R.drawable.switch_notification);
if (image != null) {
    builder.setLargeIcon(image);
}
builder.setOngoing(true);

PendingIntent inCallPendingIntent =
        PendingIntent.getActivity(uber, 234,
                UberVoice.createInCallIntent(), 0);
builder.setContentIntent(inCallPendingIntent);

builder.setContentText(body);
builder.setUsesChronometer(false);

builder.setContentTitle(title);

builder.setCategory(Notification.CATEGORY_CALL);
builder.setVisibility(Notification.VISIBILITY_PUBLIC);

builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE), AudioManager.STREAM_RING);
builder.setVibrate(new long[]{500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500});

builder.setPriority(Notification.PRIORITY_MAX);
builder.setTicker(title);
builder.setFullScreenIntent(inCallPendingIntent, true);

builder.addAction(R.drawable.hangup_action, "Reject", CallService.getPendingIntent(uber, callJson, CallService.REJECT));
builder.addAction(R.drawable.answer_action, "Answer", CallService.getPendingIntent(uber, callJson, CallService.ANSWER));

NotificationManager notificationManager = (NotificationManager) uber.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = builder.build();
notificationManager.notify(INCOMING_CALL_NOTIFICATION_ID, notification);

Here is the createInCallIntent code:

public static Intent createInCallIntent() {
    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
            | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
    intent.setClassName("<package>", IncomingCallActivity.class.getName());
    return intent;
}

And here is the IncomingCallActivity.onCreate()

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

    int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;

    getWindow().addFlags(flags);

    setContentView(R.layout.activity_incoming_call);

I have tried starting this activity directly(uber is Application reference)

Intent incomingCallIntent = new Intent(uber, IncomingCallActivity.class);
String callJson = call.toJson(uber).toString();
incomingCallIntent.putExtra("call", callJson);

incomingCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

uber.startActivity(incomingCallIntent);

What am I doing wrong?

Leo
  • 4,652
  • 6
  • 32
  • 42
  • 1
    [Notification.fullScreenIntent:](https://developer.android.com/reference/android/app/Notification.html#fullScreenIntent) The system UI may choose to display a heads-up notification, instead of launching this intent, while the user is using the device. – adneal Sep 03 '15 at 00:46
  • Yea no I get that, but obviously my phone "chooses" to show full screen for phone, why not for my app? My phone app correctly shows heads-up if I am in an immersive activity. – Leo Sep 03 '15 at 00:47
  • @Leo If a notification with id `INCOMING_CALL_NOTIFICATION_ID` is already active, `fullScreenIntent` for the new notification will be ignored. Could this be the problem you're dealing with? – Vikram Sep 05 '15 at 17:20
  • @Vikram unfortunately not, I tried changing the ID randomly – Leo Sep 05 '15 at 17:28
  • @Leo Ok. Its odd. Is the issue present on multiple devices? Have you tested on a device running vanilla android? I also recommend calling `notificationManager.cancel(INCOMING_CALL_NOTIFICATION_ID)` right before `notificationManager.notify(INCOMING_CALL_NOTIFICATION_ID, notification)`. – Vikram Sep 05 '15 at 18:06
  • If showing a "notification" regardless what the user is doing is what you required, the best bet may be just launching an Activity on receiving an incoming call. – Kai Sep 06 '15 at 06:57
  • @Kai Unfortunately launching an activity doesn't work, as it doesn't get through the lock screen. – Leo Sep 06 '15 at 19:05
  • @Leo the solutions provided here should be able to bypass the lock screen: http://stackoverflow.com/questions/4701928/disable-lock-screen – Kai Sep 07 '15 at 00:30
  • The call app uses the flag FLAG_SHOW_WHEN_LOCKED to display InCallUi ontop of lock screen. InCallUi shows an activity not a notification in lock screen. – JohanShogun Sep 08 '15 at 20:43
  • Disabling the lock screen will not yield the result you want (and may not be supported). The flag FLAG_DISMISS_KEYGUARD will show the bouncer before your activity for secure lock screens. You can use both resulting in dismiss if insecure and ontop if secure, but, some versions of Android have bugs where one of the flags are ignored if used together. – JohanShogun Sep 08 '15 at 20:50
  • @Vikram yep running on Nexus 5 with everything stock. Tried calling cancel. – Leo Sep 08 '15 at 23:18
  • Yea none of these things work. The Call app is not directly showing an activity, they are doing this notification thing which then presents it as an activity. – Leo Sep 08 '15 at 23:33
  • @Leo, that's not at all what it's doing. http://androidxref.com/5.1.1_r6/xref/packages/apps/InCallUI/src/com/android/incallui/InCallActivity.java if you have those flags you _will_ be shown ontop of lock screen. Look at InCallActivity to see how to do it. – JohanShogun Sep 09 '15 at 04:53
  • this part fell out: it's not at all what it's doing to be ontop of lock screen, the full screen intent that it sets does not magically mean it can show stuff ontop of lock screen, any app can do it if it has the correct window flags. – JohanShogun Sep 09 '15 at 05:02
  • @JohanShogun uh, so I still don't understand. You are saying that instead of showing a notification I should do: Intent incomingCallIntent = new Intent(uber, IncomingCallActivity.class); String callJson = call.toJson(uber).toString(); incomingCallIntent.putExtra("call", callJson); incomingCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); .startActivity(incomingCallIntent); This does bring up the screen if the device is unlocked. Otherwise nothing happens. I have added int flags = FLAG_SHOW_WHEN_LOCKED | FLAG_TURN_SCREEN_ON; getWindow().addFlags(flags); – Leo Sep 09 '15 at 23:28
  • Post your activity code in your question, code in comments is unreadable. :) – JohanShogun Sep 10 '15 at 04:42
  • Are you using android 5.0? Also try moving the flag setting to onAttachToWindow, the flags apply to the current window, which may or may not be the same one you are attached to. – JohanShogun Sep 10 '15 at 04:55
  • Can you share the code of CallService.getPendingIntent and activity_incoming_call layout file ? – Tarun Jan 29 '20 at 04:32

3 Answers3

6

If I understood your question correctly, you forgot to add flag WindowManager.LayoutParams.FLAG_FULLSCREEN in IncomingCallActivity

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

    int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_FULLSCREEN;

    getWindow().addFlags(flags);

This combination needed to show activity while screen is locked. Hope it helps.

Yazazzello
  • 6,053
  • 1
  • 19
  • 21
5

Figured it out! It was something stupid just as I suspected.

In my IncomingCallActivity I had the following bit of code

public void onPause() {
    super.onPause();
    finish();
}

It turns out that something having to do with how Notifications get shown actually calls onPause, therefore finishing the activity.

Thanks to @JohanShogun for attempting to help out.

Leo
  • 4,652
  • 6
  • 32
  • 42
  • I don't think you need FLAG_DISMISS_KEYGUARD though. That way the user's phone will still be locked when they hang up. An added security benefit. – Cigogne Eveillée Sep 17 '15 at 16:38
  • You do, you cannot unlock someone's phone like this, it just temporarily ignores the lock. – Leo Sep 17 '15 at 16:50
  • I know for a fact that FLAG_DISMISS_KEYGUARD will unlock the device if the user doesn't have a secure lock, like if the user just has swipe-to-unlock configured. You are right, though, if the user has a pattern of pin configured – Cigogne Eveillée Sep 17 '15 at 16:55
  • Do you still have to explicitly start the activity or does the notification do it automatically? – widavies Nov 14 '19 at 06:44
  • @wdavies973 the notification does it automatically, as long as you have full screen intent on there. – Leo Nov 14 '19 at 21:44
  • @Leo Have you tested this on Samsung devices? For some reason, when the device is unlocked, but not in an app on a Samsung device, it still shows a notification. – widavies Nov 20 '19 at 23:41
1
//in android 10 a permssion is used try it
 
 <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
Mazhar Iqbal
  • 813
  • 7
  • 7