Как предотвратить захват экрана в Android
Можно ли предотвратить запись экрана в приложении Android?
Я хотел бы разработать безопасное приложение для Android. В этом мне нужно обнаружить программное обеспечение записи экрана, которые работают в фоновом режиме и убить их. Я использовал SECURE FLAG для предотвращения скриншотов. Но я не знаю, возможно ли предотвратить захват видео с экрана Android. Дайте мне знать, как предотвратить захват экрана (видео / скриншоты).
17 ответов
Я хочу сказать, что невозможно полностью предотвратить захват экрана / видео любого приложения для Android с помощью поддерживаемых средств. Но если вы хотите заблокировать его только для обычных устройств Android, SECURE FLAG является существенным.
1) Флаг безопасности блокирует как обычный снимок экрана, так и захват видео.
Также в документации по этой ссылке сказано, что
Флаг окна: относиться к содержимому окна как к безопасному, не допуская его появления на скриншотах или просмотра на незащищенных экранах.
Приведенное выше решение наверняка предотвратит захват видео приложениями.
Смотрите ответ здесь.
2) Существуют альтернативные способы захвата содержимого экрана.
Может быть возможно сделать снимок экрана другого приложения на рутированном устройстве или с помощью SDK,
которые оба дают мало шансов, что вы либо заблокируете его, либо получите уведомление об этом.
Например: существует программное обеспечение для зеркалирования экрана вашего телефона на компьютер через SDK, поэтому программное обеспечение для захвата экрана может использоваться там, которое не будет обнаружено вашим приложением.
Смотрите ответ здесь.
Просто добавьте эту строку:
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
Перед вашим setContentView()
метод.
Я видел все ответы, которые подходят только для одного действия, но есть мое решение, которое блокирует снимок экрана для всех действий без добавления кода к действию. Прежде всего создайте класс Custom Application и добавьтеregisterActivityLifecycleCallbacks
.Затем зарегистрируйте его в своем манифесте.
MyApplicationContext.class
public class MyApplicationContext extends Application {
private Context context;
public void onCreate() {
super.onCreate();
context = getApplicationContext();
setupActivityListener();
}
private void setupActivityListener() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); }
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
}
Манифест
<application
android:name=".MyApplicationContext"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
Чтобы отключить захват экрана:
Добавьте следующую строку кода в onCreate()
метод:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
Чтобы включить захват экрана:
Найти для LayoutParams.FLAG_SECURE
и удалите строку кода.
Для пользователей Java
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
Для пользователей kotlin
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
Вы можете сделать свое приложение владельцем устройства / профиля и позвонить setScreenCaptureDisabled()
, Из документации этот API-интерфейс выполняет следующие действия:
public void setScreenCaptureDisabled (Администратор ComponentName, логическое значение отключено) Добавлено на уровне API 21
Вызывается владельцем устройства / профиля, чтобы установить, отключен ли захват экрана. Отключение захвата экрана также предотвращает отображение контента на устройствах отображения, которые не имеют защищенного видеовыхода. Смотрите FLAG_SECURE для более подробной информации о безопасных поверхностях и защищенных дисплеях.
Администратор вызывающего устройства должен быть владельцем устройства или профиля. Если это не так, будет выдано исключение безопасности. Параметры admin С каким DeviceAdminReceiver связан этот запрос. деактивирован Захват экрана отключен или нет.
В качестве альтернативы вы можете стать партнерским приложением MDM(Управление мобильными устройствами).OEMs предоставляет дополнительные API-интерфейсы своим партнерским приложениям MDM для управления устройством. Например, samsung предоставляет API для управления записью экрана на устройстве своим партнерам по MDM.
В настоящее время это единственный способ обеспечить ограничение экрана.
Попробуй это:
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
Кажется, вы знаете, как отключить скриншоты из своего приложения, и есть другие ответы, которые помогут вам в этом. Но я постараюсь дать вам важную информацию, которую никто не дает вам.
1) У вас не может быть приложения, которое на 100% защищено от снятия скриншотов (фото / видео). Официального способа делать скриншоты в Android нет. Если приложение записывает экраны, оно должно использовать некоторые неподдерживаемые методы (либо рутирование, либо использование SDK).
У вас очень мало возможностей для блокировки приложения, если оно использует root-доступ к экранам записи.
2) Никто не упомянул эту проблему здесь, но будьте очень осторожны при использовании WindowManager.LayoutParams.FLAG_SECURE
, На многих устройствах (например, на Samsung Galaxy ACE, например, GT-S5830) было проверено, что это делает весь вид зашифрованным. Как это,
Пожалуйста, поставьте чек, как это,
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
Он отлично работает на устройствах ICS, так что никаких проблем нет.
3) Я также обнаружил, что даже на более новых устройствах, таких как Android 4.3, это вызывает проблемы с анимацией при повороте экрана. Пожалуйста, проверьте этот отчет об ошибке.
Я использовал это решение, чтобы сделать снимок вручную в приложении и запретить захват сцен, когда приложение работает в фоновом режиме, надеюсь, это поможет.
@Override
protected void onResume() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
super.onResume();
}
@Override
protected void onPause() {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
super.onPause();
}
Согласно этому официальному руководству, вы можете добавить WindowManager.LayoutParams.FLAG_SECURE
на ваш макет окна, и это будет запрещать скриншоты.
Добавьте эту строку в событие OnCreate на MainActivity (Xamarin)
Window.SetFlags(WindowManagerFlags.Secure, WindowManagerFlags.Secure);
Пользователи Kotlin могут добавить следующий код в класс приложения, чтобы предотвратить создание снимков экрана приложения.
class MediSageApplication : Application() {
override fun onCreate() {
super.onCreate()
registerActivityLifecycle()
}
private fun registerActivityLifecycle() {
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
activity.window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
})
}
}
По поводу блокировки возможности сделать скриншот в приложении:
Window window = requireActivity().getWindow();
window.addFlag(WindowManager.LayoutParams.FLAG_SECURE);
не забудьте убрать этот флаг (например, в onDestroy) - чтобы включить скриншоты в других безопасных местах приложения:
window.clearFlags(WWindowManager.LayoutParams.FLAG_SECURE);
public class InShotApp extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycle();
}
private void registerActivityLifecycle() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); }
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}
});
}
}
О скриншоте фото,
FLAG_SECURE не работает рутированное устройство.
но если вы контролируете файл скриншота, вы можете предотвратить получение исходного файла.
попробуй это.
1. мониторинг скриншота (файловый монитор) с помощью удаленного сервиса Android
2. удалить оригинальное изображение скриншота.
3. доставить экземпляр растрового изображения, чтобы вы могли изменить.
Легко и элегантно:
import android.view.WindowManager.LayoutParams;
// ...
@Override
public void onWindowFocusChanged(boolean isFocused) {
if (isFocused) {
getWindow().clearFlags(LayoutParams.FLAG_SECURE);
} else {
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
}
super.onWindowFocusChanged(isFocused);
}
Для тех, кому нужно отключить скриншоты и использовать Jetpack Compose, это то, что вам нужно:
fun Activity.disableScreenshots() {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
fun Activity.enableScreenshots() {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
@Composable
fun DisableScreenshots() {
val context = LocalContext.current
DisposableEffect(Unit) {
context.getActivity()?.disableScreenshots()
onDispose {
context.getActivity()?.enableScreenshots()
}
}
}
Затем просто вызовите DisableScreenshots из вашей составной функции;)