iOS Erkennung von Screenshots?


135

Die App Snapchat im App Store ist eine App, mit der Sie Bilder mit einer Selbstzerstörung teilen können. Sie können die Bilder nur für X Sekunden anzeigen. Wenn Sie versuchen, einen Screenshot zu machen, während das Bild mit der Home-Power-Tastenkombination angezeigt wird, wird dem Absender mitgeteilt, dass Sie versucht haben, einen Screenshot zu machen.

In welchem ​​Teil des SDK können Sie erkennen, dass der Benutzer einen Screenshot macht? Ich wusste nicht, dass dies möglich ist.


1
stackoverflow.com/questions/2121970/… , Sieht so aus, als hätte es -applicationDidEnterBackground aufgerufen: bevor Sie den Screenshot früher aufgenommen haben. Da bin ich mir jetzt nicht sicher.
iDev

Jungs. Der andere Thread hat die Antwort: stackoverflow.com/questions/2121970/…
me2

1
Überprüfen Sie dies auch, stackoverflow.com/a/8711894/1730272 , es heißt, es ist nicht mehr möglich. Wahrscheinlich können Sie das ausprobieren und uns Bescheid geben.
iDev

Ich habe dies noch nirgendwo im Internet erwähnt gesehen, aber ich würde davon ausgehen, dass die App es absolut nicht wissen kann, wenn Sie Xcode verwenden, um einen Screenshot (vom Gerät im Organizer-Fenster) zu machen. Es muss die Kamerarolle auf alle Fotos überwachen, die beim Anzeigen eines empfangenen Snapchat-Fotos hinzugefügt wurden, und das Aufnehmen des Screenshots über Xcode umgeht dies insgesamt (ohne dass ein Jailbreak erforderlich ist).
Smileyborg

Follow-up: Testete diese Theorie und bestätigte, dass die App keine Xcode-Screenshots erkennt. Interessant ist jedoch, dass Apps unter iOS 6 ausdrücklich die Berechtigung zum Zugriff auf Fotos erhalten müssen. Diese App erkennt jedoch weiterhin Screenshots, ohne dass sie auf Fotos zugreifen kann. Es muss eine andere Erkennungsmethode verwendet werden. Ich stelle fest, dass bei Verwendung der Home + Sleep-Tastenmethode auch das aktive Foto vom Bildschirm entfernt wird. Es muss also ein Muster für diesen Screenshot-Prozess geben, den die App zuverlässig überwachen kann, möglicherweise mit einem GestureRecognizer?
Smileyborg

Antworten:


22

Ich habe die Antwort gefunden !! Wenn Sie einen Screenshot machen, werden alle Berührungen auf dem Bildschirm unterbrochen. Aus diesem Grund muss Snapchat gedrückt gehalten werden, um das Bild zu sehen. Referenz: http://tumblr.jeremyjohnstone.com/post/38503925370/how-to-detect-screenshots-on-ios-like-snapchat


15
Gilt nicht mehr für iOS 7. Eine iOS7 + -Lösung finden Sie weiter unten .
Joe Masilotti

6
Was Joe gesagt hat, ist richtig. Asker sollte dies als die richtige Antwort deaktivieren.
Gott der Kekse

UIApplication Benutzer hat Screenshot Benachrichtigung kann verwendet werden .. iOS 7+
Amit Tandel

353

Ab iOS 7 sind die anderen Antworten nicht mehr wahr. Apple hat es so gemacht, dass touchesCancelled:withEvent:es nicht mehr aufgerufen wird, wenn der Benutzer einen Screenshot macht.

Dies würde Snapchat effektiv vollständig zerstören, so dass ein paar Betas in einer neuen Lösung hinzugefügt wurden. Jetzt ist die Lösung so einfach wie die Verwendung von NSNotificationCenter, um UIApplicationUserDidTakeScreenshotNotification einen Beobachter hinzuzufügen .

Hier ist ein Beispiel:

Ziel c

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationUserDidTakeScreenshotNotification
                                                  object:nil
                                                   queue:mainQueue
                                              usingBlock:^(NSNotification *note) {
                                                 // executes after screenshot
                                              }];

Schnell

NotificationCenter.default.addObserver(
    forName: UIApplication.userDidTakeScreenshotNotification,
    object: nil,
    queue: .main) { notification in
        //executes after screenshot
}

3
Wenn Sie dies verwenden, touchesCancelled:withEvent:sollten Sie einen Screenshot aller (aktuellen) Versionen von iOS erkennen können.
Joshua Gross

46
Dies funktioniert nicht, um zu verhindern, dass ein Screenshot aufgenommen wird. Die App kann nur wissen, dass eine aufgenommen wurde. Aus der UIApplication-Klassenreferenz: UIApplicationUserDidTakeScreenshotNotification Wird veröffentlicht, wenn der Benutzer die Home- und Lock-Tasten drückt, um einen Screenshot zu erstellen. Diese Benachrichtigung enthält kein userInfo-Wörterbuch. Diese Benachrichtigung wird NACH der Aufnahme des Screenshots veröffentlicht.
Badweasel

6
@ Badweasel Richtig. In Anbetracht der Tatsache, dass diese Benachrichtigung den herkömmlichen Kakao-Namenskonventionen entspricht, bedeutet das Wort "Did", dass sie nachträglich veröffentlicht wird. In diesem Fall gibt es kein "Will" -Äquivalent und AFAIK kann den Benutzer nicht daran hindern, einen Screenshot mit der öffentlichen API zu erstellen.
Mick MacCallum

1
Beachten Sie, dass ich Ihnen eine +1 gegeben habe. Ich hatte die OP-Frage ursprünglich falsch verstanden und dachte, die Frage sei, wie man sie erkennt, um etwas zu verhindern - denn das war es, wonach ich suchte. Deshalb habe ich gerade die Klarstellung in den Kommentar eingefügt, da ich davon ausgehe, dass viele Leute, die zu dieser Frage kommen, nach dieser Antwort suchen. Ich nahm das auch vom Wort "tat" an, aber die Dokumentation macht es noch deutlicher. In meiner App erlaube ich Leuten, Fotos zu bearbeiten, aber einige der Tools erfordern IAPs. Aber ich lasse sie es vor dem Kauf versuchen. Ich wollte also erkennen, bevor es aufgenommen wurde, um ein Wasserzeichen hinzuzufügen. Kann nicht gemacht werden.
Badweasel

1
@MickMacCallum Gibt es einen bestimmten Grund, warum Sie dies in der Hauptwarteschlange tun?
kidsid49

13

Hier ist, wie man in Swift mit Schließungen umgeht:

func detectScreenShot(action: () -> ()) {
    let mainQueue = NSOperationQueue.mainQueue()
    NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationUserDidTakeScreenshotNotification, object: nil, queue: mainQueue) { notification in
        // executes after screenshot
        action()
    }
}

detectScreenShot { () -> () in
    print("User took a screen shot")
}

Swift 4.2

func detectScreenShot(action: @escaping () -> ()) {
    let mainQueue = OperationQueue.main
    NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: mainQueue) { notification in
        // executes after screenshot
        action()
    }
}

Dies ist als Standardfunktion enthalten in:

https://github.com/goktugyil/EZSwiftExtensions

Haftungsausschluss: Es ist mein Repo


Hey, ich habe es versucht und es hat super funktioniert, aber kannst du erklären, was im Code ein wenig vor sich geht? Ich bin neu bei Swift und es ist ein bisschen schwer zu lesen.
aecend

Dies ist einer dieser Codes, "wenn es funktioniert, leg dich nicht damit an". Sie müssen nicht lernen, was dies bewirkt, da die hier verwendeten Frameworks sehr selten sind.
Esqarrouth

Aber Sie sollten überprüfen, wie Verschlüsse funktionieren, wenn Sie diesen Teil nicht kennen. Wenn Sie Screenshot-Funktion erkennen, wird alles, was Sie in die Klammern setzen, als Aktionsfunktion gesendet
Esqarrouth,

@Esqarrouth Gibt es einen bestimmten Grund, warum Sie dies in der Hauptwarteschlange tun?
kidsid49

Ursache des Kopierens Einfügen
Esqarrouth

4

Neueste SWIFT 3 :

func detectScreenShot(action: @escaping () -> ()) {
        let mainQueue = OperationQueue.main
        NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot, object: nil, queue: mainQueue) { notification in
            // executes after screenshot
            action()
        }
    }

Rufen Sie in viewDidLoad diese Funktion auf

detectScreenShot { () -> () in
 print("User took a screen shot")
}

Jedoch,

NotificationCenter.default.addObserver(self, selector: #selector(test), name: .UIApplicationUserDidTakeScreenshot, object: nil)

    func test() {
    //do stuff here
    }

funktioniert völlig gut. Ich sehe keine Punkte von mainQueue ...


Die Frage ist, wie man benachrichtigt wird, bevor der Screenshot aufgenommen wird. Dies sagt Ihnen, nachdem es genommen wurde.
rmaddy

1
@rmaddy wo hast du gesehen, dass diese Frage fragt, wie man vorher benachrichtigt wird? Ich habe nur die Antwort über mir verbessert, nicht sicher, Ihre Kommentarabsicht ..
Maksim Kniazev

Die Frage lautet : "Erkennen, dass der Benutzer einen Screenshot macht" . Wenn das OP es später wissen wollte, sollte die Frage lauten: "Erkennen, dass der Benutzer einen Screenshot gemacht hat" .
rmaddy

1

Es gibt anscheinend keine direkte Möglichkeit, dies zu tun, um festzustellen, ob der Benutzer darauf getippt hat home + power button. Aus diesem Grund war es früher möglich, Darwin-Benachrichtigungen zu verwenden, aber es funktioniert nicht mehr. Da Snapchat dies bereits tut, schätze ich, dass sie das iPhone-Fotoalbum überprüfen, um festzustellen, ob zwischen diesen 10 Sekunden ein neues Bild hinzugefügt wurde, und in gewisser Weise mit dem aktuell angezeigten Bild vergleichen. Möglicherweise wird für diesen Vergleich eine Bildverarbeitung durchgeführt. Nur ein Gedanke, wahrscheinlich können Sie versuchen, dies zu erweitern, damit es funktioniert. Überprüfen Sie dies für weitere Details .

Bearbeiten:

Es sieht so aus, als würden sie das UITouch-Abbruchereignis erkennen (Bildschirmaufnahme bricht Berührungen ab) und dem Benutzer diese Fehlermeldung gemäß diesem Blog anzeigen : So erkennen Sie Screenshots unter iOS (wie SnapChat)

In diesem Fall können Sie – touchesCancelled:withEvent:die UITouch-Stornierung mithilfe einer Methode erfassen, um dies zu erkennen. Sie können das Bild in dieser Delegatmethode entfernen und dem Benutzer eine entsprechende Warnung anzeigen.

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];

    NSLog(@"Touches cancelled");

    [self.imageView removeFromSuperView]; //and show an alert to the user
}

Sie scheinen an den richtigen Stellen gut verbunden zu sein, um eine endgültige Antwort darauf zu erhalten;)
Smileyborg

Es ist eher eine fundierte Vermutung als eine endgültige Antwort. Leider habe ich keine Verbindungen, um eine genaue Antwort darauf zu bekommen. Wenn sie keine privaten APIs verwenden, kann ich mir dies nur vorstellen. Erkennen des Bildzusatzes zum Album und Vergleichen des Bildes mit dem aktuellen Bild auf dem Bildschirm basierend auf einem Algorithmus.
iDev

Aber da sie dies tun können, ohne Zugriff auf die Fotos und die Kamerarolle des Geräts anzufordern ... muss es etwas anderes sein, nein? Meine Theorie hängt damit zusammen, dass Sie lange auf die empfangene Fotonachricht drücken, um sie anzuzeigen, und dass Home + Lockdas Betriebssystem beim Drücken von Tasten sofort so tut, als würden keine Finger den Bildschirm berühren. Vielleicht geschieht dies ohne einen touchesEnded:withEvent(oder einen ähnlichen Rückruf) wie normalerweise, sodass sie möglicherweise auf dieses einzigartige Ereignismuster überwachen können? Ich bin vielleicht völlig auf dem falschen Weg, aber das ist derzeit meine einzige Theorie.
Smileyborg

Legen Sie einen Finger auf den Bildschirm und versuchen Sie, ohne ihn anzuheben, die anderen beiden Tasten zu drücken. Es zeigte immer noch diese Nachricht, denke ich. Vielleicht verwenden sie eine private API und haben es irgendwie geschafft, sie in den Appstore zu stellen.
iDev

2
Ab iOS 7 nicht mehr möglich.
God of Biscuits

1

Swift 4+

NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: OperationQueue.main) { notification in
           //you can do anything you want here. 
        }

Mit diesem Beobachter können Sie herausfinden, wann der Benutzer einen Screenshot macht, aber Sie können ihn nicht verhindern.


0

Swift 4 Beispiele

Beispiel 1 mit Verschluss

NotificationCenter.default.addObserver(forName: .UIApplicationUserDidTakeScreenshot, 
                                       object: nil, 
                                       queue: OperationQueue.main) { notification in
    print("\(notification) that a screenshot was taken!")
}

Beispiel 2 mit Selektor

NotificationCenter.default.addObserver(self, 
                                       selector: #selector(screenshotTaken), 
                                       name: .UIApplicationUserDidTakeScreenshot, 
                                       object: nil)

@objc func screenshotTaken() {
    print("Screenshot taken!")
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.