Skip to content

Commit

Permalink
Merge pull request #3 from Telerik-Verified-Plugins/master
Browse files Browse the repository at this point in the history
Don't wipe appstate & landscape iOS support
  • Loading branch information
devgeeks committed Oct 31, 2014
2 parents ea64cd3 + 11db044 commit 28f1304
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 50 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ This is a lovely feature for most apps, but if your app displays sensitive infor

This plugin flags your app so that it doesn't show your users' sensitive data in the task switcher. It sets the [FLAG_SECURE](http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SECURE) flag in Android (which also prevents manual screenshots from being taken) and hides the window in iOS.

On iOS this plugin will show your splashscreen in the app switcher, but it requires your splashscreens basesname to be named `Default`. E.g. `Default~iphone.png` and `Default-568@2x~iphone.png`.
On iOS this plugin will try to show your splashscreen in the app switcher. It will search for splashscreens prefixed by `Default` or the value of the key `UILaunchImageFile` in your .plist file.
If it fails to find a splashscreen for a specific device or orientation (portrait or landscape), a black screen is shown instead.

Installation
------------
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="org.devgeeks.privacyscreen" version="0.0.5">
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="org.devgeeks.privacyscreen" version="0.0.7">

<name>PrivacyScreenPlugin</name>
<description>Secures your app from displaying a screenshot in task switchers under Android and iOS. Keeps sensitive information private.</description>
Expand Down
16 changes: 13 additions & 3 deletions src/ios/AppDelegate+privacyscreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@
*/
#import "AppDelegate.h"

typedef struct {
BOOL iPhone;
BOOL iPad;
BOOL iPhone5;
BOOL iPhone6;
BOOL iPhone6Plus;
BOOL retina;

} CDV_iOSDevice;

@interface AppDelegate (privacyscreen)
- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationDidBecomeActive:(UIApplication *)application;

@end
@end
141 changes: 96 additions & 45 deletions src/ios/AppDelegate+privacyscreen.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,63 +11,114 @@

@implementation AppDelegate (privacyscreen)

// Taken from https://github.com/phonegap-build/PushPlugin/blob/master/src/ios/AppDelegate%2Bnotification.m
// its dangerous to override a method from within a category.
// Instead we will use method swizzling. we set this up in the load call.
+ (void)load
- (void)applicationDidBecomeActive:(UIApplication *)application
{
Method original, swizzled;

original = class_getInstanceMethod(self, @selector(init));
swizzled = class_getInstanceMethod(self, @selector(swizzled_init));
method_exchangeImplementations(original, swizzled);
if (imageView == NULL) {
self.window.hidden = NO;
} else {
[imageView removeFromSuperview];
}
}

- (AppDelegate *)swizzled_init
- (void)applicationWillResignActive:(UIApplication *)application
{
if ([UIApplication respondsToSelector:@selector(ignoreSnapshotOnNextApplicationLaunch:)]) {
[[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];
// Add any notification observers here...
}
// This actually calls the original init method over in AppDelegate. Equivilent to calling super
// on an overrided method, this is not recursive, although it appears that way. neat huh?
return [self swizzled_init];
NSString *imgName = [self getImageName:self.viewController.interfaceOrientation delegate:(id<CDVScreenOrientationDelegate>)self.viewController device:[self getCurrentDevice]];
UIImage *splash = [UIImage imageNamed:imgName];
if (splash == NULL) {
self.window.hidden = YES;
} else {
imageView = [[UIImageView alloc]initWithFrame:[self.viewController.view bounds]];
[imageView setImage:splash];
[self.viewController.view addSubview:imageView];
}
}

- (void)applicationDidBecomeActive:(UIApplication *)application
// 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
{
if (imageView == NULL && [[UIApplication sharedApplication] respondsToSelector:@selector(ignoreSnapshotOnNextApplicationLaunch:)]) {
[[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];
self.window.hidden = NO;
} else {
[imageView removeFromSuperview];
}
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.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;
}

- (void)applicationWillResignActive:(UIApplication *)application
- (NSString*)getImageName:(UIInterfaceOrientation)currentOrientation delegate:(id<CDVScreenOrientationDelegate>)orientationDelegate device:(CDV_iOSDevice)device
{
// for now, assuming 'Default' is the basename of the splashscreen, with a fallback to hiding the window
UIImage *splash = [self imageNamedForDevice: @"Default"];
if (splash == NULL && [[UIApplication sharedApplication] respondsToSelector:@selector(ignoreSnapshotOnNextApplicationLaunch:)]) {
[[UIApplication sharedApplication] ignoreSnapshotOnNextApplicationLaunch];
self.window.hidden = YES;
// 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";
}

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 {
imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
[imageView setImage:splash];
[UIApplication.sharedApplication.keyWindow.subviews.lastObject addSubview:imageView];
switch (currentOrientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
imageName = [imageName stringByAppendingString:@"-Landscape"];
break;
default:
break;
}
}
}

- (UIImage*)imageNamedForDevice:(NSString*)name
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
if (([UIScreen mainScreen].bounds.size.height * [UIScreen mainScreen].scale) >= 1136.0f) {
name = [name stringByAppendingString:@"-568h@2x"];
}
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
name = [name stringByAppendingString:@"-Portrait"];
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 [UIImage imageNamed: name];
}

return imageName;
}

@end
@end

0 comments on commit 28f1304

Please sign in to comment.