Як запобігти Android робити знімок екрана, коли моя програма переходить на другий план?


146

Додаток, який я зараз будую, вимагає, щоб програма забороняла ОС робити знімок екрана, коли його з міркувань безпеки відсувають на задній план. Таким чином, він не зможе побачити останній активний екран при переключенні між додатками.

Я планую розмістити цю функціональність у методі onPause класу додатків, але спочатку мені потрібно з’ясувати, як я можу досягти цієї функціональності.

То чи є хтось там, який має підказку, як це виправити?

Відповіді:


264

Спробуйте FLAG_SECURE:

public class FlagSecureTestActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                         WindowManager.LayoutParams.FLAG_SECURE);

    setContentView(R.layout.main);
  }
}

Це безумовно захищає від ручних скріншотів та автоматичних знімків екрана з історії останніх завдань ICS. Він також захищає від запису на екрані (наприклад, програми, що використовують API мультимедійних проекцій).

ОНОВЛЕННЯ : також захищено від Now On Tap або інших помічників на Android 6.0; вони не отримають доступ до деталей віджетів та контейнерів у вашому інтерфейсі, якщо користувач знайде помічника.

ОНОВЛЕННЯ №2 : проте, не все в діяльності буде захищено. Будь-які спливаючі вікна - Dialog, Spinner, AutoCompleteTextView, дія Переповнення бар і т.д. - буде небезпечно. Виправити Dialogпроблему можна, зателефонувавши getWindow()до неї та встановивши налаштування FLAG_SECURE. Решта ... стає хитромудрим. Дивіться цю публікацію в блозі для отримання додаткової інформації.


6
@ Дані: Насправді, це стосується всього питання. Я щойно тестував його на Nexus S (4.0.3), і він працює як слід - скріншот останніх завдань пригнічується. Ви все ще бачите ім'я та піктограму програми, але скріншот чорний. Ви можете спробувати це на апаратному забезпеченні ICS.
CommonsWare

2
@ StingRay5: FLAG_SECUREіснує з самого початку - до недавнього часу воно мало обмежене значення.
CommonsWare

1
Цікаво відзначити, що існує метод, який називається onCreateThumbnail ni життєвим циклом діяльності, але він ніколи не використовується.
Snicolas

2
@PankajKumar: Якщо написаний вами "код для зняття екрану", це те, що класичний трюк "захопити фреймбуфер як корінь" FLAG_SECUREне захищатиметься від цього, оскільки це занадто низький рівень. Точно так само, якщо ви взяли власну ієрархію віджетів і притягнули її до Bitmapвідключеної Canvas, FLAG_SECUREймовірно, не захиститеся від цього, оскільки ви робите власні скріншоти власних віджетів і тому, мабуть, хотіли "захищених" там. FLAG_SECUREпризначений для скріншотів системи , таких як ескізи останніх завдань.
CommonsWare

2
Чудова і проста відповідь! Мені цікаво, чому такі програми, як snapchat , не використовують це для того, щоб хтось не робив знімок екрана з надісланими зображеннями.
Shobhit Puri

78

Будьте обережні щодо використання WindowManager.LayoutParams.FLAG_SECURE, на деяких пристроях (перевірено на Samsung Galaxy ACE, наприклад, GT-S5830), це зробить вигляд сформованим. Схоже на помилку Samsung. Я рекомендую наступне:

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}

Ось як виглядає зашифрований екран:

Ескізне зображення екрану

Хоча це працює належним чином на телефонах Samsung ICS, тому я припускаю, що проблема пов'язана з пряниками (або старішими).


8
Ви абсолютно праві, ми стикалися з цим питанням, і це, безумовно, потрібно було перевірити на рівень API. Насправді забув опублікувати це, тож дякую за те, що знову вийшов. :)
StingRay5

Він також трапляється на Samsung Gio (Пряники), але на Froyo - це нормально, тому він трапляється лише на 2,3
пікселі

Ми також помітили цю проблему. Ви можете підтвердити його в емуляторі на Пряників.
twaddington

Я також можу підтвердити, що ця проблема з’являється на пристроях Samsung Gingerbread.
Ернір Ерлінгссон

7
Навіть у нових версіях Android FLAG_SECURE може бути проблематичним: на Android 4.3 FLAG_SECURE викликає проблеми з анімацією при анімації повороту екрана, див. Code.google.com/p/android/isissue/detail?id=58632 - це було виправлено на Android 4.4
Oliver

13

Рішення, надане CommonsWare, продовжує діяти і в Lollipop.

Просто зверніть увагу, якщо ви хочете продовжувати НЕ бачити знімки в список останнього для всього додатки, всі проведені заходи повинні бути вказано в onCreate()методі прапора getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); перед тимsetContentView();

Інакше знімок у недавньому списку покаже першу активність без прапора, якщо користувач переходив через нього.


1
У своєму додатку у мене є функція налаштування / очищення FLAG_SECURE на основі налаштувань користувача. Він працював чудово, доки KITKAT та чорний екран не видно у перемикачі завдань. У Lollipop в огляді відображається останній знімок мого додатка - час, коли FLAG_SECURE не встановлено (очищено).
r.bhardwaj

@ r.bhardwaj Я думаю, що ми не можемо зробити так багато в такому випадку, але ви можете порадити користувачеві, що для зміни потрібно перезапустити додаток, щоб мати повний ефект ;-), і ви закінчили.
Давідеас

1
Хтось знайшов спосіб завищити спеціальний вигляд перед тим, як зробити знімок, щоб це не просто чорний екран? Я спробував завищити погляд на менеджера вікон в onPause, але, здається, до цього часу вже пізно.
користувач1064249

Привіт @ user1064249 Ви знайшли якесь рішення? Я хочу надути Погляд запуску до того, як ОС
зробить

1

Ось рішення щодо приховування вмісту програми, прикриваючи його заставкою, коли додаток перебуває на задньому плані. Це не використовуючи техніку FLAG_SECURE, я просто перекриваю методи onPause та onResume на екранах і модифікую подання, щоб відображати той, який охоплює все ззаду.

https://stackoverflow.com/a/52976001/6686912


0
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

це працювало для мене, це заважає робити знімок екрана, а також будь-яку вбудовану або сторонніх програму запису із екрана запису.


0

Це робота для мене після додавання цих рядків у onCreate перед setContentView кожної діяльності.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.