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, но нет приемника. Поэтому вы сначала отключите функциональность скриншотов по умолчанию в андроиде, а затем реализуете свои собственные функции, чтобы сделать снимок экрана, и перед снятием снимка экрана вы должны размыть вашу защищенную информацию.