การตรวจจับภาพหน้าจอของ iOS?


136

แอพSnapchatบน App Store เป็นแอพที่ให้คุณแชร์รูปภาพด้วยการทำลายตัวเอง คุณสามารถดูภาพได้ X วินาทีเท่านั้น หากคุณพยายามจับภาพหน้าจอในขณะที่ภาพกำลังแสดงโดยใช้คำสั่งผสมปุ่มเปิด / ปิดที่บ้านระบบจะแจ้งผู้ส่งว่าคุณพยายามจับภาพหน้าจอ

ส่วนใดของ SDK ที่ช่วยให้คุณตรวจจับได้ว่าผู้ใช้กำลังจับภาพหน้าจอ ฉันไม่รู้ว่ามันเป็นไปได้


1
stackoverflow.com/questions/2121970/…ดูเหมือนว่าจะใช้เรียก -applicationDidEnterBackground: ก่อนที่จะจับภาพหน้าจอก่อนหน้านี้ ไม่แน่ใจว่าตอนนี้
iDev

พวก. อีกกระทู้มีคำตอบstackoverflow.com/questions/2121970/…
me2

1
ตรวจสอบสิ่งนี้ด้วยstackoverflow.com/a/8711894/1730272มันบอกว่ามันเป็นไปไม่ได้อีกแล้ว คุณอาจลองใช้และแจ้งให้เราทราบ
iDev

ยังไม่เห็นสิ่งนี้กล่าวถึงที่ใด ๆ บนอินเทอร์เน็ต แต่ฉันคิดว่าถ้าคุณใช้ Xcode เพื่อถ่ายภาพหน้าจอ (จากอุปกรณ์ในหน้าต่าง Organizer) ไม่มีทางที่แอปจะรู้ได้อย่างแน่นอน ต้องมีการตรวจสอบ Camera Roll สำหรับรูปภาพที่เพิ่มในขณะที่ดูภาพถ่าย Snapchat ที่ได้รับและการจับภาพหน้าจอผ่าน Xcode จะข้ามสิ่งนี้ไปทั้งหมด (โดยไม่จำเป็นต้องเจลเบรก)
smileyborg

การติดตามผล:ทดสอบทฤษฎีนี้และยืนยันว่าแอปตรวจไม่พบภาพหน้าจอ Xcode อย่างไรก็ตามฉันรู้ว่าสิ่งที่น่าสนใจคือใน iOS 6 แอปต้องได้รับอนุญาตอย่างชัดเจนในการเข้าถึงรูปภาพ ... แต่แอปนี้ยังตรวจจับภาพหน้าจอโดยไม่อนุญาตให้เข้าถึงรูปภาพ ต้องใช้วิธีอื่นในการตรวจจับ - ฉันสังเกตเห็นว่าเมื่อใช้วิธีปุ่ม Home + Sleep รูปภาพที่ใช้งานอยู่จะถูกลบออกจากหน้าจอด้วย ดังนั้นจึงต้องมีรูปแบบบางอย่างที่เกี่ยวข้องกับกระบวนการสกรีนช็อตนี้ที่แอปสามารถตรวจสอบได้อย่างน่าเชื่อถืออาจใช้ GestureRecognizer?
smileyborg

คำตอบ:


22

เจอคำตอบแล้ว !! การจับภาพหน้าจอจะขัดขวางการสัมผัสใด ๆ ที่อยู่บนหน้าจอ นี่คือสาเหตุที่ทำให้ snapchat ต้องถือเพื่อดูภาพ อ้างอิง: http://tumblr.jeremyjohnstone.com/post/38503925370/how-to-detect-screenshots-on-ios-like-snapchat


15
ไม่เป็นจริงกับ iOS 7 อีกต่อไปดูด้านล่างสำหรับโซลูชัน iOS7 +
Joe Masilotti

6
สิ่งที่โจพูดนั้นถูกต้อง ผู้ถามควรยกเลิกการเลือกนี้เป็นคำตอบที่ถูกต้อง
God of Biscuits

UIApplication User Did Take Screenshot Notification สามารถใช้ได้ .. iOS 7+
Amit Tandel

355

สำหรับ iOS 7 คำตอบอื่น ๆ ไม่เป็นความจริงอีกต่อไป Apple ทำให้touchesCancelled:withEvent:ไม่มีการเรียกอีกต่อไปเมื่อผู้ใช้ถ่ายภาพหน้าจอ

สิ่งนี้จะทำลาย Snapchat ได้อย่างมีประสิทธิภาพดังนั้นจึงมีการเพิ่ม betas สองตัวในโซลูชันใหม่ ตอนนี้การแก้ปัญหาเป็นง่ายๆเป็นใช้ NSNotificationCenter เพื่อเพิ่มผู้สังเกตการณ์จะUIApplicationUserDidTakeScreenshotNotification

นี่คือตัวอย่าง:

วัตถุประสงค์ค

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

รวดเร็ว

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

3
ใช้สิ่งนี้และtouchesCancelled:withEvent:ควรช่วยให้คุณตรวจจับภาพหน้าจอใน iOS ทุกเวอร์ชัน (ล่าสุด)
Joshua Gross

46
วิธีนี้ใช้ไม่ได้เพื่อป้องกันไม่ให้ถ่ายภาพหน้าจอ สามารถแจ้งให้แอปทราบได้ว่ามีแอปเดียวเท่านั้น .. จาก UIApplication Class Reference: UIApplicationUserDidTakeSc screenshotNotification โพสต์เมื่อผู้ใช้กดปุ่ม Home และ Lock เพื่อถ่ายภาพหน้าจอ การแจ้งเตือนนี้ไม่มีพจนานุกรม userInfo การแจ้งเตือนนี้ถูกโพสต์หลังจากถ่ายภาพหน้าจอ
badweasel

6
@badweasel ถูกต้อง. เมื่อพิจารณาจากการแจ้งเตือนนี้เป็นไปตามหลักการตั้งชื่อโกโก้ทั่วไปคำว่า "ไม่" หมายความว่ามีการโพสต์หลังจากข้อเท็จจริง ไม่มี "Will" เทียบเท่าในกรณีนี้และ AFAIK จะไม่มีทางป้องกันไม่ให้ผู้ใช้จับภาพหน้าจอโดยใช้ API สาธารณะ
Mick MacCallum

1
โปรดทราบว่าฉันให้ +1 กับคุณ ฉันอ่านคำถาม OP ผิดในตอนแรกและคิดว่าคำถามคือวิธีตรวจจับเพื่อป้องกันบางสิ่ง - เพราะนั่นคือสิ่งที่ฉันกำลังมองหา ดังนั้นฉันจึงเพิ่มคำชี้แจงในความคิดเห็นเพราะฉันคาดว่าจะมีคนจำนวนมากที่มาที่คำถามนี้กำลังมองหาคำตอบนั้น ฉันเดาว่ามาจากคำว่า "ได้" แต่เอกสารประกอบทำให้ชัดเจนยิ่งขึ้น ในแอปของฉันฉันอนุญาตให้คนอื่นแก้ไขรูปภาพได้ แต่เครื่องมือบางอย่างต้องใช้ IAP แต่ฉันให้พวกเขาลองก่อนซื้อ ผมจึงต้องการตรวจจับก่อนที่จะจับภาพเพื่อเพิ่มลายน้ำ ไม่สามารถทำได้
badweasel

1
@MickMacCallum เหตุผลเฉพาะใดที่คุณทำในคิวหลัก?
kidsid49

13

นี่คือวิธีการทำใน Swift ด้วยการปิด:

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")
}

สวิฟต์ 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()
    }
}

ซึ่งรวมอยู่ในฟังก์ชันมาตรฐานใน:

https://github.com/goktugyil/EZSwiftExtensions

Disclaimer: มันเป็น repo ของฉัน


เฮ้ฉันลองแล้วมันก็ใช้ได้ดี แต่ช่วยอธิบายหน่อยได้ไหมว่าเกิดอะไรขึ้นในโค้ด ฉันยังใหม่กับ Swift และอ่านยากไปหน่อย
ขึ้น

นี่คือหนึ่งในรหัสประเภท "ถ้ามันใช้งานได้อย่ายุ่งกับมัน" คุณไม่จำเป็นต้องเรียนรู้ว่าสิ่งนี้ทำให้เกิดกรอบที่ใช้ในที่นี้หายากมาก
Esqarrouth

แต่คุณควรตรวจสอบว่าการปิดทำงานอย่างไรหากคุณไม่ทราบว่าส่วนนั้นโดยพื้นฐานแล้วเมื่อคุณเรียกใช้ฟังก์ชั่นการตรวจจับภาพหน้าจอสิ่งที่คุณเคยใส่ไว้ใน parantheses จะถูกส่งเป็นฟังก์ชันการทำงาน
Esqarrouth

@Esqarrouth เหตุผลเฉพาะใดที่คุณทำในคิวหลัก?
kidsid49

สาเหตุของการคัดลอกวาง
Esqarrouth

4

ล่าสุด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()
        }
    }

ในviewDidLoadเรียกใช้ฟังก์ชันนี้

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

อย่างไรก็ตาม

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

    func test() {
    //do stuff here
    }

ทำงานได้ดีโดยสิ้นเชิง ไม่เห็นประเด็นหลัก ๆ เลย ...


คำถามคือถามว่าจะได้รับการแจ้งเตือนอย่างไรก่อนที่จะถ่ายภาพหน้าจอ สิ่งนี้จะบอกคุณหลังจากถ่ายแล้ว
rmaddy

1
@rmaddy เห็นตรงไหนถามว่าจะแจ้งก่อนได้อย่างไร ฉันปรับปรุงคำตอบข้างต้นเท่านั้นไม่แน่ใจ
ว่าความ

คำถามที่ถาม: "ตรวจพบว่าผู้ใช้จะจับภาพหน้าจอ" หาก OP อยากจะรู้ว่าหลังจากที่จริงคำถามที่ควรอ่านได้: "ตรวจสอบว่าผู้ใช้เอาภาพหน้าจอ"
rmaddy

1

ดูเหมือนว่าจะไม่มีวิธีโดยตรงในการตรวจสอบว่าผู้ใช้แตะhome + power buttonหรือไม่ ตามนี้เป็นไปได้ก่อนหน้านี้โดยใช้การแจ้งเตือนของดาร์วิน แต่ก็ไม่ได้ผลอีกต่อไป เนื่องจาก snapchat กำลังทำอยู่แล้วฉันเดาว่าพวกเขากำลังตรวจสอบอัลบั้มรูปภาพของ iPhone เพื่อตรวจสอบว่ามีการเพิ่มรูปภาพใหม่ในระหว่าง 10 วินาทีนี้หรือไม่และในบางครั้งพวกเขากำลังเปรียบเทียบกับภาพปัจจุบันที่แสดง อาจมีการประมวลผลภาพบางส่วนสำหรับการเปรียบเทียบนี้ เพียงแค่ความคิดคุณอาจลองขยายสิ่งนี้เพื่อให้มันทำงาน ตรวจสอบนี้สำหรับรายละเอียดเพิ่มเติม

แก้ไข:

ดูเหมือนว่าพวกเขาอาจตรวจพบเหตุการณ์ยกเลิก UITouch (การจับภาพหน้าจอยกเลิกการสัมผัส) และแสดงข้อความแสดงข้อผิดพลาดนี้แก่ผู้ใช้ตามบล็อกนี้: วิธีตรวจจับภาพหน้าจอบน iOS (เช่น SnapChat)

ในกรณีนี้คุณสามารถใช้– touchesCancelled:withEvent:วิธีการตรวจจับการยกเลิก UITouch เพื่อตรวจจับสิ่งนี้ คุณสามารถลบภาพในวิธีการมอบหมายนี้และแสดงการแจ้งเตือนที่เหมาะสมแก่ผู้ใช้

- (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
}

ดูเหมือนคุณจะเชื่อมต่อได้ดีในสถานที่ที่เหมาะสมเพื่อรับคำตอบที่ชัดเจนเกี่ยวกับเรื่องนี้)
ไมลีย์บอร์ก

เป็นการคาดเดาที่มีการศึกษามากกว่าคำตอบที่ชัดเจน น่าเสียดายที่ฉันไม่มีความเชื่อมโยงเพื่อรับคำตอบที่แน่นอนสำหรับเรื่องนี้ หากพวกเขาไม่ได้ใช้ API ส่วนตัวนั่นเป็นวิธีเดียวที่ฉันคิดได้ในการทำสิ่งนี้ เพื่อตรวจจับภาพเพิ่มเติมในอัลบั้มและเปรียบเทียบภาพนั้นกับภาพปัจจุบันในหน้าจอตามอัลกอริทึมบางอย่าง
iDev

แต่เนื่องจากพวกเขาสามารถทำได้โดยไม่ต้องร้องขอการเข้าถึงภาพถ่ายของอุปกรณ์และ Camera Roll ... มันต้องเป็นอย่างอื่นไม่ใช่เหรอ? ทฤษฎีของฉันจะเกี่ยวข้องกับการที่พวกเขาทำให้คุณกดข้อความรูปภาพที่ได้รับHome + Lockค้างไว้เพื่อดูและเมื่อคุณกดปุ่มระบบปฏิบัติการจะทำงานทันทีราวกับว่าไม่มีนิ้วสัมผัสหน้าจอ บางทีสิ่งนี้อาจเกิดขึ้นโดยไม่มีtouchesEnded:withEvent(หรือการเรียกกลับที่คล้ายกัน) ตามปกติดังนั้นบางทีพวกเขาสามารถตรวจสอบรูปแบบของเหตุการณ์ที่เป็นเอกลักษณ์นี้ได้? ฉันอาจจะเดินผิดไปหมด แต่นั่นคือทฤษฎีเดียวของฉันในตอนนี้
smileyborg

วางนิ้วบนหน้าจอและไม่ต้องยกขึ้นลองว่าคุณสามารถกดอีกสองปุ่มได้หรือไม่ มันยังคงแสดงข้อความนั้นที่ฉันเดา ดังนั้นอาจเป็นเพราะพวกเขาใช้ API ส่วนตัวและจัดการเพื่อวางใน appstore
iDev

2
เป็นไปไม่ได้อีกต่อไปใน iOS 7
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. 
        }

โดยใช้ผู้สังเกตการณ์นี้คุณจะพบว่าผู้ใช้จับภาพหน้าจอเมื่อใด แต่คุณไม่สามารถป้องกันเขาได้


0

ตัวอย่าง Swift 4

ตัวอย่าง # 1 โดยใช้การปิด

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

ตัวอย่าง # 2 พร้อมตัวเลือก

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

@objc func screenshotTaken() {
    print("Screenshot taken!")
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.