Виявлення екрана iOS?


135

Додаток 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, щоб зробити знімок екрана (з пристрою у вікні Організатора), програма абсолютно не зможе це знати. Потрібно відстежувати камеру за наявністю фотографій, доданих під час перегляду отриманої фотографії Snapchat, і знімок екрана через Xcode обходить це цілком (без необхідності джейлбрейка).
смайлик

Наступні дії: Перевірено цю теорію та підтверджено, що додаток не виявляє скріншоти Xcode. Однак я зрозумів, що цікавого полягає в тому, що на iOS 6 додаткам потрібно явно надати дозвіл на доступ до фотографій ... все ж цей додаток все ще виявляє знімки екрана, не дозволяючи йому отримувати доступ до фотографій! Потрібно використовувати інший метод виявлення - зауважую, що при використанні методу кнопки Home + Sleep активні фотографії також видаляються з екрану. Отже, має бути певна схема, пов'язана з цим процесом скріншоту, який додаток може надійно контролювати, можливо, за допомогою GestureRecognizer?
смайлик

Відповіді:


22

Я знайшов відповідь !! Зйомка екрана перериває будь-які дотики на екрані. Ось чому Snapchat вимагає утримування, щоб побачити зображення. Довідка: http://tumblr.jeremyjohnstone.com/post/38503925370/how-to-detect-screenshots-on-ios-like-snapchat


15
Більше не стосується iOS 7. Дивіться нижче для iOS7 + рішення.
Джо Масілотті

6
Те, що Джо сказав, є правильним. Аскерер повинен зняти це як правильну відповідь.
Бог печива

Користувач UIApplication зробив повідомлення про знімок екрана. IOS 7+
Amit Tandel

353

На iOS 7 інші відповіді більше не відповідають дійсності. Apple зробила це, тому touchesCancelled:withEvent:його більше не називають, коли користувач робить знімок екрана.

Це ефективно розбиває Snapchat повністю, тому було додано пару бета-версій у новому рішенні. Тепер рішення є таким же простим, як використання NSNotificationCenter для додавання спостерігача до UIApplicationUserDidTakeScreenshotNotification .

Ось приклад:

Мета C

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.
Джошуа Гросс

46
Це не працює, щоб запобігти зняттю екрана екрана. Він може повідомити програмі лише про те, що зроблено. З посилань на клас UIApplication: UIApplicationUserDidTakeScreenshotNotification Опубліковано, коли користувач натискає кнопки Home та Lock, щоб зробити знімок екрана. Це сповіщення не містить словника userInfo. Це повідомлення розміщено ПІСЛЯ зроблено скріншот.
badweasel

6
@badweasel Правильно. Зважаючи на те, що це повідомлення слідує звичайним умовам іменування какао, слово "зробив" означає, що воно розміщене після факту. У цьому випадку немає "Воля" еквівалента, і AFAIK не дозволяє запобігти користувачеві зробити знімок екрана за допомогою публічного API.
Мік Маккаллум

1
Зауважте, що я дав вам +1. Я спочатку неправильно прочитав питання про ОП і подумав, що питання полягає в тому, як його виявити, щоб щось запобігти - адже саме це я шукав. Тож я просто додав уточнення до коментаря, тому що я очікую, що багато людей, які приходять до цього питання, шукають цю відповідь. Я припускав, що також від слова "зробив", але документація робить це ще більш зрозумілим. У своєму додатку я дозволяю людям редагувати фотографії, але для деяких інструментів потрібен 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

Відмова: Це моє репо


Гей, я спробував це, і це спрацювало чудово, але чи можете ви трохи пояснити, що відбувається в коді? Я новачок у Свіфті, і це важко читати.
аекс

Це один із таких типів кодів "якщо це працює - не возитися з ним". Вам не потрібно дізнаватися, що це спричиняє рамки, які тут використовуються, дуже рідкісні.
Ескароут

Але ви повинні перевірити, як працюють закриття, якщо ви не знаєте цієї частини, а в основному, коли ви викликаєте функцію виявлення знімання екрана, те, що ви ставите в парантези, надсилається як функція дії
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
    }

працює зовсім чудово. Я не бачу жодних точок mainQueue ...


Питання полягає в тому, як повідомити про це, перш ніж зробити знімок екрана. Це говорить вам після того, як було зроблено.
rmaddy

1
@rmaddy, де ви бачили, що це запитання задає питання, як отримувати повідомлення раніше? Я лише покращив відповідь над собою, не впевнений у вашому намірі коментаря ..
Максим Князєв

Питання задає: "виявити, що користувач робить знімок екрана" . Якщо ОП хотіла дізнатися після факту, слід запитати: "виявити, що користувач зробив знімок екрана" .
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
}

ви, здається, добре зв’язані в потрібних місцях, щоб отримати остаточну відповідь з цього приводу;)
smileyborg

Це скоріше освічена здогадка, ніж остаточна відповідь. На жаль, у мене немає зв’язків, щоб отримати точну відповідь на це. Якщо вони не використовують приватні API, це єдиний спосіб, який я можу зробити для цього. Визначити додавання зображення до альбому та порівняти це зображення з поточним зображенням на екрані на основі певного алгоритму.
iDev

Але враховуючи, що вони можуть це зробити, не вимагаючи доступу до фотографій пристрою та камери Roll ... це повинно бути щось інше ні? Моя теорія пов'язана з тим, що вони змушують вас довго натискати на отримане фотографічне повідомлення, щоб переглянути його, і що при натисканні Home + Lockкнопок ОС відразу діє так, ніби пальці не торкаються екрана. Можливо, це відбувається без touchesEnded:withEvent(або подібного зворотного виклику), як це було б зазвичай, тому, можливо, вони можуть стежити за цією унікальною схемою подій? Можливо, я зовсім на неправильному шляху, але це єдина моя теорія на даний момент.
смайлик

Покладіть палець на екран і, не піднімаючи його, спробуйте, чи можете ви натиснути інші дві кнопки. Я все ще показував це повідомлення, я думаю. Можливо, вони використовують якийсь приватний API і якимсь чином вдалося розмістити в appstore.
iDev

2
Більше не можливо з iOS 7.
Бог із печива

1

Швидкий 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!")
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.