Android: настройка миниатюр недавних приложений (снимок экрана по умолчанию)

Приложение, над которым я работаю, отображает некоторую конфиденциальную информацию, которая не должна отображаться на экране "Недавние задачи" при остановке приложения нажатием кнопки "Домой".

Я хотел бы размыть конфиденциальные данные на скриншоте или вместо показать логотип приложения.

Мне известны следующие подходы, но они не соответствуют моим требованиям:

А потом есть некоторые обходные пути, которые я опробовал, но они не сработали, как хотелось бы:

  • Начните новое действие, которое показывает логотип приложения в onPause, так что вместо фактического актива отображается скриншот. Но открытие нового действия занимает слишком много времени и нарушает работу пользователя.
  • Установите вид содержимого активности на изображение логотипа приложения в onPause. Это казалось мне отличным решением. К сожалению, скриншот экрана недавних задач сделан в неуказанное время. Во время тестирования логотип приложения быстро появляется перед тем, как приложение закрывается при нажатии кнопки "Домой", но на полученном снимке экрана показывается активность незадолго до этого.
  • Удаление конфиденциальных данных из виджетов (например, textView.setText("")) имеет ту же проблему синхронизации времени экрана, что только что упоминалось.

Какие-нибудь альтернативные идеи или решения перечисленных обходных путей?

Ответ 1

Я изучил это пару месяцев назад с той же целью, что и вы.

К сожалению, мне пришлось сделать вывод, что это просто невозможно. Я перерыл исходный код Android и подтвердил его.

  • Там нет обратных вызовов или методов от Android, который позволяет настроить его (это работает в любом случае). Помимо FLAG_SECURE, эта часть кода не принимает никаких вводов или изменений.
  • OnPause и аналогичные методы жизненного цикла вызываются слишком поздно (снимок экрана уже сделан). Все методы жизненного цикла, которые намекают на то, что вы собираетесь перейти в фоновый режим, запускаются слишком поздно.
  • Изображение, которое вы видите в недавних задачах, является фактическим снимком экрана и, следовательно, не подвержено изменениям, которые вы вносите (слишком поздно) в свой вид. Это означает, что вы не можете своевременно изменять свое представление (например, сделать его невидимым, заменить его чем-то другим, добавить SECURE_FLAG или любое другое препятствие для представления). Кроме того, эти изображения можно найти на эмуляторе в /data/system_ce/0/recent_images.
  • Единственное исключение - использование FLAG_SECURE, которое предотвратит снятие скриншота вашего приложения. Я экспериментировал с установкой этого FLAG в onPause и удалением его в onResume, однако, как уже упоминалось, эти методы жизненного цикла выполняются после того, как снимок экрана уже сделан, и, таким образом, не оказали абсолютно никакого эффекта.

Как описано в разделе Как изменить снимок, отображаемый в списке последних приложений? был обратный вызов, который можно использовать для настройки эскиза: onCreateThumbnail. Тем не менее, это не работает, и это никогда не называется. Чтобы было ясно, обратный вызов все еще там, он просто никогда не вызывается ОС. Тот факт, что он прекратил работать, плохо документирован, но, по-видимому, в 4.0.3 он молча устарел/удален.

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

Когда ваше приложение переходит в фоновый режим, ваш фактический вид анимирован (чтобы получить этот переход при уменьшении). На эту анимацию можно повлиять с помощью изменений, которые вы делаете в onPause (если вы достаточно быстры, что есть) (среди прочего я экспериментировал с установкой непрозрачности на 0 в окне). Это, однако, повлияет только на анимацию. После завершения анимации вид заменяется на снимок экрана, сделанный ранее.

Также посмотрите эти вопросы, которые обсуждают это:

Ответ 2

Как реализовать наложение макета поверх всей вашей деятельности?

Сделайте его прозрачным, по умолчанию кликнув по клику, поэтому не отрицательно влиять на UX во время использования.

В onPause() установите наполовину прозрачное, размытое изображение в качестве фона этого макета, данные будут скремблированы за ним. В onResume() снова измените фон на полностью прозрачный. Вуаля.

Это может быть быстрее, чем другие типы наложений. Положительный побочный эффект заключается в том, что если вы выполняете unblurring как короткий эффект анимации, когда пользователь возвращается (с соответствующей библиотекой, которая использует С++ вместо Java), она может выглядеть даже круто, и пользователи не будут даже ум, видя это.

Я не пробовал это сам, но это то, что вы еще не пробовали.

Ответ 3

Вы можете удалить чувствительный текст в onUserLeaveHint() или onWindowFocusChanged(), хотя я сам этого не пробовал.

Ответ 4

Есть способ настроить его. Вам нужны ваши Действия с конфиденциальными данными до FLAG_SECURE в onCreate перед вами setContentView. Затем вам нужно пустое действие, которое отображает все, что вы хотите, в качестве настраиваемого эскиза. Обычно это своего рода заставка. Эта новая активность должна быть средством запуска и является единственной деятельностью, а не FLAG_SECURE. Это действие запускается, и в onResume запускается фактическое действие с конфиденциальными данными.

Android OS сделает снимок этого нового действия в начале вашего приложения. К сожалению, пользователи также увидят эту активность на короткое время. Поскольку все остальные действия - это FLAG_SECURE, ОС Android будет использовать единственный доступный снимок экрана, который был сделан в начале.

Ответ 5

Я думаю, что это может быть достигнуто только через BroadCastReceiver, но нет приемника. Поэтому вы сначала отключите функциональность скриншотов по умолчанию в андроиде, а затем реализуете свои собственные функции, чтобы сделать снимок экрана, и перед снятием снимка экрана вы должны размыть вашу защищенную информацию.