Bagaimana cara mencegah Android mengambil tangkapan layar ketika aplikasi saya ke latar belakang?

146

Aplikasi yang saya bangun saat ini memiliki persyaratan bahwa aplikasi harus mencegah OS untuk mengambil tangkapan layar aplikasi ketika sedang didorong ke latar belakang untuk alasan keamanan. Dengan cara ini, ia tidak akan dapat melihat layar aktif terakhir saat beralih antar aplikasi.

Saya berencana untuk menempatkan fungsi ini dalam metode onPause kelas aplikasi, tetapi pertama-tama saya perlu mencari tahu bagaimana saya dapat mencapai fungsi ini.

Jadi apakah ada orang di luar sana, yang memiliki petunjuk bagaimana cara memperbaikinya?

StingRay5
sumber

Jawaban:

264

Coba 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);
  }
}

Ini jelas aman terhadap tangkapan layar manual dan tangkapan layar otomatis dari riwayat tugas terbaru ICS. Ini juga aman terhadap perekaman layar (misalnya, aplikasi menggunakan API proyeksi media).

UPDATE : ini juga aman terhadap Now On Tap atau asisten lainnya di Android 6.0; mereka tidak akan mendapatkan akses ke detail widget dan kontainer di UI Anda jika pengguna membuka asisten.

UPDATE # 2 : namun, tidak semua yang ada dalam aktivitas akan dilindungi. Setiap jendela pop-up - Dialog, Spinner, AutoCompleteTextView, tindakan bar overflow, dll - akan tidak aman. Anda dapat memperbaiki Dialogmasalah dengan memanggilnya getWindow()dan mengatur FLAG_SECURE. Sisanya ... menjadi rumit. Lihat posting blog ini untuk lebih lanjut.

CommonsWare
sumber
6
@ Dany's: Sebenarnya, semuanya ada hubungannya dengan pertanyaan. Saya baru saja mengujinya pada Nexus S (4.0.3), dan berfungsi seperti yang diharapkan - tangkapan layar tugas terbaru ditekan. Anda masih melihat nama aplikasi dan ikonnya, tetapi tangkapan layarnya berwarna hitam. Anda dipersilakan untuk mencobanya di perangkat keras ICS.
CommonsWare
2
@ StingRay5: FLAG_SECUREtelah ada sejak awal - hanya memiliki arti terbatas hingga saat ini.
CommonsWare
1
Menarik untuk dicatat bahwa ada metode bernama onCreateThumbnail pada siklus hidup aktivitas, tetapi tidak pernah digunakan.
Snicolas
2
@ PankajKumar: Jika "kode untuk mengambil tangkapan layar" yang Anda tulis adalah trik klasik "ambil framebuffer sebagai root", FLAG_SECUREtidak akan bertahan melawan itu, karena itu level terlalu rendah. Demikian pula, jika Anda mengambil hierarki widget Anda sendiri dan mengubahnya menjadi Bitmap-backed Canvas, FLAG_SECUREmungkin tidak akan menentang hal itu, karena Anda mengambil tangkapan layar sendiri dari widget Anda sendiri dan karena itu mungkin menginginkan yang "aman" di sana. FLAG_SECUREuntuk screenshot sistem , seperti thumbnail tugas terbaru.
CommonsWare
2
Jawaban yang indah dan sederhana! Saya bertanya-tanya mengapa aplikasi seperti snapchat tidak menggunakan ini untuk mencegah seseorang mengambil tangkapan layar dari gambar yang dikirim.
Shobhit Puri
78

Hati-hati menggunakan WindowManager.LayoutParams.FLAG_SECURE, pada beberapa perangkat (diverifikasi pada Samsung Galaxy ACE, misalnya GT-S5830) ini akan membuat tampilan menjadi acak. Sepertinya bug spesifik Samsung. Saya merekomendasikan yang berikut ini:

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

Seperti inilah tampilan layar acak:

Gambar Layar Orak

Ini bekerja dengan baik pada ponsel ICS Samsung, jadi saya berasumsi bahwa masalahnya diisolasi untuk perangkat Gingerbread (atau lebih lama).

gardarh
sumber
8
Anda sepenuhnya benar, kami menemukan masalah ini, dan tentu saja diperlukan untuk memeriksa tingkat API. Sebenarnya lupa memposting ini, jadi terima kasih sudah menceritakannya lagi. :)
StingRay5
Ini juga terjadi pada Samsung Gio (Gingerbread) tetapi pada Froyo ok - jadi hanya terjadi pada 2,3
pixel
Kami memperhatikan masalah ini juga. Anda dapat memverifikasi di Emulator pada perangkat Gingerbread.
twaddington
Saya juga dapat mengkonfirmasi bahwa masalah ini muncul pada perangkat Samsung Gingerbread.
Ernir Erlingsson
7
Bahkan pada versi Android yang lebih baru FLAG_SECURE dapat menjadi masalah: pada Android 4.3 FLAG_SECURE menyebabkan masalah animasi dalam animasi rotasi layar, lihat code.google.com/p/android/issues/detail?id=58632 - ini telah diperbaiki di Android 4.4
Oliver
13

Solusi yang disediakan oleh CommonsWare terus berlaku juga di Lollipop.

Hanya sebuah catatan, jika Anda ingin terus tidak melihat foto dalam daftar terbaru untuk seluruh aplikasi, SEMUA kegiatan yang dilaksanakan harus menentukan dalam onCreate()metode bendera getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); sebelumsetContentView();

Jika tidak, snapshot dalam daftar terbaru akan menunjukkan aktivitas pertama tanpa tanda jika pengguna menavigasi melalui itu.

Davideas
sumber
1
Di aplikasi saya, saya memiliki fungsionalitas pengaturan / pembersihan FLAG_SECURE berdasarkan preferensi pengguna. Ini bekerja dengan baik sampai KITKAT dan layar hitam dapat dilihat di pengalih tugas. Di Lollipop, Ikhtisar menampilkan snapshot terakhir dari aplikasi saya, waktu ketika FLAG_SECURE tidak disetel (dihapus).
r.bhardwaj
@ r.bhardwaj saya pikir kami tidak bisa berbuat banyak dalam hal itu, tetapi Anda dapat memberi saran kepada pengguna bahwa, perubahan membutuhkan Aplikasi yang harus dimulai ulang untuk mengambil efek sepenuhnya ;-) dan Anda selesai.
Davideas
1
Adakah yang menemukan cara untuk mengembang tampilan kustom sebelum snapshot diambil sehingga bukan hanya layar hitam? Saya sudah mencoba menggembungkan tampilan pada window manager di onPause, tetapi tampaknya saat itu sudah terlambat.
user1064249
Hai @ user1064249 Apakah Anda menemukan solusi? Saya ingin mengembang Tampilan Peluncur sebelum OS mengambil tangkapan layar
Alexiscanny
1

Berikut ini adalah solusi untuk menyembunyikan konten suatu aplikasi dengan menutupinya dengan layar splash ketika aplikasi diletakkan di latar belakang. Ini tidak menggunakan teknik FLAG_SECURE, saya cukup mengesampingkan metode onPause dan onResume layar dan memodifikasi tampilan untuk menunjukkan yang mencakup semua yang ada di belakang.

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

D. Maul
sumber
0
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

ini bekerja untuk saya, itu mencegah dari mengambil screenshot dan juga setiap aplikasi rekaman inbuilt atau pihak ketiga dari layar perekaman.

Harsh Barnwal
sumber
0

Ini berfungsi untuk saya setelah menambahkan baris ini ke dalam onCreate sebelum setContentView dari setiap aktivitas.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
Arun Prajapati
sumber