Android Galaxy S4 - активность, которая видна на экране блокировки

Несколько лет назад я написал приложение для сигнализации, которое работало на Android 2, и теперь я пытаюсь обновить его для работы на Android 4. В частности, на Samsung Galaxy S4.

На Android 2, если телефон спал, он разбудил бы телефон и отобразил экран "Отложить или отклонить" на экране блокировки.

На Android 4 он разбудит телефон, но вам нужно его разблокировать, затем откройте область уведомлений, затем нажмите уведомление о тревоге, прежде чем вы сможете нажать "Отклонить".

Я всегда использовал этот код для пробуждения:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

Я прочитал 8 различных вопросов по стековому потоку по этому вопросу. Большинство из них дают код выше, который работал на меня много лет назад в Android 2, но не работает в Android 4. Но ни один из них не помог мне решить эту проблему. Вот вопросы, которые я читал и пробовал:

Android: удалите или отключите программно экран блокировки на устройстве Samsung Galaxy S2

Как отобразить полноэкранное окно TYPE_SYSTEM_ALERT?

Как создать активность, которая видна поверх экрана блокировки

Как запустить диалог (например, будильник/отсрочка будильника), который можно щелкнуть без разблокировки экрана

Действие Android по умолчанию по умолчанию заблокировано

заблокировано устройство Android, но хотите, чтобы звуковой сигнал и диалог отображались

экран блокировки диалогового окна Android

Показать диалог с сенсорными событиями по заблокированному экрану в Android 2.3

Есть ли у кого-нибудь идеи о том, что изменилось в Android 4, что могло вызвать это?

EDIT: Вот один из самых простых примеров, которые я видел в диалоговом окне тревоги, которое не возникает "сведено к минимуму". Это не так, как написано, появляется над заблокированным экраном, но вы можете исправить это с помощью WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED

http://wptrafficanalyzer.in/blog/setting-up-alarm-using-alarmmanager-and-waking-up-screen-and-unlocking-keypad-on-alarm-goes-off-in-android/

Он написан с помощью функции FragmentActivity и DialogFragment, но он по-прежнему работает как Activity. Он использует AlertDialog.Builder для создания диалога, и если вы попытаетесь сделать это с помощью XML-макета, это не сработает. Почему?

Ответ 1

Я понял это, и ответ сильно отличался от того, что я ожидал.

Этот фрагмент кода был включен в образец будильника с Android 2, в AlarmAlert.java:

@Override
protected void onStop() {
    super.onStop();
    // Don't hang around.
    finish();
}

Для справки вы можете увидеть файл из примера кода в Git в прошлом прямо здесь, содержащий указанную выше функцию onStop. Это никогда не вызывало проблем в Android 2.

Но в Android 4, если телефон был выключен, этот onStop будет срабатывать прямо перед тем, как телефон проснется, эффективно "минимизируя" активность. Как только я удалил эту функцию, он сразу снова работал.

Но мне интересно, это проблема, которую получают другие люди, такие как @radley и @Guardanis? Это кажется маловероятным, но, пожалуйста, дайте мне знать, если это также устранит ваши проблемы.

Если вы посещаете этот ответ в будущем, и вы получите эту проблему, я бы попытался:

  • Выньте любые onStop функции.

  • Добавить этот код в Упражнение:

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    
  • Убедитесь, что вы используете полноэкранную тему, а не тему диалога.

  • Это не повлияло на меня, но вы можете попробовать явно установить showOnLockScreen в манифесте: <activity android:name="com.example.MyActivity" android:showOnLockScreen="true"/>

  • Вторая вещь, которая для меня не изменилась, но вы можете попробовать добавить флаг WindowManager.LayoutParams.FLAG_FULLSCREEN

Я надеюсь, что это поможет другим людям!

Ответ 2

Не уверен, что это проблема во всех случаях, но документация на ShowWhenLocked говорит, что она применяется только к самому верхнему полноэкранному окну. У меня было окно в виде диалога, который не работал, но он отлично работал, как только я изменил его на обычное полноэкранное окно.

Ответ 3

У одного из вопросов, с которыми вы связались, есть ответ, который, похоже, решил эту проблему для меня.

Это код, который я использую, который работает:

@Override
public void onAttachedToWindow() {
        Window window = getWindow();

        window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.onAttachedToWindow();
    }

Я также явно объявляю это в определении активности в манифесте:

<activity 
    android:name="com.example.MyActivity"
    android:label="@string/app_name"
    android:showOnLockScreen="true"
    >

Активность Android по умолчанию по умолчанию заблокирована

Ответ 4

В порядке. Так что я недавно боролся с этим, но с 5.0.2 Galaxy Tab A. Неудивительно, что работа на любом другом устройстве не работает на Samsung (так было с первого устройства Samsung Galaxy, они сломать что-то новое каждый релиз!)

Общее решение для показа активности на экране блокировки для большинства устройств -

//wake up device and show even when on lock screen
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
        WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
        WindowManager.LayoutParams.FLAG_FULLSCREEN);

Однако это не работает для устройств samsung. Однако удаление FLAG_DISMISS_KEYGUARD делает этот трюк.

Глядя на документы для этого флага, мы имеем

Флаг окна: при установке окна будет отменено блокировка клавиатуры, только если это не защитная блокировка блокировки. Поскольку такой ключ безопасности не нужен для безопасности, он никогда не будет отображаться повторно, если пользователь перейдет в другое окно (в отличие от FLAG_SHOW_WHEN_LOCKED, который будет временно скрывать как защищенные, так и незащищенные блокировки ключей, но гарантировать, что они появятся, когда пользователь перейдет на другой пользовательский интерфейс, который не скрывает их). Если блокировка клавиатуры в настоящий момент активна и защищена (требуется шаблон разблокировки), пользователь должен будет подтвердить ее перед просмотром этого окна, если не установлен FLAG_SHOW_WHEN_LOCKED.

и для FLAG_SHOW_WHEN_LOCKED имеем

Флаг окна: специальный флаг, чтобы окна отображались, когда экран заперта. Это позволит окнам приложений иметь приоритет над ключом защитой или любыми другими экранами блокировки. Может использоваться с FLAG_KEEP_SCREEN_ON для включения экрана и отображения окон непосредственно перед отображением ключа защитное окно. Может использоваться с FLAG_DISMISS_KEYGUARD автоматически полностью отклоняет незащищенные блокировки клавиатуры. Этот флаг применяется только к самое верхнее полноэкранное окно.

Вы можете видеть, что их можно использовать вместе, но кажется, что samsung не будет беспокоиться с FLAG_SHOW_WHEN_LOCKED, если устройство заблокировано и FLAG_DISMISS_KEYGUARD присутствует. Мое приложение требует, чтобы экран блокировки настраивался, поэтому удаление флажка блокировки блокировки действительно позволяет мне отображать полноэкранные действия на экране блокировки. Yay для меня, нет, для samsung.

Ответ 5

В Котлине,

Для уровня Api 28 или менее, вы можете просто добавить метод ниже, который нужно открыть:

override fun onAttachedToWindow() {
    super.onAttachedToWindow()
    toBeShownOnLockScreen()
}

private fun toBeShownOnLockScreen() {
    window.addFlags(
        WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
    )
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setTurnScreenOn(true)
        setShowWhenLocked(true)
    } else {
        window.addFlags(
            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
        )
    }
}

И чтобы он работал на Android Pie и выше, в дополнение к вышеприведенному шагу нам нужно также установить в AndroidManifest:

<activity
    android:name=".view.activity.LockScreenActivity"
    android:showOnLockScreen="true"
    android:showWhenLocked="true"
    android:turnScreenOn="true" />

Я тестировал этот код с уровня API от 21 до 29 и работает как шарм!