Полноэкранное уведомление отображается только как предупреждение

Я уже 3 дня бьюсь головой об стол с этой проблемой, подскажите пожалуйста, где я сбился.

Когда я получаю входящий вызов VoIP, я пытаюсь показать полноэкранное уведомление, как это делает PhoneApp. Я в порядке с головой, если пользователь находится в захватывающей деятельности. Тем не менее, я получаю только уведомление, и никогда не получаю полноэкранный режим. Мне нужно уведомление, чтобы игнорировать экран блокировки.

Вот что я делаю:

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

Вот код createInCallIntent:

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

А вот 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);

Я попытался начать это действие напрямую (uber - это ссылка на приложение)

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

Что я делаю неправильно?


person Leo    schedule 03.09.2015    source источник
comment
Notification.fullScreenIntent: системный пользовательский интерфейс может отображать хедз-ап уведомление вместо запуска этого намерения, пока пользователь использует устройство.   -  person adneal    schedule 03.09.2015
comment
Да, нет, я понимаю, но, очевидно, мой телефон выбирает полноэкранный режим для телефона, почему не для моего приложения? Мое приложение для телефона правильно показывает хедз-ап, если я занимаюсь иммерсивным действием.   -  person Leo    schedule 03.09.2015
comment
@Leo Если уведомление с идентификатором INCOMING_CALL_NOTIFICATION_ID уже активно, fullScreenIntent для нового уведомления будет игнорироваться. Может ли это быть проблемой, с которой вы имеете дело?   -  person Vikram    schedule 05.09.2015
comment
@Vikram, к сожалению, нет, я пытался случайно изменить идентификатор   -  person Leo    schedule 05.09.2015
comment
@Лео Хорошо. Это странно. Проблема присутствует на нескольких устройствах? Вы тестировали на устройстве с ванильным андроидом? Я также рекомендую звонить notificationManager.cancel(INCOMING_CALL_NOTIFICATION_ID) прямо перед notificationManager.notify(INCOMING_CALL_NOTIFICATION_ID, notification).   -  person Vikram    schedule 05.09.2015
comment
Если отображение уведомления независимо от того, что делает пользователь, — это то, что вам нужно, лучшим вариантом может быть просто запуск действия при получении входящего вызова.   -  person Kai    schedule 06.09.2015
comment
@Kai К сожалению, запуск действия не работает, так как оно не проходит через экран блокировки.   -  person Leo    schedule 06.09.2015
comment
@Leo, представленные здесь решения должны иметь возможность обходить экран блокировки: stackoverflow.com/questions/4701928/disable-lock -экран   -  person Kai    schedule 07.09.2015
comment
Приложение вызова использует флаг FLAG_SHOW_WHEN_LOCKED для отображения InCallUi поверх экрана блокировки. InCallUi показывает действие, а не уведомление на экране блокировки.   -  person JohanShogun    schedule 08.09.2015
comment
Отключение экрана блокировки не даст желаемого результата (и может не поддерживаться). Флаг FLAG_DISMISS_KEYGUARD будет отображать вышибалу перед вашей активностью для безопасных экранов блокировки. Вы можете использовать оба, что приводит к отклонению, если небезопасно, и к включению, если безопасно, но в некоторых версиях Android есть ошибки, из-за которых один из флагов игнорируется при совместном использовании.   -  person JohanShogun    schedule 08.09.2015
comment
@Vikram, да, работает на Nexus 5 со всем, что есть в наличии. Пробовал звонить отменить.   -  person Leo    schedule 09.09.2015
comment
Да ничего из этого не работает. Приложение «Вызов» не показывает действие напрямую, оно делает это уведомление, которое затем представляет его как действие.   -  person Leo    schedule 09.09.2015
comment
@ Лео, это совсем не то, что он делает. androidxref.com/5.1. 1_r6/xref/packages/apps/InCallUI/src/com/, если у вас есть эти флаги, вы будете отображаться поверх экрана блокировки. Посмотрите на InCallActivity, чтобы узнать, как это сделать.   -  person JohanShogun    schedule 09.09.2015
comment
эта часть выпала: это совсем не то, что он делает, чтобы быть поверх экрана блокировки, установленное полноэкранное намерение не означает волшебным образом, что он может показывать что-то поверх экрана блокировки, любое приложение может это сделать, если у него есть правильное окно флаги.   -  person JohanShogun    schedule 09.09.2015
comment
@JohanShogun эээ, я до сих пор не понимаю. Вы говорите, что вместо того, чтобы показывать уведомление, я должен сделать: Intent incomingCallIntent = new Intent(uber, IncomingCallActivity.class); Строка callJson = call.toJson(uber).toString(); incomingCallIntent.putExtra (вызов, callJson); incomingCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ‹приложение›.startActivity(incomingCallIntent); Это вызывает экран, если устройство разблокировано. В противном случае ничего не происходит. Я добавил int flags = FLAG_SHOW_WHEN_LOCKED | FLAG_TURN_SCREEN_ON; getWindow().addFlags(флаги);   -  person Leo    schedule 10.09.2015
comment
Разместите код своей активности в своем вопросе, код в комментариях не читается. :)   -  person JohanShogun    schedule 10.09.2015
comment
Вы используете андроид 5.0? Также попробуйте переместить параметр флага в onAttachToWindow, флаги применяются к текущему окну, которое может совпадать или не совпадать с тем, к которому вы подключены.   -  person JohanShogun    schedule 10.09.2015
comment
Можете ли вы поделиться кодом файла макета CallService.getPendingIntent и activity_incoming_call?   -  person Tarun    schedule 29.01.2020


Ответы (2)


Если я правильно понял ваш вопрос, вы забыли добавить флаг WindowManager.LayoutParams.FLAG_FULLSCREEN в 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);

Эта комбинация необходима для отображения активности при заблокированном экране. Надеюсь, поможет.

person Yazazzello    schedule 11.09.2015
comment
Нет, это не имело к этому никакого отношения. - person Leo; 11.09.2015

Догадаться! Как я и подозревал, это была какая-то глупость.

В моем IncomingCallActivity у меня был следующий фрагмент кода

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

Оказывается, что-то, связанное с тем, как отображаются уведомления, на самом деле вызывает onPause, поэтому действие завершается.

Спасибо @JohanShogun за попытку помочь.

person Leo    schedule 11.09.2015
comment
Я не думаю, что вам нужен FLAG_DISMISS_KEYGUARD. Таким образом, телефон пользователя все еще будет заблокирован, когда он повесит трубку. Дополнительное преимущество безопасности. - person Cigogne Eveillée; 17.09.2015
comment
Да, вы не можете разблокировать чей-то телефон таким образом, он просто временно игнорирует блокировку. - person Leo; 17.09.2015
comment
Я точно знаю, что FLAG_DISMISS_KEYGUARD разблокирует устройство, если у пользователя нет надежной блокировки, например, если пользователь просто настроил разблокировку смахиванием. Однако вы правы, если у пользователя настроен шаблон PIN-кода. - person Cigogne Eveillée; 17.09.2015
comment
Вам по-прежнему нужно явно запускать действие или уведомление делает это автоматически? - person widavies; 14.11.2019
comment
@ wdavies973 уведомление делает это автоматически, если у вас есть полноэкранное намерение. - person Leo; 15.11.2019
comment
@Leo Вы тестировали это на устройствах Samsung? По какой-то причине, когда устройство разблокировано, но не в приложении на устройстве Samsung, оно все равно показывает уведомление. - person widavies; 21.11.2019