iOS 7マルチタスクスイッチャーでスクリーンショットを制御する


98

私はiOS 7の新しいマルチタスクスイッチャーに関するいくつかの情報、特にアプリが休止状態になったときにOSが撮るスクリーンショットを探しています。

ここに画像の説明を入力してください

この機能またはスクリーンショットを完全にオフにする方法はありますか?または、アプリをスイッチャーから完全に非表示にできますか?アプリはバックグラウンドで実行する必要がありますが、アプリのスクリーンショットを表示したくありません。

スクリーンショットは潜在的にセキュリティリスクです。デバイスのホームボタンをダブルクリックする誰もがカード番号またはアカウントの概要を利用できるようになる銀行アプリについて考えてください。

これについて洞察力のある人は誰ですか?ありがとう。


1
私の現在の解決策は、アプリが休止状態に入ったときにアプリのロゴを含む空白のビューを読み込み、アプリが戻ったときにそれを削除することですが、その解決策は管理が難しく、エレガントなソリューションというよりはハックのように見えます。また、このソリューションはデバイスなどによっては失敗することがあります。そのため、実際に使用できるソリューションではありません。
Tommie 2013

回答:


101

ではバックグラウンドで実行するようにUIを準備、アップルは言います:

アプリのスナップショット用にUIを準備する

アプリがバックグラウンドに入り、デリゲートメソッドが戻った後のある時点で、UIKitはアプリの現在のユーザーインターフェイスのスナップショットを取得します。システムは結果の画像をアプリスイッチャーに表示します。また、アプリをフォアグラウンドに戻すときに、画像を一時的に表示します。

アプリのUIには、パスワードやクレジットカード番号などの機密性の高いユーザー情報を含めないでください。インターフェイスにそのような情報が含まれている場合は、背景に入るときにビューから削除してください。また、アプリのコンテンツを不明瞭にするアラート、一時的なインターフェイス、およびシステムビューコントローラーを閉じます。スナップショットはアプリのインターフェースを表し、ユーザーが認識できる必要があります。アプリがフォアグラウンドに戻ったら、必要に応じてデータとビューを復元できます。

テクニカルQ&A QA1838:機密情報がタスクスイッチャーに表示されないようにするを参照してください

機密情報を覆い隠す/置き換えることに加えて、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ではなくを使用しています。

デリゲートプロトコルのパターンではなく、通知を使用してこれをすべて処理できるようにしたいのですが、限られたテストでは、通知はタイムリーに十分に処理されませんが、上記のパターンは正常に機能します。


6
ここで述べたように、stackoverflow.com / questions / 18937313 / …シミュレーターでの動作がデバイスでの動作と必ずしも同じではないことに注意してください。
Michael Forrest 2013年

5
ここでignoreSnapshotOnNextApplicationLaunch説明するように、状態の復元中に呼び出されない場合、その価値はありますが無視されます
Charles A.

3
applicationDillEnterBackgroundまでスクリーンショットが取得されないため、applicationWillResignActiveで実行する必要はありません。ホームボタンをダブルタップしても、スクリーンショットは撮られません。あなたが見ている画面はライブです。画面にアニメーションを追加して、サイクルの背景色などを確認します。次に別のアプリを選択すると、実際のスクリーンショットが撮られる前にapplicationDidEnterBackgroundが呼び出されます。
honus

3
ところで、私はAppleのエンジニアから、ドキュメントre ignoreSnapshotOnNextApplicationLaunchが正しくないことを知らされていました。私たち全員が観察したように、スナップショットは実際に取得されますが、次回の起動では使用されません。
Robは

2
ignoreSnapshotOnNextApplicationLaunchは、アプリケーションの起動時にスクリーンショットが表示されないように、次のように動作するようです。マルチタスクUIのスクリーンショット、またはアプリケーションが起動ではなく再開されている場合には影響しません。
グレンメイナード2014年

32

これは私が私のアプリケーションで使用したソリューションです:

Tommyの言うとおり、applicationWillResignActiveを使用できます。私がやったことは、SplashImageでUIImageViewを作成し、それをサブビューとしてメインウィンドウに追加することでした。

(void)applicationWillResignActive:(UIApplication *)application
{
    imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    [imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
    [self.window addSubview:imageView];
}

ホームボタンをダブルタップしてもapplicationDidEnterBackgroundがトリガーされず、applicationWillResignActiveがトリガーされるため、applicationDidEnterBackgroundの代わりにこのメソッドを使用しました。他の場合にも引き起こされる可能性があると人々が言っ​​ているのを聞いたので、問題が発生するかどうかを確認するために引き続きテストしていますが、今のところありません!;)

ここでimageviewを削除します:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(imageView != nil) {
        [imageView removeFromSuperview];
        imageView = nil;
    }
}

お役に立てれば!

補足:シミュレータと実際のデバイスの両方でこれをテストしました。シミュレータでは表示されませんが、実際のデバイスでは表示されます!


2
欠点が1つあります。ユーザーが通知ドックをプルダウンすると、applicationWillResignActiveが呼び出されます。したがって、アプリのコンテンツが表示されることを期待しながら、指を上から下にスライドしてその画像を表示します。
キリルガマスコフ2014

4
applicationWillResignActiveの機密情報をぼかし、aplicationDidEnterBackgroundにimageViewを設定することをお勧めします
Kirill Gamazkov

この作品、しかし、iOS7に展開xCode6で構築された回転のバグがあります:stackoverflow.com/questions/26147068/...
アレックス・ストーン

applicationWillResignActiveで言及したコードを書いた場合、アプリをフォアグラウンド状態に戻すと何が表示されますか?「Portrait(768x1024).png」の画像または実際の画面は表示されますか?
NSPratik 2014

2
@Pratik:applicationDidBecomeActiveメソッド(上記を参照)で再度削除しない限り、画像が表示されます。
ローラ

14

このすばやく簡単な方法では、iOS7以降のアプリスイッチャーでアプリのアイコンの上に黒いスナップショットが表示されます。

まず、アプリのキーウィンドウ(通常、application:didFinishLaunchingWithOptionsのAppDelegate.mで設定)を取得し、アプリがバックグラウンドに移動しようとしているときに非表示にします。

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

4

私は次のソリューションを使用しました。アプリケーションが辞任するときに、appWindowスナップショットをビューとして取得し、ぼかしを追加します。次に、このビューをアプリウィンドウに追加します

これを行う方法:

  1. appDelegateで、実装の直前に行を追加します。

    static const int kNVSBlurViewTag = 198490;//or wherever number you like
  2. このメソッドを追加します。

    - (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;
        }
  3. 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];
    }

SwiftObjective Cでサンプルプロジェクトを作成しました。どちらのプロジェクトでも、次のアクションを実行します。

-application:didResignActive-スナップショットが作成され、ぼかされ、アプリウィンドウに追加されます

-application:willBecomeActiveブラービューがウィンドウから削除されます。

使い方:

Objecitve C

  1. AppDelegate+NVSBlurAppScreenプロジェクトに.hおよび.mファイルを追加する

  2. -applicationWillResignActive:メソッドに次の行を追加します。

    [self nvs_blurPresentedView];
  3. -applicationDidEnterBackground:メソッドに次の行を追加します。

    [self nvs_unblurPresentedView];

迅速

  1. AppDelegateExtention.swiftファイルをプロジェクトに追加します

  2. applicationWillResignActive関数に次の行を追加します。

    blurPresentedView()
  3. applicationDidBecomeActive関数に次の行を追加します。

    unblurPresentedView()

2

関数でのみ使用[self.window addSubview:imageView];するapplicationWillResignActive場合、このimageViewはUIAlertView、UIActionSheetまたはMFMailComposeViewControllerをカバーしません...

最善の解決策は

- (void)applicationWillResignActive:(UIApplication *)application
{
    UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
    [mainWindow addSubview:imageView];
}

ウェブビューでフルスクリーンモードで動画を再生している場合は、非常に良い解決策です。
トミー

優れた!。マルチタスクスイッチャーに入る前にキーパッドを開いていても機能します。ありがとう
Prabhu.Somasundaram 2017

0

私自身のソリューションを「回答」として提供しますが、このソリューションは非常に信頼できません。スクリーンショットとして黒い画面が表示されることもあれば、XIBが表示されたり、アプリ自体からスクリーンショットが表示されることもあります。デバイスによって、および/またはシミュレータでこれを実行するかどうかによって異なります。

アプリ固有の詳細がたくさんあるため、このソリューションのコードは提供できません。しかし、これは私のソリューションの基本的な要点を説明するはずです。

AppWeleResignActiveの下のAppDelegate.mで、iOS7を実行しているかどうかを確認します。実行している場合は、中央にapp-logoがある空の新しいビューをロードします。applicationDidBecomeActiveが呼び出されたら、古いビューを再起動します。これはリセットされますが、これは、開発しているアプリケーションのタイプで機能します。


1
カメラアプリの機能を確認すると、背景に移動すると画像がぼやけた画像に変化します(アイコンに変化するにつれて変化がわかります)
Petesh

@Peteshはい、それは素晴らしい実装ですが、問題は彼らがそれをどのように行うかです。プライベートAPIが怖い。
Rob

@Tommie「デバイスに依存している、またはシミュレータでこれを実行しているかどうか」と言います。私には、デバイスでは機能しているように見えますが(私は完全なテストを行っていません)、シミュレータでは機能していません。デバイスで機能しないと思いますか?
Rob

0

アクティベーターを使用して、マルチタスクを起動するホームボタンのダブルクリックを構成し、ホームボタンのデフォルトのダブルクリックとマルチタスクウィンドウの起動を無効にすることができます。このメソッドは、スクリーンショットをアプリケーションのデフォルト画像に変更するために使用できます。これは、デフォルトのパスコード保護機能を備えたアプリに適用されます。


-2

Xamarin.iOS

https://stackoverflow.com/a/20040270/7561から適応

単に色を表示する代わりに、起動画面を表示したいと思いました。

 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();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.