Come posso impedire ad Android di fare uno screenshot quando la mia app passa in background?


146

L'app che sto attualmente costruendo ha il requisito che l'app deve impedire al sistema operativo di fare uno screenshot dell'app quando viene inserita in background per motivi di sicurezza. In questo modo non sarà in grado di vedere l'ultima schermata attiva quando si passa da un'app all'altra.

Sto pianificando di inserire questa funzionalità nel metodo onPause della classe di applicazione, ma prima devo scoprire come posso ottenere questa funzionalità.

Quindi c'è qualcuno là fuori, che ha la minima idea di come risolvere questo problema?

Risposte:


264

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

Ciò garantisce sicuramente schermate manuali e schermate automatiche della cronologia delle attività recenti di ICS. Protegge anche dalla registrazione dello schermo (ad esempio, le app che utilizzano le API di proiezione multimediale).

AGGIORNAMENTO : protegge anche da Now On Tap o altri assistenti su Android 6.0; non avranno accesso ai dettagli di widget e contenitori nell'interfaccia utente se l'utente richiama l'assistente.

AGGIORNAMENTO # 2 : tuttavia, non tutto sarà protetto. Tutte le finestre pop-up - Dialog, Spinner, AutoCompleteTextView, azione barra di troppo pieno, ecc - sarà insicuro. È possibile risolvere il Dialogproblema chiamando getWindow()e impostando FLAG_SECURE. Il resto ... diventa complicato. Vedi questo post sul blog per ulteriori informazioni.


6
@Dany's: in realtà, ha tutto a che fare con la domanda. L'ho appena testato su un Nexus S (4.0.3) e funziona come previsto: lo screenshot delle attività recenti è stato soppresso. Vedi ancora il nome e l'icona dell'applicazione, ma lo screenshot è nero. Sei il benvenuto per provarlo su hardware ICS.
CommonsWare il

2
@ StingRay5: FLAG_SECUREesiste sin dall'inizio - aveva un significato limitato fino a poco tempo fa.
CommonsWare il

1
È interessante notare che esiste un metodo chiamato onCreateThumbnail nel ciclo di vita dell'attività, ma non viene mai utilizzato.
Snicolas,

2
@PankajKumar: Se il "codice per catturare la schermata" che hai scritto è quel classico trucco "prendi il framebuffer come root", FLAG_SECUREnon ti difenderà dal momento che è troppo basso livello. Allo stesso modo, se hai preso la tua gerarchia di widget e l'hai fatta attirare Bitmapindietro Canvas, FLAG_SECUREprobabilmente non ti difenderai da questo, poiché stai prendendo i tuoi screenshot dei tuoi widget e quindi presumibilmente volevi quelli "sicuri" lì dentro. FLAG_SECUREè per schermate di sistema , come le miniature delle attività recenti.
CommonsWare,

2
Risposta meravigliosa e semplice! Mi chiedo perché app come Snapchat non lo utilizzino per impedire a qualcuno di fare uno screenshot delle immagini inviate.
Shobhit Puri,

78

Fai attenzione a utilizzare WindowManager.LayoutParams.FLAG_SECURE, su alcuni dispositivi (verificato su Samsung Galaxy ACE, ad esempio GT-S5830), ciò renderà la vista confusa. Sembra un bug specifico di Samsung. Raccomando quanto segue:

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

Ecco come appare uno schermo criptato:

Immagine di schermo criptata

Funziona correttamente sui telefoni ICS Samsung, quindi presumo che il problema sia isolato dai dispositivi Gingerbread (o precedenti).


8
Hai perfettamente ragione, ci siamo imbattuti in questo problema ed era certamente necessario verificare il livello API. In realtà ho dimenticato di postare questo, quindi grazie per averlo riportato di nuovo. :)
StingRay5,

Si verifica anche su Samsung Gio (Gingerbread) ma su Froyo è ok - quindi si verifica solo su 2.3
pixel

Abbiamo notato anche questo problema. Puoi verificare nell'emulatore sui dispositivi Gingerbread.
twaddington,

Posso anche confermare che questo problema appare sui dispositivi Samsung Gingerbread.
Ernir Erlingsson,

7
Anche nelle versioni Android più recenti FLAG_SECURE può essere problematico: su Android 4.3 FLAG_SECURE causa problemi di animazione nell'animazione di rotazione dello schermo, vedi code.google.com/p/android/issues/detail?id=58632 - questo problema è stato risolto su Android 4.4
Oliver

13

La soluzione fornita da CommonsWare continua ad essere valida anche in Lollipop.

Solo una nota, se si desidera continuare a non visualizzare le istantanee nell'elenco recente per l' intera app, TUTTE le attività implementate devono specificare nel onCreate()metodo il flag getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); primasetContentView();

Altrimenti un'istantanea nell'elenco recente mostrerà la prima attività senza il flag se l'utente ha navigato attraverso di essa.


1
Nella mia app, ho la funzionalità di impostare / cancellare FLAG_SECURE in base alle preferenze dell'utente. Ha funzionato bene fino a quando KITKAT e lo schermo nero possono essere visti nel selettore di attività. In Lollipop, la panoramica mostra l'ultima istantanea della mia app, l'ora in cui FLAG_SECURE non è stato impostato (cancellato).
r.bhardwaj,

@ r.bhardwaj penso che non possiamo fare così tanto in quel caso, ma puoi avvisare l'utente che, la modifica ha bisogno di riavviare l'App per avere pieno effetto ;-) e il gioco è fatto.
Davideas,

1
Qualcuno ha trovato un modo per gonfiare una vista personalizzata prima di scattare un'istantanea, quindi non è solo una schermata nera? Ho provato a gonfiare una vista sul gestore delle finestre in onPause, ma sembra che ormai sia troppo tardi.
user1064249

Ciao @ utente1064249 Hai trovato una soluzione? Voglio gonfiare la vista del lanciatore prima che il sistema operativo prenda lo screenshot
Alexiscanny il

1

Ecco una soluzione per nascondere il contenuto di un'app coprendola con una schermata iniziale quando l'app viene messa in background. Questo non sta usando la tecnica FLAG_SECURE, ho semplicemente l'override dei metodi onPause e onResume delle schermate e ho modificato la vista per mostrarne una che copre tutto ciò che sta dietro.

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


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

questo ha funzionato per me, impedisce di fare screenshot e anche qualsiasi applicazione di registrazione integrata o di terze parti dalla schermata di registrazione.


0

Questo funziona per me dopo aver aggiunto queste righe in onCreate prima di setContentView di ogni attività.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.