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 для создания снимка экрана (с устройства в окне «Органайзер»), приложение не сможет узнать об этом. Он должен контролировать Camera Roll для всех фотографий, добавленных во время просмотра полученной фотографии Snapchat, и делать снимок экрана через XCode вообще обходит это (без необходимости джейлбрейка).
— smileyborg

Продолжение: проверил эту теорию и подтвердил, что приложение не обнаруживает скриншоты Xcode. Тем не менее, я понял, что интересно то, что на iOS 6 приложениям должно быть явно предоставлено разрешение на доступ к фотографиям ... но это приложение по-прежнему обнаруживает скриншоты, не позволяя ему получать доступ к фотографиям! Должно быть, используется другой метод обнаружения - я замечаю, что при использовании метода Home + Sleep button активная фотография также удаляется с экрана. Таким образом, должен быть какой-то шаблон, связанный с этим процессом скриншота, который приложение может надежно отслеживать, возможно, с помощью GestureRecognizer?
— smileyborg

Ответы:


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 .

Вот пример:

Цель С

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 Опубликовано, когда пользователь нажимает кнопки «Домой» и «Блокировка», чтобы сделать снимок экрана. Это уведомление не содержит словаря 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")
}

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

Это включено как стандартная функция в:

https://github.com/goktugyil/EZSwiftExtensions

Отказ от ответственности: это мой репо


Эй, я попробовал это, и это отлично сработало, но не могли бы вы немного объяснить, что происходит в коде? Я новичок в Swift, и его немного сложно читать.
— конец

Это один из тех кодов типа «если это работает, не связывайтесь с ним». Вам не нужно изучать, что это делает, потому что используемые здесь фреймворки очень редки.
— Esqarrouth

Но вы должны проверить, как работают замыкания, если вы не знаете эту часть, в основном, когда вы вызываете функцию определения снимка экрана, все, что вы помещаете в парантезы, отправляется как функция действия
— 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

Но, учитывая, что они могут сделать это, не запрашивая доступ к фотографиям устройства и Camera Roll ... это должно быть что-то еще нет? Моя теория была бы связана с тем, что они заставляют вас долго нажимать на полученное фото-сообщение, чтобы просмотреть его, и что, когда вы нажимаете Home + Lockкнопки, ОС немедленно действует так, как будто пальцы не касаются экрана. Может быть, это происходит без touchesEnded:withEvent(или аналогичного обратного вызова), как это обычно бывает , поэтому, возможно, они могут отслеживать этот уникальный паттерн событий? Я могу быть совершенно не на том пути, но это моя единственная теория на данный момент.
— smileyborg

Положите палец на экран и, не поднимая его, попробуйте нажать две другие кнопки. Я думаю, это все еще показывало это сообщение. Так что, может быть, они используют какой-то частный API и каким-то образом удалось разместить его в магазине приложений.
— iDev

2
С iOS 7 больше не возможно.
— God of Biscuits

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.