Sebuah Capacitor privacy screen menyembunyikan konten aplikasi saat user membuka app switcher dan, di Android, memblokir screenshot serta screen recording. Tanpa ini, iOS dan Android akan mengambil snapshot layar terakhir, sehingga saldo bank, rekam medis, atau code sekali pakai tetap terlihat di daftar recent apps. @capgo/capacitor-privacy-screen adds this with one call or one config flag, and lets you protect only the screens that need it.
Apa yang terlihat di app switcher
Saat pengguna keluar dari aplikasi, kedua sistem akan mengambil gambar layar saat ini:
- iOS mengambil snapshot saat aplikasi tidak lagi aktif dan menampilkannya di app switcher, serta sesaat saat aplikasi dijalankan ulang.
- Android menampilkan preview live atau cached di menu Recents.
Siapa pun yang melihat ponsel akan melihat snapshot tersebut. Begitu juga saat screen-sharing panggilan, atau pengguna yang merekam layar untuk tiket support. Screenshot juga tersinkron ke cloud photo library, di sinilah kebocoran data sensitif sering terjadi.
Aplikasi apa yang membutuhkannya
| Tipe aplikasi | Apa yang bisa bocor |
|---|---|
| Perbankan, fintech, crypto | Saldo, nomor kartu, IBAN, transaksi |
| Password manager, authenticator | Password, kode TOTP, recovery key |
| Kesehatan dan medis | Diagnosis, resep, hasil lab |
| Messaging | Percakapan pribadi |
| HR, payroll, legal | Salaries, contracts |
| Dating, media pribadi | Foto dan match |
Security review dan penetration test untuk kategori ini rutin menemukan kurangnya proteksi app switcher. OWASP MASVS mencakup pengecekan data sensitif yang terekspos melalui UI, dan auditor menguji hal tersebut.
Install
bun add @capgo/capacitor-privacy-screen
bunx cap sync
Plugin ini mendukung Capacitor 8 dengan versi 8.x.
Opsi 1: lindungi seluruh aplikasi saat startup
Atur di capacitor.config.ts. Plugin native akan membacanya saat dimuat, sebelum JavaScript Anda berjalan, sehingga snapshot pertama pun tetap terlindungi:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.bank',
appName: 'Example Bank',
webDir: 'dist',
plugins: {
PrivacyScreen: {
enabled: true,
android: {
dimBackground: false,
privacyModeOnActivityHidden: 'splash',
},
ios: {
blurEffect: 'dark',
},
},
},
};
export default config;
Jalankan bunx cap sync after changing the config. The enabled opsi ini hanya dibaca dari konfigurasi Capacitor, ini bukan opsi runtime.
Opsi 2: lindungi layar tertentu
import { PrivacyScreen } from '@capgo/capacitor-privacy-screen';
export async function enterSensitiveScreen() {
await PrivacyScreen.enable({
android: { dimBackground: true },
ios: { blurEffect: 'light' },
});
}
export async function leaveSensitiveScreen() {
await PrivacyScreen.disable();
}
const { enabled } = await PrivacyScreen.isEnabled();
Hubungkan ini ke router Anda agar setiap path masuk dan keluar terlindungi. Contohnya dengan Vue Router:
router.afterEach(async (to) => {
if (to.meta.sensitive) {
await PrivacyScreen.enable();
} else {
await PrivacyScreen.disable();
}
});
Dengan Angular, gunakan guard atau NavigationEnd subscription. Dengan React Router, gunakan hook di layout component Anda. Yang terpenting adalah navigasi back, deep links, dan perpindahan tab harus melewati logika yang sama, jika tidak, layar sensitif bisa tidak terlindungi.
Kegunaan setiap opsi
Android
- Proteksi menggunakan
WindowManager.LayoutParams.FLAG_SECURE. Saat aktif, screenshot dan screen recording akan diblokir dan preview Recents akan disembunyikan. dimBackground: truemenampilkan overlay redup di app switcher. Denganfalse, plugin akan menampilkan splash drawable Anda jika tersedia, jika tidak akan meredupkan layar.privacyModeOnActivityHiddenmengontrol apa yang muncul saat activity Anda tersembunyi oleh hal lain, misalnya system biometric prompt:'none'(default),'dim'atau'splash'.- Metode lama
preventScreenshotssudah deprecated dan diabaikan.FLAG_SECUREselalu diterapkan selama proteksi aktif. Untuk mengizinkan screenshot di satu layar, panggildisable()sebelumnya danenable()setelahnya.
iOS
- Saat aplikasi tidak lagi aktif, plugin akan menambahkan overlay agar snapshot di app switcher tidak menampilkan konten Anda.
blurEffect: 'light'atau'dark'menggunakan native blur.'none'(default) menampilkan launch screen jika tersedia, jika tidak, akan menggunakan background sistem.- Saat diaktifkan, konten aplikasi juga ditempatkan di layer rendering yang aman. Anggap pemblokiran screenshot iOS sebagai upaya terbaik: Apple tidak menyediakan API resmi untuk memblokir screenshot, dan perilakunya bisa berubah antar versi iOS.
Web
Implementasi web hanya melacak flag enabled agar code Anda berjalan di mana saja. Browser tidak bisa menyembunyikan preview tab atau memblokir screenshot.
Gabungkan dengan biometrik
Pola umum untuk aplikasi perbankan: blur di app switcher, lalu minta Face ID atau sidik jari saat aplikasi kembali dibuka setelah beberapa waktu. Fitur plugin ini privacyModeOnActivityHidden menjaga konten tetap tertutup selama prompt biometrik Android muncul.
import { App } from '@capacitor/app';
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
// null until the app has really gone to the background
let backgroundedAt: number | null = null;
App.addListener('appStateChange', async ({ isActive }) => {
if (!isActive) {
backgroundedAt = Date.now();
return;
}
const away = backgroundedAt === null ? 0 : Date.now() - backgroundedAt;
backgroundedAt = null;
if (away > 60_000) {
await NativeBiometric.verifyIdentity({ reason: 'Confirm it is you' });
}
});
Lihat plugin biometrik native untuk setup dan error handling.
Plugin resmi dan plugin Capgo
Tim Capacitor juga merilis @capacitor/privacy-screen dengan API yang sangat mirip (enable, disable, isEnabled dan opsi platform yang sama). Plugin Capgo mempertahankan API tersebut dan menambahkan:
enabled: truedi konfigurasi Capacitor, sehingga proteksi sudah aktif sebelum JavaScript berjalan. Plugin resmi hanya bisa diaktifkan via JavaScript.- Perenderan konten iOS yang aman saat diaktifkan, yang didokumentasikan sebagai bagian dari perilaku plugin, selain overlay app switcher.
getPluginVersion()untuk diagnostik.- Implementasi web yang mempertahankan flag enabled, sehingga code yang sama dapat berjalan di browser preview.
Jika Anda sudah menggunakan plugin resmi, transisinya sebagian besar hanya berupa perubahan import.
Detail UX yang penting
- Jangan blokir screenshot di semua bagian tanpa alasan. User sering mengambil screenshot struk, nomor konfirmasi, dan pengaturan. Lindungi layar berisi data sensitif saja, bukan seluruh aplikasi, kecuali kebijakan keamanan Anda mewajibkannya.
- Berikan penjelasan ke user. Jika seseorang mencoba mengambil screenshot di Android dan hasilnya gambar hitam, catatan singkat di help center akan mengurangi jumlah support ticket.
- Tes fitur screen sharing. Video call dan casting akan terblokir di Android saat
FLAG_SECUREdiatur. Jika aplikasi Anda punya alur “share screen dengan support”, nonaktifkan proteksi untuk fitur tersebut. - Cek aksesibilitas. Screen reader tetap berfungsi dengan
FLAG_SECURE, namun tetap lakukan tes dengan TalkBack dan VoiceOver.
Checklist pengujian
- Buka layar sensitif, lalu buka app switcher. Konten harus tersembunyi di kedua platform.
- Di Android, coba ambil screenshot dan screen recording. Keduanya harus hitam atau terblokir.
- Trigger prompt biometrik dan cek tampilan background.
- Kembali dari layar sensitif ke layar biasa. Proteksi akan otomatis mati jika Anda menggunakan mode per-layar.
- Kill dan relaunch aplikasi. Dengan
enabled: truedi config, snapshot pertama harus terlindungi. - Test di iPad dengan Split View dan Slide Over. Aplikasi mungkin tetap terlihat saat tidak aktif.
Troubleshooting
Snapshot masih menampilkan konten di iOS. Anda mengaktifkan proteksi setelah aplikasi masuk ke background, atau hanya pada beberapa route. Gunakan opsi config untuk proteksi seluruh aplikasi.
Layar hitam di Recents pada Android, bukan splash screen. Set dimBackground: false dan pastikan splash drawable Anda ada, jika tidak plugin akan beralih ke mode dimming.
Screenshot tetap berfungsi di Android. Periksa isEnabled(). Bagian lain dari aplikasi Anda mungkin memanggil disable() saat navigasi.
Proteksi hilang setelah update OTA. Nilai konfigurasi bersifat native. Jika Anda mengubah plugins.PrivacyScreen di capacitor.config.ts, kirim build store baru. Runtime enable() dan disable() call di JavaScript Anda dapat diubah dengan live updates Capgo.
Referensi keamanan terkait
Privacy screen adalah salah satu poin dalam checklist keamanan mobile. Perhatikan juga secure storage, certificate pinning, dan root detection. Capgo punya plugin untuk SSL pinning dan root dan jailbreak detection, serta artikel kami tentang aturan privasi Apple untuk aplikasi Capacitor yang membahas sisi review. Opsi plugin lengkap ada di dokumentasi privacy screen.