Wie verhindere ich, dass Android einen Screenshot macht, wenn meine App in den Hintergrund tritt?

146

Die App, die ich gerade erst baue, muss verhindern, dass das Betriebssystem aus Sicherheitsgründen einen Screenshot der App erstellt, wenn diese in den Hintergrund verschoben wird. Auf diese Weise wird beim Wechseln zwischen Apps nicht der letzte aktive Bildschirm angezeigt.

Ich habe vor, diese Funktionalität in die onPause-Methode der Anwendungsklasse aufzunehmen, aber zuerst muss ich herausfinden, wie ich diese Funktionalität erreichen kann.

Gibt es da draußen jemanden, der eine Ahnung hat, wie man das behebt?

StingRay5
quelle

Antworten:

264

Versuchen Sie 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);
  }
}

Dies schützt definitiv vor manuellen Screenshots und automatischen Screenshots aus dem ICS-Verlauf der letzten Aufgaben. Es schützt auch vor Bildschirmaufzeichnungen (z. B. Apps, die die Medienprojektions-APIs verwenden).

UPDATE : Es schützt auch vor Now On Tap oder anderen Assistenten unter Android 6.0. Sie erhalten keinen Zugriff auf die Details von Widgets und Containern in Ihrer Benutzeroberfläche, wenn der Benutzer den Assistenten aufruft.

UPDATE 2 : Es wird jedoch nicht alles in der Aktivität geschützt. Jegliche Pop-up - Fenster - Dialog, Spinner, AutoCompleteTextView, action bar Überlauf, usw. - wird unsicher sein. Sie können das DialogProblem beheben , indem Sie es aufrufen getWindow()und einstellen FLAG_SECURE. Der Rest ... wird schwierig. Weitere Informationen finden Sie in diesem Blogbeitrag .

CommonsWare
quelle
6
@ Dany's: Eigentlich hat es alles mit der Frage zu tun. Ich habe es gerade auf einem Nexus S (4.0.3) getestet und es funktioniert wie erwartet - der Screenshot der letzten Aufgaben wird unterdrückt. Der Anwendungsname und das Symbol werden weiterhin angezeigt, der Screenshot ist jedoch schwarz. Sie können es gerne auf ICS-Hardware ausprobieren.
CommonsWare
2
@ StingRay5: FLAG_SECUREexistiert von Anfang an - es hatte bis vor kurzem nur eine begrenzte Bedeutung.
CommonsWare
1
Interessant zu bemerken, dass es eine Methode namens onCreateThumbnail im Aktivitätslebenszyklus gibt, die jedoch nie verwendet wird.
Snicolas
2
@PankajKumar: Wenn der von Ihnen geschriebene "Code zum Aufnehmen eines Screenshots" der klassische Trick "Framebuffer als Root" ist, FLAG_SECUREwird er sich nicht dagegen wehren, da dies zu niedrig ist. Wenn Sie Ihre eigene Widget-Hierarchie genommen und auf ein Bitmap-backed ziehen lassen Canvas, wird dies FLAG_SECUREwahrscheinlich nicht dagegen verteidigt, da Sie Ihre eigenen Screenshots Ihrer eigenen Widgets machen und daher vermutlich die "sicheren" dort haben wollten . FLAG_SECUREist für System- Screenshots gedacht, z. B. für die Miniaturansichten der letzten Aufgaben.
CommonsWare
2
Wunderbare und einfache Antwort! Ich frage mich, warum Apps wie Snapchat dies nicht verwenden, um zu verhindern, dass jemand einen Screenshot der gesendeten Bilder macht.
Shobhit Puri
78

Seien Sie vorsichtig bei der Verwendung von WindowManager.LayoutParams.FLAG_SECURE. Auf einigen Geräten (überprüft auf Samsung Galaxy ACE, z. B. GT-S5830) wird die Ansicht dadurch verschlüsselt. Sieht aus wie ein Samsung-spezifischer Fehler. Ich empfehle folgendes:

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

So sieht ein verschlüsselter Bildschirm aus:

Verwürfeltes Bildschirmbild

Dies funktioniert jedoch auf ICS-Samsung-Handys ordnungsgemäß, sodass ich davon ausgehe, dass das Problem auf Gingerbread-Geräte (oder ältere Geräte) beschränkt ist.

Gardarh
quelle
8
Sie haben vollkommen recht, wir sind auf dieses Problem gestoßen, und es war sicherlich erforderlich, um die API-Ebene zu überprüfen. Eigentlich habe ich vergessen, dies zu posten, also danke, dass du es wieder angesprochen hast. :)
StingRay5
Es kommt auch auf Samsung Gio (Lebkuchen) vor, aber auf Froyo ist es in Ordnung - so kommt es nur auf 2,3
Pixel
Wir haben dieses Problem ebenfalls bemerkt. Sie können dies im Emulator auf Lebkuchengeräten überprüfen.
Twaddington
Ich kann auch bestätigen, dass dieses Problem auf Samsung Gingerbread-Geräten auftritt.
Ernir Erlingsson
7
Selbst in neueren Android-Versionen kann FLAG_SECURE problematisch sein: Unter Android 4.3 verursacht FLAG_SECURE Animationsprobleme bei der Bildschirmrotationsanimation, siehe code.google.com/p/android/issues/detail?id=58632 - dies wurde unter Android 4.4
Oliver
13

Die von CommonsWare bereitgestellte Lösung ist auch in Lollipop weiterhin gültig.

Nur eine Anmerkung: Wenn Sie weiterhin keine Snapshots in der letzten Liste für die gesamte App sehen möchten , sollten ALLE implementierten Aktivitäten in der onCreate()Methode das Flag getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); vor angebensetContentView();

Andernfalls zeigt ein Schnappschuss in der letzten Liste die erste Aktivität ohne Flag an, wenn der Benutzer durch die Liste navigiert ist.

Davideas
quelle
1
In meiner App habe ich die Möglichkeit, FLAG_SECURE basierend auf einer Benutzereinstellung festzulegen / zu löschen. Es hat gut funktioniert, bis KITKAT und schwarzer Bildschirm im Task-Switcher zu sehen sind. In Lollipop zeigt die Übersicht den letzten Schnappschuss meiner App an, den Zeitpunkt, zu dem FLAG_SECURE nicht festgelegt (gelöscht) wurde.
r.bhardwaj
@ r.bhardwaj Ich denke, wir können in diesem Fall nicht so viel tun, aber Sie können dem Benutzer raten, dass die App neu gestartet werden muss, damit sie vollständig wirksam wird ;-) und Sie sind fertig.
Davideas
1
Hat jemand eine Möglichkeit gefunden, eine benutzerdefinierte Ansicht aufzublasen, bevor ein Schnappschuss erstellt wird, sodass es sich nicht nur um einen schwarzen Bildschirm handelt? Ich habe versucht, eine Ansicht des Fenstermanagers in onPause aufzublähen, aber bis dahin scheint es zu spät zu sein.
user1064249
Hi @ user1064249 Haben Sie eine Lösung gefunden? Ich möchte die Launcher-Ansicht aufblasen, bevor das Betriebssystem den Screenshot macht
Alexiscanny
1

Hier ist eine Lösung zum Ausblenden von Inhalten einer App, indem Sie diese mit einem Begrüßungsbildschirm abdecken, wenn die App in den Hintergrund gestellt wird. Dies verwendet nicht die FLAG_SECURE-Technik. Ich überschreibe einfach die onPause- und onResume-Methoden der Bildschirme und ändere die Ansicht so, dass eine angezeigt wird, die alles im Hintergrund abdeckt.

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

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

Dies hat bei mir funktioniert. Es verhindert, dass Screenshots und auch eingebaute oder Drittanbieter-Aufnahmeanwendungen vom Aufnahmebildschirm aufgenommen werden.

Harte Barnwal
quelle
0

Dies ist Arbeit für mich, nachdem ich diese Zeile vor setContentView für jede Aktivität zu onCreate hinzugefügt habe.

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