Управление скриншотом в многозадачном коммутаторе iOS 7
Я пытался найти некоторую информацию о новом многозадачном коммутаторе в iOS 7 и особенно скриншот, который ОС делает, когда приложение переходит в спящий режим.
Есть ли способ полностью отключить эту функцию или скриншот? Или я могу полностью скрыть приложение от переключателя? Приложение должно работать в фоновом режиме, но мы не хотим показывать скриншот из приложения.
Снимок экрана представляет потенциальную угрозу безопасности, подумайте о банковских приложениях, в которых номер вашей карты или сводная информация о счете будут доступны всем, кто дважды щелкнет кнопку "Домой" на устройстве.
Кто-нибудь с каким-либо пониманием этого? Благодарю.
8 ответов
В Руководстве по программированию приложений для iOS Apple говорит:
Удалите конфиденциальную информацию из представлений, прежде чем перейти к фону.
Когда приложение переходит в фоновый режим, система делает снимок главного окна приложения, который затем кратко представляет при переводе приложения обратно на передний план. Прежде чем вернуться из вашего
applicationDidEnterBackground:
метод, вы должны скрыть или скрыть пароли и другую конфиденциальную личную информацию, которая может быть захвачена как часть снимка.
В дополнение к маскировке / замене конфиденциальной информации вы можете также попросить iOS 7 не делать снимок экрана с помощью ignoreSnapshotOnNextApplicationLaunch
, Согласно документации для этого метода:
Если вы чувствуете, что моментальный снимок не может правильно отражать пользовательский интерфейс вашего приложения при перезапуске приложения, вы можете позвонить [
ignoreSnapshotOnNextApplicationLaunch
], чтобы предотвратить создание снимка.
Сказав это, кажется, что снимок экрана все еще сделан, и поэтому я подал отчет об ошибке. Но вы должны проверить дальше и посмотреть, поможет ли использование этого параметра.
Если бы это было корпоративное приложение, вы также можете посмотреть соответствующие настройки allowScreenShot
обрисовано в общих чертах в разделе " Полезные данные ограничений" справочника профилей конфигурации.
Вот реализация, которая достигает того, что мне нужно. Вы можете представить свой собственный UIImageView
или вы можете использовать шаблон протокола делегата, чтобы скрыть конфиденциальную информацию:
// SecureDelegate.h
#import <Foundation/Foundation.h>
@protocol SecureDelegate <NSObject>
- (void)hide:(id)object;
- (void)show:(id)object;
@end
Затем я дал делегату приложения свойство для этого:
@property (weak, nonatomic) id<SecureDelegate> secureDelegate;
Мой контроллер вида устанавливает это:
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.secureDelegate = self;
}
Контроллер представления, очевидно, реализует этот протокол:
- (void)hide:(id)object
{
self.passwordLabel.alpha = 0.0;
}
- (void)show:(id)object
{
self.passwordLabel.alpha = 1.0;
}
И, наконец, мой делегат приложения использует этот протокол и свойство:
- (void)applicationWillResignActive:(UIApplication *)application
{
[application ignoreSnapshotOnNextApplicationLaunch]; // this doesn't appear to work, whether called here or `didFinishLaunchingWithOptions`, but seems prudent to include it
[self.secureDelegate hide:@"applicationWillResignActive:"]; // you don't need to pass the "object", but it was useful during my testing...
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self.secureDelegate show:@"applicationDidBecomeActive:"];
}
Обратите внимание, я использую applicationWillResignActive
а не рекомендованный applicationDidEnterBackground
, потому что, как уже отмечали другие, последний не вызывается при двойном нажатии на кнопку домой, когда приложение работает.
Я хотел бы использовать уведомления для обработки всего этого, а не шаблон протокола делегата, но в моем ограниченном тестировании уведомления не обрабатываются достаточно своевременно, но приведенный выше шаблон работает нормально.
Это решение, с которым я работал для моего приложения:
Как сказал Томми: Вы можете использовать приложение WillResignActive. Я сделал UIImageView с моим SplashImage и добавил его как подпредставление в мое главное окно.
(void)applicationWillResignActive:(UIApplication *)application
{
imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
[imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
[self.window addSubview:imageView];
}
Я использовал этот метод вместо applicationDidEnterBackground, потому что applicationDidEnterBackground не будет срабатывать, если вы дважды нажмете кнопку "Домой", и будет приложение applicationWillResignActive. Я слышал, как люди говорят, что это может быть вызвано и в других случаях, так что я все еще проверяю, не вызывает ли это проблемы, но пока нет!;)
Здесь, чтобы удалить изображение:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(imageView != nil) {
[imageView removeFromSuperview];
imageView = nil;
}
}
Надеюсь это поможет!
Sidenote: Я тестировал это как на симуляторе, так и на реальном устройстве: он не будет отображаться на симуляторе, но на реальном устройстве!
Этот быстрый и простой метод создаст черный снимок над значком вашего приложения в переключателе приложений iOS7 или новее.
Во-первых, возьмите ключевое окно вашего приложения (обычно это настраивается в AppDelegate.m в приложении: didFinishLaunchingWithOptions) и спрячьте его, когда ваше приложение собирается перейти в фоновый режим:
- (void)applicationWillResignActive:(UIApplication *)application
{
if(isIOS7Or8)
{
self.window.hidden = YES;
}
}
Затем откройте окно ключа вашего приложения, когда оно снова станет активным:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(isIOS7Or8)
{
self.window.hidden = NO;
}
}
На этом этапе проверьте переключатель приложений и убедитесь, что вы видите черный снимок над значком вашего приложения. Я заметил, что если вы запустите переключатель приложений сразу после перемещения вашего приложения в фоновый режим, может произойти задержка ~5 секунд, когда вы увидите снимок вашего приложения (тот, который вы хотите скрыть!), После того, как который он переходит в полностью черный снимок. Я не уверен, что случилось с задержкой; если у кого-то есть предложения, пожалуйста, свяжитесь с нами.
Если вы хотите, чтобы в переключателе был цвет, отличный от черного, вы могли бы сделать что-то вроде этого, добавив подпредставление с любым фоновым цветом:
- (void)applicationWillResignActive:(UIApplication *)application
{
if(isIOS7Or8)
{
UIView *colorView = [[[UIView alloc] initWithFrame:self.window.frame] autorelease];
colorView.tag = 9999;
colorView.backgroundColor = [UIColor purpleColor];
[self.window addSubview:colorView];
[self.window bringSubviewToFront:colorView];
}
}
Затем удалите этот цветной подпредставление, когда ваше приложение снова станет активным:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(isIOS7Or8)
{
UIView *colorView = [self.window viewWithTag:9999];
[colorView removeFromSuperview];
}
}
Я использовал следующее решение: когда приложение собирается уйти в отставку, я получаю снимок appWindow как вид и добавляю к нему размытие. Затем я добавляю этот вид в окно приложения.
как это сделать:
в appDelegate перед реализацией добавить строку:
static const int kNVSBlurViewTag = 198490;//or wherever number you like
добавить эти методы:
- (void)nvs_blurPresentedView { if ([self.window viewWithTag:kNVSBlurViewTag]){ return; } [self.window addSubview:[self p_blurView]]; } - (void)nvs_unblurPresentedView { [[self.window viewWithTag:kNVSBlurViewTag] removeFromSuperview]; } #pragma mark - Private - (UIView *)p_blurView { UIView *snapshot = [self.window snapshotViewAfterScreenUpdates:NO]; UIView *blurView = nil; if ([UIVisualEffectView class]){ UIVisualEffectView *aView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]]; blurView = aView; blurView.frame = snapshot.bounds; [snapshot addSubview:aView]; } else { UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:snapshot.bounds]; toolBar.barStyle = UIBarStyleBlackTranslucent; [snapshot addSubview:toolBar]; } snapshot.tag = kNVSBlurViewTag; return snapshot; }
сделайте так, чтобы ваша реализация appDelegate была следующей:
- (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. //... //your code //... [self nvs_blurPresentedView]; } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. //... //your code //... [self nvs_unblurPresentedView]; }
Я создал примеры проектов в Swift и Objective C. Оба проекта выполняют следующие действия:
-application: didResignActive - снимок создан, размыт и добавлен в окно приложения
-application: представление размытия willBecomeActive удаляется из окна.
Как пользоваться:
Объектив C
добавлять
AppDelegate+NVSBlurAppScreen
Файлы.h и.m для вашего проектав вашем -applicationWillResignActive: метод добавьте следующую строку:
[self nvs_blurPresentedView];
в вашем -applicationDidEnterBackground: метод добавьте следующую строку:
[self nvs_unblurPresentedView];
стриж
добавьте файл AppDelegateExtention.swift в свой проект
в вашей функции applicationWillResignActive добавьте следующую строку:
blurPresentedView()
в вашей функции applicationDidBecomeActive добавьте следующую строку:
unblurPresentedView()
Если только использовать [self.window addSubview:imageView];
в applicationWillResignActive
функция, этот imageView не будет покрывать UIAlertView, UIActionSheet или MFMailComposeViewController...
Лучшее решение
- (void)applicationWillResignActive:(UIApplication *)application
{
UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
[mainWindow addSubview:imageView];
}
Вы можете использовать активатор для настройки двойного нажатия кнопки "Домой" для запуска многозадачности и отключения по умолчанию двойного нажатия кнопки "Домой" и запуска окна многозадачности. Этот метод можно использовать для изменения снимков экрана на изображение по умолчанию для приложения. Это применимо к приложениям с функцией защиты паролем по умолчанию.
Предоставление моего собственного решения в качестве "ответов", хотя это решение очень ненадежно. Иногда я получаю черный экран как скриншот, иногда XIB и иногда скриншот из самого приложения. В зависимости от устройства и / или если я запускаю это в симуляторе.
Пожалуйста, обратите внимание, что я не могу предоставить код для этого решения, так как там много деталей для конкретного приложения. Но это должно объяснить основную суть моего решения.
В AppDelegate.m под applicationWillResignActive я проверяю, работает ли у нас iOS7, если мы это сделаем, я загружаю новое представление, которое пусто с логотипом приложения в середине. Когда вызывается applicationDidBecomeActive, я перезапускаю свои старые представления, которые будут сброшены, но это работает для типа приложения, которое я разрабатываю.
Xamarin.iOS
Адаптировано с /questions/41613025/upravlenie-skrinshotom-v-mnogozadachnom-kommutatore-ios-7/41613050#41613050
Вместо того, чтобы просто показать цвет, я хотел показать свой экран запуска.
public override void DidEnterBackground(UIApplication application)
{
//to add the background image in place of 'active' image
var backgroundImage = new UIImageView();
backgroundImage.Tag = 1234;
backgroundImage.Image = UIImage.FromBundle("Background");
backgroundImage.Frame = this.window.Frame;
this.window.AddSubview(backgroundImage);
this.window.BringSubviewToFront(backgroundImage);
}
public override void WillEnterForeground(UIApplication application)
{
//remove 'background' image
var backgroundView = this.window.ViewWithTag(1234);
if(null != backgroundView)
backgroundView.RemoveFromSuperview();
}