IOS 7 मल्टीटास्किंग स्विचर में स्क्रीनशॉट को नियंत्रित करना


98

मैं iOS 7 में नए मल्टीटास्किंग स्विचर के बारे में कुछ जानकारी खोजने की कोशिश कर रहा हूं और विशेष रूप से स्क्रीनशॉट जो ओएस तब लेता है जब ऐप हाइबरनेशन में जा रहा है।

यहां छवि विवरण दर्ज करें

क्या इस सुविधा या स्क्रीनशॉट को पूरी तरह से बंद करने का कोई तरीका है? या मैं ऐप को पूरी तरह से स्विचर से छिपा सकता हूं? ऐप को पृष्ठभूमि में चलाने की आवश्यकता है, लेकिन हम ऐप से कोई स्क्रीनशॉट नहीं दिखाना चाहते हैं।

स्क्रीनशॉट संभावित रूप से एक सुरक्षा-जोखिम है, बैंकिंग-ऐप्स के लिए उन पंक्तियों पर विचार करें जहां आपका कार्ड नंबर या खाता सारांश किसी को भी उपलब्ध होगा जो डिवाइस पर होम बटन पर डबल-क्लिक करता है।

किसी को भी इस में किसी भी अंतर्दृष्टि के साथ? धन्यवाद।


1
मेरा वर्तमान समाधान ऐप लोगो के साथ रिक्त दृश्य लोड करने के लिए है, जब ऐप हाइबरनेशन में प्रवेश करता है और ऐप वापस आने पर इसे हटा देता है, लेकिन यह समाधान प्रबंधित करने के लिए कठिन है और एक सुरुचिपूर्ण समाधान के बजाय हैक की तरह लगता है। इसके अलावा, यह समाधान डिवाइस आदि के आधार पर समय-समय पर विफल रहता है, इसलिए यह वास्तव में उपयोग करने योग्य नहीं है।
टॉमी

जवाबों:


101

में पृष्ठभूमि में चलाने के लिए अपने यूआई तैयार कर रहा है , एप्पल का कहना है:

ऐप स्नैपशॉट के लिए आपका UI तैयार करें

आपके एप्लिकेशन के बैकग्राउंड में प्रवेश करने के बाद और आपके प्रतिनिधि विधि के वापस आने के कुछ समय बाद, UIKit आपके ऐप के वर्तमान उपयोगकर्ता इंटरफ़ेस का एक स्नैपशॉट लेता है। सिस्टम ऐप स्विचर में परिणामी छवि प्रदर्शित करता है। यह आपके ऐप को अग्रभूमि में लाते समय अस्थायी रूप से छवि प्रदर्शित करता है।

आपके ऐप के UI में कोई भी संवेदनशील उपयोगकर्ता जानकारी नहीं होनी चाहिए, जैसे पासवर्ड या क्रेडिट कार्ड नंबर। यदि आपके इंटरफ़ेस में ऐसी जानकारी है, तो पृष्ठभूमि में प्रवेश करते समय इसे अपने विचारों से हटा दें। इसके अलावा, अलर्ट, अस्थायी इंटरफेस और सिस्टम व्यू कंट्रोलर को खारिज करें जो आपके ऐप की सामग्री को अस्पष्ट करते हैं। स्नैपशॉट आपके ऐप के इंटरफ़ेस का प्रतिनिधित्व करता है और उपयोगकर्ताओं के लिए पहचानने योग्य होना चाहिए। जब आपका ऐप अग्रभूमि में वापस आ जाता है, तो आप डेटा और विचारों को उपयुक्त रूप से पुनर्स्थापित कर सकते हैं।

देखें तकनीकी क्यू एंड ए 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/ ... व्यवहार हमेशा डिवाइस पर सिम्युलेटर में समान नहीं है!
माइकल फॉरेस्ट

5
इसके लायक होने के लिए, ignoreSnapshotOnNextApplicationLaunchविधि को अनदेखा किया जाता है यदि इसे राज्य बहाली के दौरान लागू नहीं किया जाता है, जैसा कि यहां वर्णित है
चार्ल्स ए।

3
आपको ApplicationWillResignActive में इसे करने की आवश्यकता नहीं है क्योंकि स्क्रीनशॉट को ApplicationDidEnterBackground तक नहीं लिया गया है। जब आप होम बटन को डबल-टैप करते हैं, तो कोई स्क्रीन शॉट नहीं लिया जाता है; आप जो स्क्रीन देख रहे हैं वह लाइव है। सत्यापित करने के लिए अपनी स्क्रीन पर एक एनीमेशन जोड़ें, जैसे कि पृष्ठभूमि के रंग चक्र। यदि आप दूसरे ऐप को चुनते हैं, तो वास्तविक स्क्रीनशॉट लेने से पहले आपके एप्लिकेशनडीनएटरबेकग्राउंड को कॉल किया जाएगा।
19

3
BTW, मुझे एक Apple इंजीनियर द्वारा सूचित किया गया था कि दस्तावेज़ीकरण फिर ignoreSnapshotOnNextApplicationLaunchसे गलत है, जैसा कि हम सभी ने देखा है, एक स्नैपशॉट वास्तव में लिया गया है, लेकिन बस अगले लॉन्च में इसका उपयोग नहीं किया जाएगा।
रॉब

2
IgnSnapshotOnNextApplicationLaunch ऐसा लगता है कि ऐसा लगता है: एप्लिकेशन लॉन्च के दौरान स्क्रीनशॉट को प्रदर्शित होने से रोकें । यह मल्टीटास्किंग यूआई स्क्रीनशॉट को प्रभावित नहीं करता है, या यदि आपके एप्लिकेशन को लॉन्च किए जाने के बजाय फिर से शुरू किया जा रहा है।
ग्लेन मेनार्ड

32

यह वह समाधान है जो मैंने अपने आवेदन के लिए काम किया है:

जैसा कि टॉमी ने कहा: आप applicationWillResignActive का उपयोग कर सकते हैं। मैंने जो भी किया था वह अपने स्प्लैशशीम के साथ एक UIImageView बना रहा था और इसे मेरी मुख्य विंडो में सबव्यू के रूप में जोड़ रहा था-

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

उम्मीद है की यह मदद करेगा!

सिडेनोट: मैंने इसे सिम्युलेटर और एक वास्तविक डिवाइस दोनों पर परीक्षण किया: यह सिम्युलेटर पर शो नहीं होगा, लेकिन यह एक वास्तविक डिवाइस पर है!


2
एक खामी है: ApplicationWillResignActive को अन्य मामलों के बीच कहा जाता है, जब उपयोगकर्ता सूचना डॉक नीचे खींचता है। तो आप अपनी उंगली को ऊपर से नीचे की ओर खिसकाएं और उस छवि को देखें, जबकि आपको ऐप कंटेंट देखने की उम्मीद है।
किरिल गमाज़कोव

4
आवेदन पर संवेदनशील जानकारी को धुंधला करना बेहतर हैअभिलेखनीय और सेट पर छवि देखेंप्लीकेशनडीडइंटरबारैकग्राउंड
किरिल गमाज़कोव

यह काम करता है, लेकिन xcode6 के साथ निर्मित iOS7 में तैनात होने पर रोटेशन बग होता है: stackoverflow.com/questions/26147068/…
एलेक्स स्टोन

यदि मैं आपको applicationWillResignActive में उल्लिखित कोड लिखता हूं , तो जब मैं अपने ऐप को अग्रभूमि राज्य में वापस लाऊंगा तो मैं क्या देखूंगा? क्या मुझे "पोर्ट्रेट (768x1024) .png" छवि या वास्तविक स्क्रीन दिखाई देगी?
NSPratik

2
@Pratik: आप छवि को तब तक देखेंगे, जब तक कि आप इसे दोबारा नहीं हटाते हैं ApplicationDidBecomeActive मेथड (ऊपर देखें)।
लौरा

14

यह त्वरित और आसान तरीका 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];
    }
}

4

मैंने निम्नलिखित समाधान का उपयोग किया: जब एप्लिकेशन इस्तीफा देने जा रहा है तो मुझे एक दृश्य के रूप में ऐपवॉन्ड स्नैपशॉट मिलता है और इसमें धुंधला जोड़ देता है। फिर मैं इस दृश्य को ऐप विंडो में जोड़ता हूं

यह कैसे करना है:

  1. ऐप्पलगेट में लागू होने से ठीक पहले लाइन जोड़ें:

    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. अपना एपडेलगेट कार्यान्वयन इस प्रकार करें:

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

मैंने स्विफ्ट और ऑब्जेक्टिव सी में उदाहरण प्रोजेक्ट बनाए । दोनों परियोजनाएं निम्नलिखित कार्य करती हैं:

-संयोजन: didResignActive - स्नैपशॉट बनाया गया है, धुंधला हो गया है और ऐप विंडो में जोड़ा गया है

-संयोजन: willBecomeActive कलंक दृश्य खिड़की से हटाया जा रहा है।

कैसे इस्तेमाल करे:

ओब्जेक्टेकवे सी

  1. AppDelegate+NVSBlurAppScreenअपने प्रोजेक्ट में .h और .m फाइलें जोड़ें

  2. in -liclicWillResignActive: विधि निम्न पंक्ति जोड़ें:

    [self nvs_blurPresentedView];
  3. in -applicationDidEnterBackground: विधि निम्न पंक्ति जोड़ें:

    [self nvs_unblurPresentedView];

तीव्र

  1. अपने प्रोजेक्ट में AppDelegateExtention.swift फ़ाइल जोड़ें

  2. अपने आवेदन मेंWRRReactive फ़ंक्शन निम्न पंक्ति जोड़ें:

    blurPresentedView()
  3. अपने आवेदन मेंDecBecomeActive फ़ंक्शन निम्न पंक्ति जोड़ें:

    unblurPresentedView()

2

यदि केवल फ़ंक्शन [self.window addSubview:imageView];में उपयोग किया जाता applicationWillResignActiveहै, तो यह इमेज व्यू UIAlertView, UIActionSheet या MFMailComposeView कंटेंट ... को कवर नहीं करेगा

सबसे अच्छा समाधान है

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

एक वेबव्यू में फुलस्क्रीन-मोड में वीडियो प्ले करने पर बहुत अच्छा समाधान!
टॉमी

अति उत्कृष्ट!। मल्टीटास्किंग स्विचर में आने से पहले हमारे पास कीपैड खुला होने पर भी यह काम करता है! धन्यवाद
Prabhu.Somasundaram

0

अपने स्वयं के समाधान को "उत्तर" के रूप में प्रदान करना, हालांकि यह समाधान बहुत अविश्वसनीय है। कभी-कभी मुझे स्क्रीनशॉट के रूप में एक काली स्क्रीन मिलती है, कभी-कभी XIB और कभी-कभी ऐप से ही स्क्रीनशॉट। डिवाइस पर निर्भर करता है और / या अगर मैं सिम्युलेटर में इसे चलाता हूं।

कृपया ध्यान दें कि मैं इस समाधान के लिए कोई कोड प्रदान नहीं कर सकता, क्योंकि इसमें बहुत सारे ऐप-विशिष्ट विवरण हैं। लेकिन यह मेरे समाधान के बुनियादी सार की व्याख्या करना चाहिए।

अगर हम iOS7 चला रहे हैं, तो AppDelegate.m में ApplicationWillResignActive I चेक के तहत, अगर हम करते हैं तो मैं एक नया दृश्य लोड करता हूं जो बीच में ऐप-लोगो के साथ खाली है। एक बार ApplicationDidBecomeActive कहा जाता है मैं अपने पुराने विचारों को फिर से लॉन्च करता हूं, जिसे रीसेट किया जाएगा - लेकिन यह उस एप्लिकेशन के प्रकार के लिए काम करता है जो मैं विकसित कर रहा हूं।


1
यदि आप देखते हैं कि कैमरा ऐप क्या करता है - यह पृष्ठभूमि में जाने पर छवि को धुंधले में परिवर्तित कर देता है (आप आइकन पर कम होने के साथ संक्रमण को देख सकते हैं)
पेटेश

@Petesh हाँ, यह एक अच्छा कार्यान्वयन है, लेकिन सवाल यह है कि वे इसे कैसे करते हैं। मुझे एक निजी एपीआई से डर लगता है।
रोब

@ टॉमी आप कहते हैं "डिवाइस पर निर्भर करता है और / या अगर मैं सिम्युलेटर में इसे चलाता हूं"। मेरे लिए, यह डिवाइस पर काम करने के लिए प्रकट होता है (हालांकि मैंने थकावट का परीक्षण नहीं किया है), लेकिन सिम्युलेटर नहीं। क्या आप पा रहे हैं कि यह डिवाइस पर काम नहीं करता है?
रोब

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();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.