From a7aea66479ce5fe29bc0e7ebb205f2c3285068eb Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Thu, 23 Feb 2017 17:13:03 +0000 Subject: [PATCH 01/24] =?UTF-8?q?(iOS)=20added=20option=20=E2=80=9CPrivacy?= =?UTF-8?q?OnBackground=E2=80=9D=20to=20activate=20privacy=20only=20in=20b?= =?UTF-8?q?ackground=20mode=20as=20activating=20in=20resign=20activates=20?= =?UTF-8?q?privacy=20in=20cases=20where=20it=20may=20not=20be=20required?= =?UTF-8?q?=20(i.e.=20touch=20ID=20prompt).\n=20(iOS)=20added=20option=20?= =?UTF-8?q?=E2=80=9CPrivacyOverrideLaunchImage=E2=80=9D=20to=20be=20able?= =?UTF-8?q?=20to=20use=20images=20that=20are=20different=20from=20the=20la?= =?UTF-8?q?unch=20screen=20even=20when=20this=20exists.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ios/PrivacyScreenPlugin.m | 241 ++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 115 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 67303ee..366d992 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -12,144 +12,155 @@ @implementation PrivacyScreenPlugin - (void)pluginInitialize { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) + name:UIApplicationDidBecomeActiveNotification object:nil]; + NSString* onBackgroundKey = @"privacyonbackground"; + + if([self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] && [[self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] isEqualToString:@"true"]) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; + else + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationWillResignActiveNotification object:nil]; } - (void)onAppDidBecomeActive:(UIApplication *)application { - if (imageView == NULL) { - self.viewController.view.window.hidden = NO; - } else { - [imageView removeFromSuperview]; - } + if (imageView == NULL) { + self.viewController.view.window.hidden = NO; + } else { + [imageView removeFromSuperview]; + } } - (void)onAppWillResignActive:(UIApplication *)application { - CDVViewController *vc = (CDVViewController*)self.viewController; - NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; - UIImage *splash = [UIImage imageNamed:imgName]; - if (splash == NULL) { - imageView = NULL; - self.viewController.view.window.hidden = YES; - } else { - imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; - [imageView setImage:splash]; - - #ifdef __CORDOVA_4_0_0 + CDVViewController *vc = (CDVViewController*)self.viewController; + NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; + UIImage *splash = [UIImage imageNamed:imgName]; + if (splash == NULL) { + imageView = NULL; + self.viewController.view.window.hidden = YES; + } else { + imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; + [imageView setImage:splash]; + +#ifdef __CORDOVA_4_0_0 [[UIApplication sharedApplication].keyWindow addSubview:imageView]; - #else +#else [self.viewController.view addSubview:imageView]; - #endif - } +#endif + } } // Code below borrowed from the CDV splashscreen plugin @ https://github.com/apache/cordova-plugin-splashscreen // Made some adjustments though, becuase landscape splashscreens are not available for iphone < 6 plus - (CDV_iOSDevice) getCurrentDevice { - CDV_iOSDevice device; - - UIScreen* mainScreen = [UIScreen mainScreen]; - CGFloat mainScreenHeight = mainScreen.bounds.size.height; - CGFloat mainScreenWidth = mainScreen.bounds.size.width; - - int limit = MAX(mainScreenHeight,mainScreenWidth); - - device.iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); - device.iPhone = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone); - device.retina = ([mainScreen scale] == 2.0); - device.iPhone4 = (device.iPhone && limit == 480.0); - device.iPhone5 = (device.iPhone && limit == 568.0); - // note these below is not a true device detect, for example if you are on an - // iPhone 6/6+ but the app is scaled it will prob set iPhone5 as true, but - // this is appropriate for detecting the runtime screen environment - device.iPhone6 = (device.iPhone && limit == 667.0); - device.iPhone6Plus = (device.iPhone && limit == 736.0); - - return device; + CDV_iOSDevice device; + + UIScreen* mainScreen = [UIScreen mainScreen]; + CGFloat mainScreenHeight = mainScreen.bounds.size.height; + CGFloat mainScreenWidth = mainScreen.bounds.size.width; + + int limit = MAX(mainScreenHeight,mainScreenWidth); + + device.iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); + device.iPhone = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone); + device.retina = ([mainScreen scale] == 2.0); + device.iPhone4 = (device.iPhone && limit == 480.0); + device.iPhone5 = (device.iPhone && limit == 568.0); + // note these below is not a true device detect, for example if you are on an + // iPhone 6/6+ but the app is scaled it will prob set iPhone5 as true, but + // this is appropriate for detecting the runtime screen environment + device.iPhone6 = (device.iPhone && limit == 667.0); + device.iPhone6Plus = (device.iPhone && limit == 736.0); + + return device; } - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(id)orientationDelegate device:(CDV_iOSDevice)device { - // Use UILaunchImageFile if specified in plist. Otherwise, use Default. - NSString* imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; - - NSUInteger supportedOrientations = [orientationDelegate supportedInterfaceOrientations]; - - // Checks to see if the developer has locked the orientation to use only one of Portrait or Landscape - BOOL supportsLandscape = (supportedOrientations & UIInterfaceOrientationMaskLandscape); - BOOL supportsPortrait = (supportedOrientations & UIInterfaceOrientationMaskPortrait || supportedOrientations & UIInterfaceOrientationMaskPortraitUpsideDown); - // this means there are no mixed orientations in there - BOOL isOrientationLocked = !(supportsPortrait && supportsLandscape); - - if (imageName) { - imageName = [imageName stringByDeletingPathExtension]; - } else { - imageName = @"Default"; - } - - // Add Asset Catalog specific prefixes - if ([imageName isEqualToString:@"LaunchImage"]) - { - if(device.iPhone4 || device.iPhone5 || device.iPad) { - imageName = [imageName stringByAppendingString:@"-700"]; - } else if(device.iPhone6) { - imageName = [imageName stringByAppendingString:@"-800"]; - } else if(device.iPhone6Plus) { - imageName = [imageName stringByAppendingString:@"-800"]; - if (currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { - imageName = [imageName stringByAppendingString:@"-Portrait"]; - } + NSString* imageName = @"Default"; + //Override Launch images? + NSString* privacyOverrideLaunchImage = @"privacyoverridelaunchimage"; + if([self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] && [[self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] isEqualToString:@"true"]) + { + } - } - - BOOL isLandscape = supportsLandscape && - (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight); - - if (device.iPhone5) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-568h"]; - } else if (device.iPhone6) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-667h"]; - } else if (device.iPhone6Plus) { // supports landscape - if (isOrientationLocked) { - imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"")]; - } else { - switch (currentOrientation) { - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; - default: - break; - } + else + { + // Use UILaunchImageFile if specified in plist. Otherwise, use Default. + imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; + imageName = [imageName stringByDeletingPathExtension]; } - imageName = [imageName stringByAppendingString:@"-736h"]; - } else if (device.iPad) { // supports landscape - if (isOrientationLocked) { - imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"-Portrait")]; - } else { - switch (currentOrientation) { - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; - - case UIInterfaceOrientationPortrait: - case UIInterfaceOrientationPortraitUpsideDown: - default: - imageName = [imageName stringByAppendingString:@"-Portrait"]; - break; - } + NSUInteger supportedOrientations = [orientationDelegate supportedInterfaceOrientations]; + + // Checks to see if the developer has locked the orientation to use only one of Portrait or Landscape + BOOL supportsLandscape = (supportedOrientations & UIInterfaceOrientationMaskLandscape); + BOOL supportsPortrait = (supportedOrientations & UIInterfaceOrientationMaskPortrait || supportedOrientations & UIInterfaceOrientationMaskPortraitUpsideDown); + // this means there are no mixed orientations in there + BOOL isOrientationLocked = !(supportsPortrait && supportsLandscape); + + + // Add Asset Catalog specific prefixes + if ([imageName isEqualToString:@"LaunchImage"]) + { + if(device.iPhone4 || device.iPhone5 || device.iPad) { + imageName = [imageName stringByAppendingString:@"-700"]; + } else if(device.iPhone6) { + imageName = [imageName stringByAppendingString:@"-800"]; + } else if(device.iPhone6Plus) { + imageName = [imageName stringByAppendingString:@"-800"]; + if (currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { + imageName = [imageName stringByAppendingString:@"-Portrait"]; + } + } } - } - - return imageName; + + BOOL isLandscape = supportsLandscape && + (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight); + + if (device.iPhone5) { // does not support landscape + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-568h"]; + } else if (device.iPhone6) { // does not support landscape + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-667h"]; + } else if (device.iPhone6Plus) { // supports landscape + if (isOrientationLocked) { + imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"")]; + } else { + switch (currentOrientation) { + case UIInterfaceOrientationLandscapeLeft: + case UIInterfaceOrientationLandscapeRight: + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; + default: + break; + } + } + imageName = [imageName stringByAppendingString:@"-736h"]; + + } else if (device.iPad) { // supports landscape + if (isOrientationLocked) { + imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"-Portrait")]; + } else { + switch (currentOrientation) { + case UIInterfaceOrientationLandscapeLeft: + case UIInterfaceOrientationLandscapeRight: + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; + + case UIInterfaceOrientationPortrait: + case UIInterfaceOrientationPortraitUpsideDown: + default: + imageName = [imageName stringByAppendingString:@"-Portrait"]; + break; + } + } + } + + return imageName; } -@end \ No newline at end of file +@end From f726af18a56291379a35633273bf00b48f499d78 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Thu, 23 Feb 2017 17:51:45 +0000 Subject: [PATCH 02/24] Changed version number to 0.3.2. --- package.json | 2 +- plugin.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e4f1ced..212642e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.3.1", + "version": "0.3.2", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 99d0576..b17e4e6 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. From 5e0095a321fb3fc9fbe9ef789c5b28a96ea3bcf9 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 24 Feb 2017 11:54:57 +0000 Subject: [PATCH 03/24] Updated Readme.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1631370..1d79d08 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ Usage: This plugin exposes no interface, it simply sets your app to be private. You don't need to do anything except install the plugin. +For iOS there are 2 preferences that can be set in config.xml: +- "PrivacyOnBackground": If set to "true" allows splashscreen to be shown only when app enters background (i.e. switched to another app or pressed the home button) +- "PrivacyOverrideLaunchImage": If set to "true" allows privacy screen to be the Default image even if LaunchImage is set in the info-plist + Test this plugin on a real device because the iOS simulator (7.1 at least) does a poor job hiding your app. ## License From 1572f8054b93a05713b304c192535b8e685e9a0d Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 1 Mar 2017 11:22:05 +0000 Subject: [PATCH 04/24] =?UTF-8?q?Added=20fix=20for=20issue=20with=20some?= =?UTF-8?q?=20app=20generators=20that=20can=E2=80=99t=20use=20=E2=80=98-?= =?UTF-8?q?=E2=80=99=20in=20resource=20names.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ios/PrivacyScreenPlugin.m | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 366d992..6a32816 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -39,8 +39,16 @@ - (void)onAppWillResignActive:(UIApplication *)application NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; UIImage *splash = [UIImage imageNamed:imgName]; if (splash == NULL) { - imageView = NULL; - self.viewController.view.window.hidden = YES; + + //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) + imgName = [imgName stringByReplacingOccurrencesOfString:@"-" withString:@""]; + + UIImage *splash = [UIImage imageNamed:imgName]; + //If still null image doesn't really exist. + if (splash == NULL) { + imageView = NULL; + self.viewController.view.window.hidden = YES; + } } else { imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; [imageView setImage:splash]; From 50be9f9936ee57c34e9b878d6a560cf346bd8a37 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 1 Mar 2017 11:31:21 +0000 Subject: [PATCH 05/24] Changed to version 0.3.3 --- plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.xml b/plugin.xml index b17e4e6..8ae0543 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. From ebf8a8c09e63b514cac9fd1b5e23df871ea65f24 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 1 Mar 2017 11:40:48 +0000 Subject: [PATCH 06/24] Fixed bad logic after testing. --- src/ios/PrivacyScreenPlugin.m | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 6a32816..b095f7c 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -38,18 +38,23 @@ - (void)onAppWillResignActive:(UIApplication *)application CDVViewController *vc = (CDVViewController*)self.viewController; NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; UIImage *splash = [UIImage imageNamed:imgName]; - if (splash == NULL) { + if (splash == NULL) + { //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) imgName = [imgName stringByReplacingOccurrencesOfString:@"-" withString:@""]; - UIImage *splash = [UIImage imageNamed:imgName]; + splash = [UIImage imageNamed:imgName]; //If still null image doesn't really exist. if (splash == NULL) { imageView = NULL; self.viewController.view.window.hidden = YES; } - } else { + } + + //If splash image ended up being initialized + if(splash) + { imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; [imageView setImage:splash]; From fcba592ca1ab51875dcda3b862af7c54aab12c47 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 1 Mar 2017 15:34:26 +0000 Subject: [PATCH 07/24] =?UTF-8?q?Added=20=E2=80=9CPrivacyImageName?= =?UTF-8?q?=E2=80=9D=20preference=20for=20custom=20image=20names=20in=20bu?= =?UTF-8?q?ndle.\n=20changed=20version=20to=200.3.4.\n=20Updated=20README.?= =?UTF-8?q?md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- plugin.xml | 2 +- src/ios/PrivacyScreenPlugin.m | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1d79d08..43b3b99 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,10 @@ Usage: This plugin exposes no interface, it simply sets your app to be private. You don't need to do anything except install the plugin. -For iOS there are 2 preferences that can be set in config.xml: +For iOS there are 3 preferences that can be set in config.xml: - "PrivacyOnBackground": If set to "true" allows splashscreen to be shown only when app enters background (i.e. switched to another app or pressed the home button) - "PrivacyOverrideLaunchImage": If set to "true" allows privacy screen to be the Default image even if LaunchImage is set in the info-plist +- "PrivacyImageName": String for image name, images should be in the app bundle and follow the size naming convention (i.e. for app name "Test", there should be a "Test-667h.png" in the bundle for iPhone 6) Test this plugin on a real device because the iOS simulator (7.1 at least) does a poor job hiding your app. diff --git a/plugin.xml b/plugin.xml index 8ae0543..5d748d5 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index b095f7c..c7c3b73 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -94,7 +94,9 @@ - (CDV_iOSDevice) getCurrentDevice - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(id)orientationDelegate device:(CDV_iOSDevice)device { - NSString* imageName = @"Default"; + NSString* privacyImageNameKey = @"privacyimagename"; + NSString* prefImageName = [self.commandDelegate.settings objectForKey:[privacyImageNameKey lowercaseString]]; + NSString* imageName = prefImageName ? prefImageName : @"Default"; //Override Launch images? NSString* privacyOverrideLaunchImage = @"privacyoverridelaunchimage"; if([self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] && [[self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] isEqualToString:@"true"]) From 74884d57d95ba180ffcfefe8b869aa11ae18a5c0 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 3 Mar 2017 18:22:07 +0000 Subject: [PATCH 08/24] Added option for www path image. Version 0.3.5 --- plugin.xml | 2 +- src/ios/PrivacyScreenPlugin.m | 49 ++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/plugin.xml b/plugin.xml index 5d748d5..36da721 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index c7c3b73..a1903f7 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -37,23 +37,13 @@ - (void)onAppWillResignActive:(UIApplication *)application { CDVViewController *vc = (CDVViewController*)self.viewController; NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; - UIImage *splash = [UIImage imageNamed:imgName]; + UIImage* splash = [self getImageFromName:imgName]; if (splash == NULL) { - - //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) - imgName = [imgName stringByReplacingOccurrencesOfString:@"-" withString:@""]; - - splash = [UIImage imageNamed:imgName]; - //If still null image doesn't really exist. - if (splash == NULL) { - imageView = NULL; - self.viewController.view.window.hidden = YES; - } + imageView = NULL; + self.viewController.view.window.hidden = YES; } - - //If splash image ended up being initialized - if(splash) + else { imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; [imageView setImage:splash]; @@ -174,8 +164,37 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i } } } - +// if(imageName) +// { +// imageName = [imageName stringByAppendingString:@".png"]; +// } return imageName; } +- (UIImage*) getImageFromName:(NSString*) imageName +{ + UIImage *image = [UIImage imageNamed:imageName]; + if (image == NULL) + { + //If not in bundle try to go to resources path + NSString* imagePath = [imageName stringByAppendingString:@".png"]; + image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:imagePath]]; + if(image) + return image; + + //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) + imageName = [imageName stringByReplacingOccurrencesOfString:@"-" withString:@""]; + image = [UIImage imageNamed:imageName]; + if(image == NULL) + { + imagePath = [imageName stringByAppendingString:@".png"]; + image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:imagePath]]; + //If still null image doesn't really exist. + } + } + + + return image; +} + @end From 5864939ed606c91d41d99650bbc7f3ad417b995e Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 24 Mar 2017 12:38:51 +0000 Subject: [PATCH 09/24] Changed to version 0.3.6 \n Changed plugin lifecycle. --- package.json | 2 +- plugin.xml | 7 +- src/android/PrivacyScreenPlugin.java | 18 ++++++ src/ios/PrivacyScreenPlugin.h | 6 +- src/ios/PrivacyScreenPlugin.m | 97 ++++++++++++++++++++++++++-- www/PrivacyScreenPlugin.js | 34 ++++++++-- 6 files changed, 150 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 212642e..751e654 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.3.2", + "version": "0.3.6", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 36da721..36287bd 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,9 +1,14 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. MIT + + + + + diff --git a/src/android/PrivacyScreenPlugin.java b/src/android/PrivacyScreenPlugin.java index 691f5a6..310987a 100644 --- a/src/android/PrivacyScreenPlugin.java +++ b/src/android/PrivacyScreenPlugin.java @@ -34,4 +34,22 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) { Activity activity = this.cordova.getActivity(); activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); } + //Not used in Android + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + if ("setTimer".equals(action)) { + callbackContext.success(); + return true; + } + else if ("hidePrivacyScreen".equals(action)) { + callbackContext.success(); + return true; + } + else if ("showPrivacyScreen".equals(action)) { + callbackContext.success(); + return true; + } + + return false; // Returning false results in a "MethodNotFound" error. + } } diff --git a/src/ios/PrivacyScreenPlugin.h b/src/ios/PrivacyScreenPlugin.h index 6ce5c3a..cfe049b 100644 --- a/src/ios/PrivacyScreenPlugin.h +++ b/src/ios/PrivacyScreenPlugin.h @@ -20,4 +20,8 @@ typedef struct { @interface PrivacyScreenPlugin : CDVPlugin -@end \ No newline at end of file +- (void) setTimer:(CDVInvokedUrlCommand*)command; +- (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command; +- (void) showPrivacyScreen:(CDVInvokedUrlCommand*)command; + +@end diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index a1903f7..13b7d72 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -6,14 +6,28 @@ */ #import "PrivacyScreenPlugin.h" +#define PRIVACY_TIMER_DEFAULT 2.0f; + static UIImageView *imageView; +@interface PrivacyScreenPlugin () + +@property (strong, nonatomic) NSTimer* privacyTimer; +@property (nonatomic) float privacyTimerInterval; +@end + + @implementation PrivacyScreenPlugin +#pragma mark - Initialize - (void)pluginInitialize { + self.privacyTimerInterval = PRIVACY_TIMER_DEFAULT; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) + name:CDVPageDidLoadNotification object:nil]; + NSString* onBackgroundKey = @"privacyonbackground"; if([self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] && [[self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] isEqualToString:@"true"]) @@ -24,16 +38,90 @@ - (void)pluginInitialize name:UIApplicationWillResignActiveNotification object:nil]; } +#pragma mark - Explicit Commands +- (void) setTimer:(CDVInvokedUrlCommand*)command +{ + if(command.arguments.count > 0) + { + if(!command.arguments[0] || command.arguments[0] == [NSNull null]) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"Timer argument is null"]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + return; + } + //timeInterval argument + self.privacyTimerInterval = [command.arguments[0] floatValue]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } + else + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"No arguments provided"]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } +} + +- (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command +{ + [self removePrivacyScreen]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +- (void) showPrivacyScreen:(CDVInvokedUrlCommand*)command +{ + [self applyPrivacyScreen]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +#pragma mark - Triggered functions +- (void) onPageDidLoad +{ + [self removePrivacyScreen]; +} + - (void)onAppDidBecomeActive:(UIApplication *)application { - if (imageView == NULL) { + if(!self.privacyTimer) + self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval + target:self + selector:@selector(removePrivacyScreen) + userInfo:nil + repeats:NO]; +} + +- (void)onAppWillResignActive:(UIApplication *)application +{ + [self applyPrivacyScreen]; +} + +#pragma mark - Helper functions +-(void) removePrivacyScreen +{ + if (imageView == NULL) + { self.viewController.view.window.hidden = NO; - } else { - [imageView removeFromSuperview]; + } + else + { + [UIView animateWithDuration:0.1f + animations:^{ + imageView.alpha = 0.0f; + } + completion:^(BOOL finished) { + [imageView removeFromSuperview]; + }]; + } + + if(self.privacyTimer) + { + [self.privacyTimer invalidate]; + self.privacyTimer = nil; } } -- (void)onAppWillResignActive:(UIApplication *)application +-(void) applyPrivacyScreen { CDVViewController *vc = (CDVViewController*)self.viewController; NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; @@ -54,6 +142,7 @@ - (void)onAppWillResignActive:(UIApplication *)application [self.viewController.view addSubview:imageView]; #endif } + } // Code below borrowed from the CDV splashscreen plugin @ https://github.com/apache/cordova-plugin-splashscreen diff --git a/www/PrivacyScreenPlugin.js b/www/PrivacyScreenPlugin.js index ae80e7d..312012e 100644 --- a/www/PrivacyScreenPlugin.js +++ b/www/PrivacyScreenPlugin.js @@ -1,8 +1,28 @@ -//var exec = require('cordova/exec'); +cordova.define("cordova-plugin-privacy-screen.PrivacyScreen", function(require, exports, module) { -/** - * Not sure this will even have a JS API - */ -//exports.activate = function(arg, success, error) { - //exec(success, error, "PrivacyScreenPlugin", "activate", [arg]); -//}; +function PrivacyScreen() {} + +//Default time to remove privacy screen is 2 seconds (+0.1s for fade animation) +PrivacyScreen.prototype.setTimer = function(successCallback, errorCallback, timeInterval) { + cordova.exec(successCallback, errorCallback, "PrivacyScreenPlugin", "setTimer", [timeInterval]); +}; + +PrivacyScreen.prototype.hidePrivacyScreen = function(successCallback, errorCallback) { + cordova.exec(successCallback, errorCallback, "PrivacyScreenPlugin", "hidePrivacyScreen", []); +}; + +PrivacyScreen.prototype.showPrivacyScreen = function(successCallback, errorCallback) { + cordova.exec(successCallback, errorCallback, "PrivacyScreenPlugin", "showPrivacyScreen", []); +}; + +PrivacyScreen.install = function() { + if (!window.plugins) { + window.plugins = {}; + } + + window.plugins.privacyscreen = new PrivacyScreen(); + return window.plugins.privacyscreen; +}; + +cordova.addConstructor(PrivacyScreen.install); +}); \ No newline at end of file From 9ac9c96c492b96e368fe785f7edf25d80209a29b Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 24 Mar 2017 12:48:09 +0000 Subject: [PATCH 10/24] js fix --- www/PrivacyScreenPlugin.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/www/PrivacyScreenPlugin.js b/www/PrivacyScreenPlugin.js index 312012e..1c13da7 100644 --- a/www/PrivacyScreenPlugin.js +++ b/www/PrivacyScreenPlugin.js @@ -1,5 +1,3 @@ -cordova.define("cordova-plugin-privacy-screen.PrivacyScreen", function(require, exports, module) { - function PrivacyScreen() {} //Default time to remove privacy screen is 2 seconds (+0.1s for fade animation) @@ -24,5 +22,4 @@ PrivacyScreen.install = function() { return window.plugins.privacyscreen; }; -cordova.addConstructor(PrivacyScreen.install); -}); \ No newline at end of file +cordova.addConstructor(PrivacyScreen.install); \ No newline at end of file From 417aad33cc8c8f0a4789e3f51e5e980802ce68b1 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 24 Mar 2017 12:54:13 +0000 Subject: [PATCH 11/24] timer fix --- src/ios/PrivacyScreenPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 13b7d72..97b738b 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -6,7 +6,7 @@ */ #import "PrivacyScreenPlugin.h" -#define PRIVACY_TIMER_DEFAULT 2.0f; +#define PRIVACY_TIMER_DEFAULT 5.0f; static UIImageView *imageView; From cdf05a9f3c40d03bff9e6d810d970c308efcbf3f Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Mon, 27 Mar 2017 11:37:11 +0100 Subject: [PATCH 12/24] Changed to version 0.3.7\n Fixed bug with responding to wrong function on page load.\n Added timer preference.\n Show Privacy screen hides after timer. --- README.md | 8 +++++- package.json | 2 +- plugin.xml | 2 +- src/ios/PrivacyScreenPlugin.m | 53 +++++++++++++++++++++-------------- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 43b3b99..296953d 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,18 @@ For Cordova 3.x.x: Usage: ------ -This plugin exposes no interface, it simply sets your app to be private. You don't need to do anything except install the plugin. +This plugin exposes no interface in Android, it simply sets your app to be private. You don't need to do anything except install the plugin. + +In iOS the privacy screen fades on page load or in a set time interval, if you want more control you have the following functions: +- setTimer(successCallback, errorCallback, timeInterval) : sets timer to make privacy screen fade away (default is 3 seconds and can be set through preference). +- hidePrivacyScreen(successCallback, errorCallback) : Explicitely hides the privacy screen. +- showPrivacyScreen(successCallback, errorCallback) : Explicitely shows the privacy screen (respects timer interval to fade) For iOS there are 3 preferences that can be set in config.xml: - "PrivacyOnBackground": If set to "true" allows splashscreen to be shown only when app enters background (i.e. switched to another app or pressed the home button) - "PrivacyOverrideLaunchImage": If set to "true" allows privacy screen to be the Default image even if LaunchImage is set in the info-plist - "PrivacyImageName": String for image name, images should be in the app bundle and follow the size naming convention (i.e. for app name "Test", there should be a "Test-667h.png" in the bundle for iPhone 6) +- "PrivacyTimer": accepts a value in seconds for the privacy screen timer Test this plugin on a real device because the iOS simulator (7.1 at least) does a poor job hiding your app. diff --git a/package.json b/package.json index 751e654..28f72a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.3.6", + "version": "0.3.7", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 36287bd..3147df1 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 97b738b..806ddbf 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -6,7 +6,7 @@ */ #import "PrivacyScreenPlugin.h" -#define PRIVACY_TIMER_DEFAULT 5.0f; +#define PRIVACY_TIMER_DEFAULT 3.0f; static UIImageView *imageView; @@ -22,20 +22,24 @@ @implementation PrivacyScreenPlugin #pragma mark - Initialize - (void)pluginInitialize { - self.privacyTimerInterval = PRIVACY_TIMER_DEFAULT; + NSString* privacyTimerKey = @"privacytimer"; + NSString* prefTimer = [self.commandDelegate.settings objectForKey:[privacyTimerKey lowercaseString]];\ + if(prefTimer) + self.privacyTimerInterval = [prefTimer floatValue] > 0.0f ? [prefTimer floatValue] : PRIVACY_TIMER_DEFAULT; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPageDidLoad) name:CDVPageDidLoadNotification object:nil]; NSString* onBackgroundKey = @"privacyonbackground"; if([self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] && [[self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] isEqualToString:@"true"]) - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; else - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationWillResignActiveNotification object:nil]; } #pragma mark - Explicit Commands @@ -63,7 +67,7 @@ - (void) setTimer:(CDVInvokedUrlCommand*)command - (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command { - [self removePrivacyScreen]; + [self removePrivacyScreen]; CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @@ -71,6 +75,12 @@ - (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command - (void) showPrivacyScreen:(CDVInvokedUrlCommand*)command { [self applyPrivacyScreen]; + [self.privacyTimer invalidate]; + self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval + target:self + selector:@selector(removePrivacyScreen) + userInfo:nil + repeats:NO]; CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @@ -83,6 +93,7 @@ - (void) onPageDidLoad - (void)onAppDidBecomeActive:(UIApplication *)application { + //[self.privacyTimer invalidate]; if(!self.privacyTimer) self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval target:self @@ -227,10 +238,10 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i switch (currentOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; default: - break; + break; } } imageName = [imageName stringByAppendingString:@"-736h"]; @@ -242,21 +253,21 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i switch (currentOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; - + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; + case UIInterfaceOrientationPortrait: case UIInterfaceOrientationPortraitUpsideDown: default: - imageName = [imageName stringByAppendingString:@"-Portrait"]; - break; + imageName = [imageName stringByAppendingString:@"-Portrait"]; + break; } } } -// if(imageName) -// { -// imageName = [imageName stringByAppendingString:@".png"]; -// } + // if(imageName) + // { + // imageName = [imageName stringByAppendingString:@".png"]; + // } return imageName; } @@ -269,7 +280,7 @@ - (UIImage*) getImageFromName:(NSString*) imageName NSString* imagePath = [imageName stringByAppendingString:@".png"]; image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:imagePath]]; if(image) - return image; + return image; //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) imageName = [imageName stringByReplacingOccurrencesOfString:@"-" withString:@""]; From 20c451b0d4a1583fe4fac8ea8e511c840b6ec128 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Mon, 27 Mar 2017 14:20:21 +0100 Subject: [PATCH 13/24] Default timer fix --- src/ios/PrivacyScreenPlugin.m | 45 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 806ddbf..4fd83a3 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -23,9 +23,12 @@ @implementation PrivacyScreenPlugin - (void)pluginInitialize { NSString* privacyTimerKey = @"privacytimer"; - NSString* prefTimer = [self.commandDelegate.settings objectForKey:[privacyTimerKey lowercaseString]];\ + NSString* prefTimer = [self.commandDelegate.settings objectForKey:[privacyTimerKey lowercaseString]]; + //Default value + self.privacyTimerInterval = PRIVACY_TIMER_DEFAULT; if(prefTimer) - self.privacyTimerInterval = [prefTimer floatValue] > 0.0f ? [prefTimer floatValue] : PRIVACY_TIMER_DEFAULT; + self.privacyTimerInterval = [prefTimer floatValue] > 0.0f ? [prefTimer floatValue] : PRIVACY_TIMER_DEFAULT; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; @@ -35,11 +38,11 @@ - (void)pluginInitialize NSString* onBackgroundKey = @"privacyonbackground"; if([self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] && [[self.commandDelegate.settings objectForKey:[onBackgroundKey lowercaseString]] isEqualToString:@"true"]) - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; else - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) + name:UIApplicationWillResignActiveNotification object:nil]; } #pragma mark - Explicit Commands @@ -67,7 +70,7 @@ - (void) setTimer:(CDVInvokedUrlCommand*)command - (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command { - [self removePrivacyScreen]; + [self removePrivacyScreen]; CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @@ -95,7 +98,7 @@ - (void)onAppDidBecomeActive:(UIApplication *)application { //[self.privacyTimer invalidate]; if(!self.privacyTimer) - self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval + self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval target:self selector:@selector(removePrivacyScreen) userInfo:nil @@ -238,10 +241,10 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i switch (currentOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; default: - break; + break; } } imageName = [imageName stringByAppendingString:@"-736h"]; @@ -253,21 +256,21 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i switch (currentOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; - break; - + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; + case UIInterfaceOrientationPortrait: case UIInterfaceOrientationPortraitUpsideDown: default: - imageName = [imageName stringByAppendingString:@"-Portrait"]; - break; + imageName = [imageName stringByAppendingString:@"-Portrait"]; + break; } } } - // if(imageName) - // { - // imageName = [imageName stringByAppendingString:@".png"]; - // } +// if(imageName) +// { +// imageName = [imageName stringByAppendingString:@".png"]; +// } return imageName; } @@ -280,7 +283,7 @@ - (UIImage*) getImageFromName:(NSString*) imageName NSString* imagePath = [imageName stringByAppendingString:@".png"]; image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:imagePath]]; if(image) - return image; + return image; //try to take out hyfens and see if that works (Compatbility with Outsystems mobile issue) imageName = [imageName stringByReplacingOccurrencesOfString:@"-" withString:@""]; From 195a89a91217f764b63a4224f5e194a340079377 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 4 Aug 2017 10:58:48 +0100 Subject: [PATCH 14/24] Fix for preview image being stuck after leaving app rapidly on splash. --- src/ios/PrivacyScreenPlugin.m | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 4fd83a3..8f3344b 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -97,7 +97,7 @@ - (void) onPageDidLoad - (void)onAppDidBecomeActive:(UIApplication *)application { //[self.privacyTimer invalidate]; - if(!self.privacyTimer) + if(!self.privacyTimer || !self.privacyTimer.valid) self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval target:self selector:@selector(removePrivacyScreen) @@ -113,11 +113,9 @@ - (void)onAppWillResignActive:(UIApplication *)application #pragma mark - Helper functions -(void) removePrivacyScreen { - if (imageView == NULL) - { - self.viewController.view.window.hidden = NO; - } - else + self.viewController.view.window.hidden = NO; + + if (imageView != NULL) { [UIView animateWithDuration:0.1f animations:^{ @@ -128,7 +126,7 @@ -(void) removePrivacyScreen }]; } - if(self.privacyTimer) + if(self.privacyTimer || self.privacyTimer.valid) { [self.privacyTimer invalidate]; self.privacyTimer = nil; From d61c5d92b6c1b151afbe85d3fbd1aa02507c1344 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 4 Aug 2017 12:00:17 +0100 Subject: [PATCH 15/24] Additional fix --- src/ios/PrivacyScreenPlugin.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 8f3344b..097a393 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -96,9 +96,9 @@ - (void) onPageDidLoad - (void)onAppDidBecomeActive:(UIApplication *)application { - //[self.privacyTimer invalidate]; - if(!self.privacyTimer || !self.privacyTimer.valid) - self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval + [self.privacyTimer invalidate]; + //if(!self.privacyTimer || !self.privacyTimer.valid) + self.privacyTimer = [NSTimer scheduledTimerWithTimeInterval:self.privacyTimerInterval target:self selector:@selector(removePrivacyScreen) userInfo:nil @@ -126,11 +126,11 @@ -(void) removePrivacyScreen }]; } - if(self.privacyTimer || self.privacyTimer.valid) - { - [self.privacyTimer invalidate]; - self.privacyTimer = nil; - } +// if(self.privacyTimer || self.privacyTimer.valid) +// { + [self.privacyTimer invalidate]; + self.privacyTimer = nil; +// } } -(void) applyPrivacyScreen From ddfb6d2607de8702fe00443daab2f72a0e3b5912 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Mon, 4 Sep 2017 14:08:30 +0100 Subject: [PATCH 16/24] Fix for Privacy screen getting iOs app stuck on iOS 8+ devices. --- src/ios/PrivacyScreenPlugin.m | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 097a393..e5d4d0f 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -113,10 +113,11 @@ - (void)onAppWillResignActive:(UIApplication *)application #pragma mark - Helper functions -(void) removePrivacyScreen { - self.viewController.view.window.hidden = NO; - - if (imageView != NULL) + if(imageView) { + self.viewController.view.window.hidden = NO; + + [UIView animateWithDuration:0.1f animations:^{ imageView.alpha = 0.0f; @@ -124,6 +125,7 @@ -(void) removePrivacyScreen completion:^(BOOL finished) { [imageView removeFromSuperview]; }]; + } // if(self.privacyTimer || self.privacyTimer.valid) @@ -136,15 +138,18 @@ -(void) removePrivacyScreen -(void) applyPrivacyScreen { CDVViewController *vc = (CDVViewController*)self.viewController; - NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id)vc device:[self getCurrentDevice]]; + NSString *imgName = [self getImageName:(id)vc device:[self getCurrentDevice]]; UIImage* splash = [self getImageFromName:imgName]; + if (splash == NULL) { - imageView = NULL; self.viewController.view.window.hidden = YES; } else { + [imageView removeFromSuperview]; + imageView = nil; + imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; [imageView setImage:splash]; @@ -154,7 +159,7 @@ -(void) applyPrivacyScreen [self.viewController.view addSubview:imageView]; #endif } - + } // Code below borrowed from the CDV splashscreen plugin @ https://github.com/apache/cordova-plugin-splashscreen @@ -183,7 +188,7 @@ - (CDV_iOSDevice) getCurrentDevice return device; } -- (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(id)orientationDelegate device:(CDV_iOSDevice)device +- (NSString*)getImageName:(id)orientationDelegate device:(CDV_iOSDevice)device { NSString* privacyImageNameKey = @"privacyimagename"; NSString* prefImageName = [self.commandDelegate.settings objectForKey:[privacyImageNameKey lowercaseString]]; @@ -209,7 +214,7 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i // this means there are no mixed orientations in there BOOL isOrientationLocked = !(supportsPortrait && supportsLandscape); - + UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; // Add Asset Catalog specific prefixes if ([imageName isEqualToString:@"LaunchImage"]) { @@ -219,14 +224,14 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i imageName = [imageName stringByAppendingString:@"-800"]; } else if(device.iPhone6Plus) { imageName = [imageName stringByAppendingString:@"-800"]; - if (currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { + if (deviceOrientation == UIDeviceOrientationPortrait || deviceOrientation == UIDeviceOrientationPortraitUpsideDown) { imageName = [imageName stringByAppendingString:@"-Portrait"]; } } } BOOL isLandscape = supportsLandscape && - (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight); + (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight); if (device.iPhone5) { // does not support landscape imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-568h"]; @@ -236,7 +241,7 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i if (isOrientationLocked) { imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"")]; } else { - switch (currentOrientation) { + switch (deviceOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: imageName = [imageName stringByAppendingString:@"-Landscape"]; @@ -251,7 +256,7 @@ - (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(i if (isOrientationLocked) { imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"-Portrait")]; } else { - switch (currentOrientation) { + switch (deviceOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: imageName = [imageName stringByAppendingString:@"-Landscape"]; From c2e0635a163b092817cac3df30447a7b706a0c59 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Mon, 4 Sep 2017 14:32:20 +0100 Subject: [PATCH 17/24] Updated files with 0.3.10 version --- package.json | 2 +- plugin.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 28f72a6..b8e0924 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.3.7", + "version": "0.3.10", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 3147df1..14d487a 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. From 6350dfa045b7ed14d971639eabc59a6c3e466e10 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Fri, 15 Dec 2017 17:23:19 +0000 Subject: [PATCH 18/24] Changed version to 0.4.0 \n Added screen sizes for 2x and 3x density using system like splash screen (launch screen) --- README.md | 9 ++- package.json | 2 +- plugin.xml | 2 +- src/ios/PrivacyScreenPlugin.m | 131 ++++++++++++++++++++++++++++++++-- 4 files changed, 133 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 296953d..17e3dca 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,13 @@ For iOS there are 3 preferences that can be set in config.xml: - "PrivacyOverrideLaunchImage": If set to "true" allows privacy screen to be the Default image even if LaunchImage is set in the info-plist - "PrivacyImageName": String for image name, images should be in the app bundle and follow the size naming convention (i.e. for app name "Test", there should be a "Test-667h.png" in the bundle for iPhone 6) - "PrivacyTimer": accepts a value in seconds for the privacy screen timer - + +When using splash storyboard add images to the config xml. +(i.e + + + ) + Test this plugin on a real device because the iOS simulator (7.1 at least) does a poor job hiding your app. ## License @@ -47,4 +53,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/package.json b/package.json index b8e0924..46b9128 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.3.10", + "version": "0.4.0", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 14d487a..13c6e16 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index e5d4d0f..b1ce894 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -139,7 +139,16 @@ -(void) applyPrivacyScreen { CDVViewController *vc = (CDVViewController*)self.viewController; NSString *imgName = [self getImageName:(id)vc device:[self getCurrentDevice]]; - UIImage* splash = [self getImageFromName:imgName]; + UIImage* splash; + if([self isUsingCDVLaunchScreen]) + { + splash = [self updatePrivacyImage]; + } + else + { + splash = [self getImageFromName:imgName]; + + } if (splash == NULL) { @@ -147,17 +156,21 @@ -(void) applyPrivacyScreen } else { - [imageView removeFromSuperview]; - imageView = nil; - - imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; - [imageView setImage:splash]; + if(![self isUsingCDVLaunchScreen]) + { + [imageView removeFromSuperview]; + imageView = nil; + + imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; + [imageView setImage:splash]; + } #ifdef __CORDOVA_4_0_0 [[UIApplication sharedApplication].keyWindow addSubview:imageView]; #else [self.viewController.view addSubview:imageView]; #endif + } } @@ -188,11 +201,115 @@ - (CDV_iOSDevice) getCurrentDevice return device; } +- (BOOL) isUsingCDVLaunchScreen { + NSString* launchStoryboardName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"]; + if (launchStoryboardName) { + return ([launchStoryboardName isEqualToString:@"CDVLaunchScreen"]); + } else { + return NO; + } +} + +// Sets the view's frame and image. +- (UIImage*)updatePrivacyImage +{ + NSString* imageName = [self getImageName:(id)self.viewController device:[self getCurrentDevice]]; + + UIImage* img = [UIImage imageNamed:imageName]; + [imageView removeFromSuperview]; + imageView = nil; + + imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; + [imageView setImage: img]; + + // Check that splash screen's image exists before updating bounds + if (imageView.image) + { + [self updateBounds]; + } + else + { + NSLog(@"WARNING: The splashscreen image named %@ was not found", imageName); + } + return img; +} + +- (void)updateBounds +{ + if ([self isUsingCDVLaunchScreen]) { + // CB-9762's launch screen expects the image to fill the screen and be scaled using AspectFill. + CGSize viewportSize = [UIApplication sharedApplication].delegate.window.bounds.size; + imageView.frame = CGRectMake(0, 0, viewportSize.width, viewportSize.height); + imageView.contentMode = UIViewContentModeScaleAspectFill; + return; + } + + UIImage* img = imageView.image; + CGRect imgBounds = (img) ? CGRectMake(0, 0, img.size.width, img.size.height) : CGRectZero; + + CGSize screenSize = [self.viewController.view convertRect:[UIScreen mainScreen].bounds fromView:nil].size; + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + CGAffineTransform imgTransform = CGAffineTransformIdentity; + + /* If and only if an iPhone application is landscape-only as per + * UISupportedInterfaceOrientations, the view controller's orientation is + * landscape. In this case the image must be rotated in order to appear + * correctly. + */ + CDV_iOSDevice device = [self getCurrentDevice]; + if (UIInterfaceOrientationIsLandscape(orientation) && !device.iPhone6Plus && !device.iPad) + { + imgTransform = CGAffineTransformMakeRotation(M_PI / 2); + imgBounds.size = CGSizeMake(imgBounds.size.height, imgBounds.size.width); + } + + // There's a special case when the image is the size of the screen. + if (CGSizeEqualToSize(screenSize, imgBounds.size)) + { + CGRect statusFrame = [self.viewController.view convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil]; + if (!(IsAtLeastiOSVersion(@"7.0"))) + { + imgBounds.origin.y -= statusFrame.size.height; + } + } + else if (imgBounds.size.width > 0) + { + CGRect viewBounds = self.viewController.view.bounds; + CGFloat imgAspect = imgBounds.size.width / imgBounds.size.height; + CGFloat viewAspect = viewBounds.size.width / viewBounds.size.height; + // This matches the behaviour of the native splash screen. + CGFloat ratio; + if (viewAspect > imgAspect) + { + ratio = viewBounds.size.width / imgBounds.size.width; + } + else + { + ratio = viewBounds.size.height / imgBounds.size.height; + } + imgBounds.size.height *= ratio; + imgBounds.size.width *= ratio; + } + + imageView.transform = imgTransform; + imageView.frame = imgBounds; +} + + + + - (NSString*)getImageName:(id)orientationDelegate device:(CDV_iOSDevice)device { + + NSString* imageName; + // detect if we are using CB-9762 Launch Storyboard; if so, return the associated image instead + if ([self isUsingCDVLaunchScreen]) { + imageName = @"Default"; + return imageName; + } NSString* privacyImageNameKey = @"privacyimagename"; NSString* prefImageName = [self.commandDelegate.settings objectForKey:[privacyImageNameKey lowercaseString]]; - NSString* imageName = prefImageName ? prefImageName : @"Default"; + imageName = prefImageName ? prefImageName : @"Default"; //Override Launch images? NSString* privacyOverrideLaunchImage = @"privacyoverridelaunchimage"; if([self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] && [[self.commandDelegate.settings objectForKey:[privacyOverrideLaunchImage lowercaseString]] isEqualToString:@"true"]) From d1c88a942361a82ac9b3b32ea265bd2266729fb4 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Mon, 18 Dec 2017 15:17:40 +0000 Subject: [PATCH 19/24] Launch Imges --- README.md | 4 ++-- package.json | 2 +- plugin.xml | 2 +- src/ios/PrivacyScreenPlugin.m | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 17e3dca..0a14892 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ For iOS there are 3 preferences that can be set in config.xml: When using splash storyboard add images to the config xml. (i.e - - + + ) Test this plugin on a real device because the iOS simulator (7.1 at least) does a poor job hiding your app. diff --git a/package.json b/package.json index 46b9128..c18bf29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.4.0", + "version": "0.4.1", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index 13c6e16..a2aa763 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index b1ce894..2b16c4c 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -304,7 +304,10 @@ - (NSString*)getImageName:(id)orientationDelegate NSString* imageName; // detect if we are using CB-9762 Launch Storyboard; if so, return the associated image instead if ([self isUsingCDVLaunchScreen]) { - imageName = @"Default"; + // Use UILaunchImageFile if specified in plist. Otherwise, use Default. + imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; + imageName = [imageName stringByDeletingPathExtension]; + imageName = imageName ? imageName : @"LaunchImage"; return imageName; } NSString* privacyImageNameKey = @"privacyimagename"; From c4215699eb22a140d06140376e398442de9e5af8 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 10 Jan 2018 13:51:19 +0000 Subject: [PATCH 20/24] Added iPhone 4S support --- src/ios/PrivacyScreenPlugin.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index 2b16c4c..db2f270 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -353,7 +353,9 @@ - (NSString*)getImageName:(id)orientationDelegate BOOL isLandscape = supportsLandscape && (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight); - if (device.iPhone5) { // does not support landscape + if (device.iPhone4) { // does not support landscape + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-480h"]; + } else if (device.iPhone5) { // does not support landscape imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-568h"]; } else if (device.iPhone6) { // does not support landscape imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-667h"]; From e887a5dec7ebab280fe503bf88761238da62d184 Mon Sep 17 00:00:00 2001 From: ncaeiro75 Date: Wed, 31 Jan 2018 15:52:11 +0000 Subject: [PATCH 21/24] Update PrivacyScreenPlugin.h Added iPhoneX to device struct --- src/ios/PrivacyScreenPlugin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ios/PrivacyScreenPlugin.h b/src/ios/PrivacyScreenPlugin.h index cfe049b..1fc5e4a 100644 --- a/src/ios/PrivacyScreenPlugin.h +++ b/src/ios/PrivacyScreenPlugin.h @@ -15,6 +15,7 @@ typedef struct { BOOL iPhone6; BOOL iPhone6Plus; BOOL retina; + BOOL iPhoneX; } CDV_iOSDevice; From 6e4242d137e4251b0fec101475a0df79f8f7cb5a Mon Sep 17 00:00:00 2001 From: ncaeiro75 Date: Wed, 31 Jan 2018 16:00:28 +0000 Subject: [PATCH 22/24] Update PrivacyScreenPlugin.m Removed '-' from calculated privacy screen images names; Support for iPhoneX screen size; Removed support for Launch Screen Storyboard; --- src/ios/PrivacyScreenPlugin.m | 46 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index db2f270..e248b7f 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -197,6 +197,7 @@ - (CDV_iOSDevice) getCurrentDevice // this is appropriate for detecting the runtime screen environment device.iPhone6 = (device.iPhone && limit == 667.0); device.iPhone6Plus = (device.iPhone && limit == 736.0); + device.iPhoneX = (device.iPhone && limit == 812.0); return device; } @@ -236,6 +237,9 @@ - (UIImage*)updatePrivacyImage - (void)updateBounds { + /* + * Launch Screen StoryBoard not supported + * if ([self isUsingCDVLaunchScreen]) { // CB-9762's launch screen expects the image to fill the screen and be scaled using AspectFill. CGSize viewportSize = [UIApplication sharedApplication].delegate.window.bounds.size; @@ -243,6 +247,7 @@ - (void)updateBounds imageView.contentMode = UIViewContentModeScaleAspectFill; return; } + */ UIImage* img = imageView.image; CGRect imgBounds = (img) ? CGRectMake(0, 0, img.size.width, img.size.height) : CGRectZero; @@ -302,14 +307,19 @@ - (NSString*)getImageName:(id)orientationDelegate { NSString* imageName; - // detect if we are using CB-9762 Launch Storyboard; if so, return the associated image instead - if ([self isUsingCDVLaunchScreen]) { - // Use UILaunchImageFile if specified in plist. Otherwise, use Default. - imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; - imageName = [imageName stringByDeletingPathExtension]; - imageName = imageName ? imageName : @"LaunchImage"; - return imageName; - } + /* + * Launch Storyboard not supported + // detect if we are using CB-9762 Launch Storyboard; if so, return the associated image instead + if ([self isUsingCDVLaunchScreen]) { + // Use UILaunchImageFile if specified in plist. Otherwise, use Default. + imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; + imageName = [imageName stringByDeletingPathExtension]; + imageName = imageName ? imageName : @"LaunchImage"; + return imageName; + } + * + */ + NSString* privacyImageNameKey = @"privacyimagename"; NSString* prefImageName = [self.commandDelegate.settings objectForKey:[privacyImageNameKey lowercaseString]]; imageName = prefImageName ? prefImageName : @"Default"; @@ -354,40 +364,42 @@ - (NSString*)getImageName:(id)orientationDelegate (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight); if (device.iPhone4) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-480h"]; + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"480h"]; } else if (device.iPhone5) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-568h"]; + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"568h"]; } else if (device.iPhone6) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"-667h"]; + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"667h"]; + } else if (device.iPhoneX) { // does not support landscape + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"812]; } else if (device.iPhone6Plus) { // supports landscape if (isOrientationLocked) { - imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"")]; + imageName = [imageName stringByAppendingString:(supportsLandscape ? @"Landscape" : @"")]; } else { switch (deviceOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; + imageName = [imageName stringByAppendingString:@"Landscape"]; break; default: break; } } - imageName = [imageName stringByAppendingString:@"-736h"]; + imageName = [imageName stringByAppendingString:@"736h"]; } else if (device.iPad) { // supports landscape if (isOrientationLocked) { - imageName = [imageName stringByAppendingString:(supportsLandscape ? @"-Landscape" : @"-Portrait")]; + imageName = [imageName stringByAppendingString:(supportsLandscape ? @"Landscape" : @"Portrait")]; } else { switch (deviceOrientation) { case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeRight: - imageName = [imageName stringByAppendingString:@"-Landscape"]; + imageName = [imageName stringByAppendingString:@"Landscape"]; break; case UIInterfaceOrientationPortrait: case UIInterfaceOrientationPortraitUpsideDown: default: - imageName = [imageName stringByAppendingString:@"-Portrait"]; + imageName = [imageName stringByAppendingString:@"Portrait"]; break; } } From 7d66752f8e7b85814f55b4b27b60507ff36f2b96 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 31 Jan 2018 17:14:14 +0000 Subject: [PATCH 23/24] Changed version --- package.json | 2 +- plugin.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c18bf29..a08ddaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-privacyscreen", - "version": "0.4.1", + "version": "0.4.3", "description": "Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.", "cordova": { "id": "cordova-plugin-privacyscreen", diff --git a/plugin.xml b/plugin.xml index a2aa763..a79c1ae 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + PrivacyScreenPlugin Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private. From 6ce5655a836b765bb42015d4148ba5f8a410b2f2 Mon Sep 17 00:00:00 2001 From: "Tiago Nunes (BPI)" Date: Wed, 31 Jan 2018 17:27:13 +0000 Subject: [PATCH 24/24] Bug fix for pull request and clean up --- src/ios/PrivacyScreenPlugin.m | 81 ++++------------------------------- 1 file changed, 8 insertions(+), 73 deletions(-) diff --git a/src/ios/PrivacyScreenPlugin.m b/src/ios/PrivacyScreenPlugin.m index e248b7f..c68916f 100644 --- a/src/ios/PrivacyScreenPlugin.m +++ b/src/ios/PrivacyScreenPlugin.m @@ -140,15 +140,8 @@ -(void) applyPrivacyScreen CDVViewController *vc = (CDVViewController*)self.viewController; NSString *imgName = [self getImageName:(id)vc device:[self getCurrentDevice]]; UIImage* splash; - if([self isUsingCDVLaunchScreen]) - { - splash = [self updatePrivacyImage]; - } - else - { - splash = [self getImageFromName:imgName]; - - } + + splash = [self getImageFromName:imgName]; if (splash == NULL) { @@ -156,14 +149,12 @@ -(void) applyPrivacyScreen } else { - if(![self isUsingCDVLaunchScreen]) - { - [imageView removeFromSuperview]; - imageView = nil; + + [imageView removeFromSuperview]; + imageView = nil; - imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; - [imageView setImage:splash]; - } + imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; + [imageView setImage:splash]; #ifdef __CORDOVA_4_0_0 [[UIApplication sharedApplication].keyWindow addSubview:imageView]; @@ -202,52 +193,8 @@ - (CDV_iOSDevice) getCurrentDevice return device; } -- (BOOL) isUsingCDVLaunchScreen { - NSString* launchStoryboardName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchStoryboardName"]; - if (launchStoryboardName) { - return ([launchStoryboardName isEqualToString:@"CDVLaunchScreen"]); - } else { - return NO; - } -} - -// Sets the view's frame and image. -- (UIImage*)updatePrivacyImage -{ - NSString* imageName = [self getImageName:(id)self.viewController device:[self getCurrentDevice]]; - - UIImage* img = [UIImage imageNamed:imageName]; - [imageView removeFromSuperview]; - imageView = nil; - - imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]]; - [imageView setImage: img]; - - // Check that splash screen's image exists before updating bounds - if (imageView.image) - { - [self updateBounds]; - } - else - { - NSLog(@"WARNING: The splashscreen image named %@ was not found", imageName); - } - return img; -} - - (void)updateBounds { - /* - * Launch Screen StoryBoard not supported - * - if ([self isUsingCDVLaunchScreen]) { - // CB-9762's launch screen expects the image to fill the screen and be scaled using AspectFill. - CGSize viewportSize = [UIApplication sharedApplication].delegate.window.bounds.size; - imageView.frame = CGRectMake(0, 0, viewportSize.width, viewportSize.height); - imageView.contentMode = UIViewContentModeScaleAspectFill; - return; - } - */ UIImage* img = imageView.image; CGRect imgBounds = (img) ? CGRectMake(0, 0, img.size.width, img.size.height) : CGRectZero; @@ -307,18 +254,6 @@ - (NSString*)getImageName:(id)orientationDelegate { NSString* imageName; - /* - * Launch Storyboard not supported - // detect if we are using CB-9762 Launch Storyboard; if so, return the associated image instead - if ([self isUsingCDVLaunchScreen]) { - // Use UILaunchImageFile if specified in plist. Otherwise, use Default. - imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; - imageName = [imageName stringByDeletingPathExtension]; - imageName = imageName ? imageName : @"LaunchImage"; - return imageName; - } - * - */ NSString* privacyImageNameKey = @"privacyimagename"; NSString* prefImageName = [self.commandDelegate.settings objectForKey:[privacyImageNameKey lowercaseString]]; @@ -370,7 +305,7 @@ - (NSString*)getImageName:(id)orientationDelegate } else if (device.iPhone6) { // does not support landscape imageName = isLandscape ? nil : [imageName stringByAppendingString:@"667h"]; } else if (device.iPhoneX) { // does not support landscape - imageName = isLandscape ? nil : [imageName stringByAppendingString:@"812]; + imageName = isLandscape ? nil : [imageName stringByAppendingString:@"812h"]; } else if (device.iPhone6Plus) { // supports landscape if (isOrientationLocked) { imageName = [imageName stringByAppendingString:(supportsLandscape ? @"Landscape" : @"")];