iOS 8 Support

- Supporting iOS 8
- Updating translations
- Rewriting PushManager to extensively use futures
- Pick up calls directly from the lock-screen
This commit is contained in:
Frederic Jacobs 2014-09-15 01:32:19 +02:00
parent 8b42036f16
commit cd0bda7105
51 changed files with 339 additions and 136 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -39,6 +39,15 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A1B989631725EC1300B6E8B5"
BuildableName = "libspandsp.a"
BlueprintName = "spandsp"
ReferencedContainer = "container:spandsp.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -39,6 +39,15 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A1FDCBF916DBC57D00868894"
BuildableName = "libspeex.a"
BlueprintName = "speex"
ReferencedContainer = "container:speex.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>

View File

@ -4,8 +4,8 @@ link_with ["Signal", "SignalTests"]
pod 'UICKeyChainStore', :podspec => 'Podspecs/UICKeyChainStore.podspec'
pod 'OpenSSL', '~> 1.0.109'
pod 'MMDrawerController', '~> 0.5.0'
pod 'MMDrawerController', '~> 0.5.7'
pod 'libPhoneNumber-iOS', '~> 0.7'
pod 'PastelogKit', '~> 1.1'
pod 'AFNetworking', '~> 2.3.1'
pod 'AFNetworking', '~> 2.4.1'
pod 'TwistedOakCollapsingFutures','~> 1.0'

View File

@ -1,23 +1,23 @@
PODS:
- AFNetworking (2.3.1):
- AFNetworking (2.4.1):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/UIKit
- AFNetworking/NSURLConnection (2.3.1):
- AFNetworking/NSURLConnection (2.4.1):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/NSURLSession (2.3.1):
- AFNetworking/NSURLSession (2.4.1):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/Reachability (2.3.1)
- AFNetworking/Security (2.3.1)
- AFNetworking/Serialization (2.3.1)
- AFNetworking/UIKit (2.3.1):
- AFNetworking/Reachability (2.4.1)
- AFNetworking/Security (2.4.1)
- AFNetworking/Serialization (2.4.1)
- AFNetworking/UIKit (2.4.1):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- CocoaLumberjack (1.9.2):
@ -26,17 +26,17 @@ PODS:
- CocoaLumberjack/Extensions (1.9.2):
- CocoaLumberjack/Core
- libPhoneNumber-iOS (0.7.3)
- MMDrawerController (0.5.6):
- MMDrawerController (0.5.7):
- MMDrawerController/Core
- MMDrawerController/MMDrawerBarButtonItem
- MMDrawerController/MMDrawerVisualStates
- MMDrawerController/Subclass
- MMDrawerController/Core (0.5.6)
- MMDrawerController/MMDrawerBarButtonItem (0.5.6):
- MMDrawerController/Core (0.5.7)
- MMDrawerController/MMDrawerBarButtonItem (0.5.7):
- MMDrawerController/Core
- MMDrawerController/MMDrawerVisualStates (0.5.6):
- MMDrawerController/MMDrawerVisualStates (0.5.7):
- MMDrawerController/Core
- MMDrawerController/Subclass (0.5.6):
- MMDrawerController/Subclass (0.5.7):
- MMDrawerController/Core
- OpenSSL (1.0.109)
- PastelogKit (1.1):
@ -47,9 +47,9 @@ PODS:
- UnionFind (1.0.1)
DEPENDENCIES:
- AFNetworking (~> 2.3.1)
- AFNetworking (~> 2.4.1)
- libPhoneNumber-iOS (~> 0.7)
- MMDrawerController (~> 0.5.0)
- MMDrawerController (~> 0.5.7)
- OpenSSL (~> 1.0.109)
- PastelogKit (~> 1.1)
- TwistedOakCollapsingFutures (~> 1.0)
@ -60,10 +60,10 @@ EXTERNAL SOURCES:
:podspec: Podspecs/UICKeyChainStore.podspec
SPEC CHECKSUMS:
AFNetworking: 6d7b76aa5d04c8c37daad3eef4b7e3f2a7620da3
AFNetworking: 0aabc6fae66d6e5d039eeb21c315843c7aae51ab
CocoaLumberjack: 205769c032b5fef85b92472046bcc8b7e7c8a817
libPhoneNumber-iOS: 98fc07d70c8fdb5e6a8e3442c37e97353065c20e
MMDrawerController: 4bae84535ca7a5f4cb55a66a001e6035c3571677
MMDrawerController: c3ab7a318ddc7e2bcd133139c3161af08c6e1197
OpenSSL: 4810adf5c99b0e2cd20670a11a987c805e8a521c
PastelogKit: 32836ec27e587a8876326abeaf9a1b5e2bc484ea
TwistedOakCollapsingFutures: 07aab84fd3958dc94d55ef705b12857d9fbe61d1

2
Pods

@ -1 +1 @@
Subproject commit 5d4e467489501e0a8b76a3f636380e8f00296947
Subproject commit 594aa6022c574bd1798041dd440af1aedc4d21b5

View File

@ -396,6 +396,7 @@
B6416FD4199A0478003C5699 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6416FAB199A0478003C5699 /* Localizable.strings */; };
B67ADDC41989FF8700E1A773 /* CallServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* CallServerRequestsManager.m */; };
B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; };
B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B684A46C19C3446200B11029 /* PushManagerTest.m */; };
B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6850E591995A4710068E715 /* whisperFake.cer */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6B1013C196D213F007E3930 /* SGNKeychainUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */; };
@ -1098,6 +1099,7 @@
B67ADDC21989FF8700E1A773 /* CallServerRequestsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallServerRequestsManager.h; sourceTree = "<group>"; };
B67ADDC31989FF8700E1A773 /* CallServerRequestsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CallServerRequestsManager.m; sourceTree = "<group>"; };
B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; };
B684A46C19C3446200B11029 /* PushManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PushManagerTest.m; path = Signal/test/push/PushManagerTest.m; sourceTree = SOURCE_ROOT; };
B6850E591995A4710068E715 /* whisperFake.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperFake.cer; sourceTree = "<group>"; };
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
B6B1013A196D213F007E3930 /* SGNKeychainUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGNKeychainUtil.h; sourceTree = "<group>"; };
@ -2196,6 +2198,7 @@
A157073917F0CD6D007C2BD6 /* Supporting Files */,
A157073B17F0CD6D007C2BD6 /* TestUtil.h */,
A157073C17F0CD6D007C2BD6 /* TestUtil.m */,
B684A46C19C3446200B11029 /* PushManagerTest.m */,
A157073D17F0CD6D007C2BD6 /* util */,
);
path = test;
@ -3007,12 +3010,18 @@
D221A088169C9E5E00537ABF = {
DevelopmentTeam = U68MSDN6DR;
SystemCapabilities = {
com.apple.DataProtection = {
enabled = 1;
};
com.apple.InAppPurchase = {
enabled = 0;
};
com.apple.InterAppAudio = {
enabled = 0;
};
com.apple.VPNLite = {
enabled = 0;
};
};
};
D221A0A9169C9E5F00537ABF = {
@ -3739,6 +3748,7 @@
76EB066118170B34006006FC /* RegisterViewController.m in Sources */,
76EB068D18170B34006006FC /* InboxFeedTableViewCell.m in Sources */,
BFB074C119A4BCA400F2947C /* FutureUtilTest.m in Sources */,
B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */,
76EB05A918170B33006006FC /* RtpSocket.m in Sources */,
765052B0182AC9B5008313E1 /* DialerButtonView.m in Sources */,
76EB062B18170B33006006FC /* BadState.m in Sources */,
@ -4194,8 +4204,8 @@
isa = XCBuildConfiguration;
baseConfigurationReference = C71793B33D9C45079F74487E /* Pods.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CURRENT_PROJECT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -4234,7 +4244,7 @@
LLVM_LTO = NO;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_NAME = Signal;
PROVISIONING_PROFILE = "036480DA-A21D-4CC6-BF48-98E8AE1EE981";
PROVISIONING_PROFILE = "4aa31d4f-187c-470a-add6-8e949fc2cfd1";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TEST_AFTER_BUILD = YES;
@ -4483,8 +4493,8 @@
isa = XCBuildConfiguration;
baseConfigurationReference = C71793B33D9C45079F74487E /* Pods.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CURRENT_PROJECT_VERSION = 1;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -4521,7 +4531,7 @@
LLVM_LTO = NO;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_NAME = Signal;
PROVISIONING_PROFILE = "7214A823-1F7A-4460-82D8-D89CA511CEA6";
PROVISIONING_PROFILE = "4434E074-1111-40F0-A7B6-CEA8437ACFE1";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TEST_AFTER_BUILD = YES;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -29,13 +29,13 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.4</string>
<string>1.0.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.4</string>
<string>1.0.5</string>
<key>LSApplicationCategoryType</key>
<string></string>
<string>public.app-category.social-networking</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIAppFonts</key>
@ -48,6 +48,7 @@
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>remote-notification</string>
<string>voip</string>
</array>

View File

@ -32,6 +32,8 @@
@property (nonatomic, strong) MMDrawerController *drawerController;
@property (nonatomic, strong) NotificationTracker *notificationTracker;
@property (nonatomic) TOCFutureSource *callPickUpFuture;
@end
@implementation AppDelegate
@ -154,7 +156,18 @@
InCallViewController *callViewController = [InCallViewController inCallViewControllerWithCallState:latestCall
andOptionallyKnownContact:latestCall.potentiallySpecifiedContact];
if (latestCall.initiatedLocally == false){
[self.callPickUpFuture.future thenDo:^(NSNumber *accept) {
if ([accept isEqualToNumber:@YES]) {
[callViewController answerButtonTapped];
} else if ([accept isEqualToNumber:@NO]){
[callViewController rejectButtonTapped];
}
}];
}
[_drawerController.centerViewController presentViewController:callViewController animated:YES completion:nil];
} onThread:NSThread.mainThread untilCancelled:nil];
@ -162,12 +175,15 @@
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
[PushManager.sharedManager registerForPushWithToken:deviceToken];
[[PushManager sharedManager].pushNotificationFutureSource trySetResult:deviceToken];
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
[PushManager.sharedManager verifyPushActivated];
DDLogError(@"Failed to register for push notifications: %@", error);
[[PushManager sharedManager].pushNotificationFutureSource trySetFailure:error];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
[[PushManager sharedManager].userNotificationFutureSource trySetResult:notificationSettings];
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
@ -184,7 +200,7 @@
DDLogError(@"Decryption of session descriptor failed");
return;
}
self.callPickUpFuture = [TOCFutureSource new];
[Environment.phoneManager incomingCallWithSession:call];
}
@ -207,11 +223,20 @@
[self removeScreenProtection];
if (Environment.isRegistered) {
[PushManager.sharedManager verifyPushActivated];
[PushManager.sharedManager verifyPushPermissions];
[AppAudioManager.sharedInstance requestRequiredPermissionsIfNeeded];
}
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler{
if ([identifier isEqualToString:Signal_Accept_Identifier]) {
[self.callPickUpFuture trySetResult:@YES];
} else if ([identifier isEqualToString:Signal_Decline_Identifier]){
[self.callPickUpFuture trySetResult:@NO];
}
completionHandler();
}
- (void)applicationWillResignActive:(UIApplication *)application{
[self protectScreen];
}

View File

@ -43,7 +43,11 @@
// Some users push IDs were not correctly registered, by precaution, we are going to re-register all of them
[PushManager.sharedManager askForPushRegistration];
[PushManager.sharedManager registrationWithSuccess:^{
} failure:^{
DDLogError(@"Error re-registering on migration from 1.0.2");
}];
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];

View File

@ -6,19 +6,42 @@
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <TwistedOakCollapsingFutures/CollapsingFutures.h>
#import <Foundation/Foundation.h>
#define Signal_Accept_Identifier @"Signal_Call_Accept"
#define Signal_Decline_Identifier @"Signal_Call_Decline"
/**
* The Push Manager is responsible for registering the device for Signal push notifications.
*/
@interface PushManager : NSObject
+ (instancetype)sharedManager;
- (void)verifyPushActivated;
/**
* Push notification token is always registered during signup. User can however revoke notifications.
* Therefore, we check on startup if mandatory permissions are granted.
*/
- (void)askForPushRegistration;
- (void)verifyPushPermissions;
- (void)askForPushRegistrationWithSuccess:(void (^)())success failure:(void (^)())failure;
/**
* Push notification registration method
*
* @param success Block to execute after succesful push notification registration
* @param failure Block to executre if push notification registration fails
*/
- (void)registerForPushWithToken:(NSData*)token;
- (void)registrationWithSuccess:(void (^)())success failure:(void (^)())failure;
/**
* The pushNotification and userNotificationFutureSource are accessed by the App Delegate after requested permissions.
*/
@property TOCFutureSource *pushNotificationFutureSource;
@property TOCFutureSource *userNotificationFutureSource;
@end

View File

@ -9,13 +9,13 @@
#import "PushManager.h"
#import "Environment.h"
#import "CallServerRequestsManager.h"
#import "FutureUtil.h"
@interface PushManager ()
@property (nonatomic, copy) void (^PushRegisteringSuccessBlock)();
@property (nonatomic, copy) void (^PushRegisteringFailureBlock)();
@property TOCFutureSource *registerWithServerFutureSource;
@property int retries;
@property UIAlertView *missingPermissionsAlertView;
@end
@ -26,123 +26,209 @@
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [self new];
sharedManager.missingPermissionsAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil];
});
return sharedManager;
}
- (void)verifyPushActivated{
UIRemoteNotificationType notificationTypes = [UIApplication.sharedApplication enabledRemoteNotificationTypes];
- (void)verifyPushPermissions{
BOOL needsPushSettingChangeAlert = NO;
if (notificationTypes == UIRemoteNotificationTypeNone) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeBadge) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeAlert) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeSound) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)) {
needsPushSettingChangeAlert = YES;
}
if (needsPushSettingChangeAlert) {
[Environment.preferences setRevokedPushPermission:YES];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil];
[alertView show];
} else if (!needsPushSettingChangeAlert){
if (Environment.preferences.encounteredRevokedPushPermission) {
[self askForPushRegistration];
if (SYSTEM_VERSION_LESS_THAN(_iOS_8_0)) {
// Displaying notifications and ringing
if ([self isMissingMandatoryNotificationTypes:[UIApplication.sharedApplication enabledRemoteNotificationTypes]]) {
[self registrationWithSuccess:^{
DDLogInfo(@"Push notifications were succesfully re-enabled");
} failure:^{
[self.missingPermissionsAlertView show];
}];
}
} else{
// UIUserNotificationsSettings
UIUserNotificationSettings *settings = [UIApplication.sharedApplication currentUserNotificationSettings];
// To use Signal, it is required to have sound notifications and alert types.
if ([self isMissingMandatoryNotificationTypes:settings.types]) {
[self registrationForUserNotificationWithSuccess:^{
DDLogInfo(@"User notifications were succesfully re-enabled");
} failure:^{
[self.missingPermissionsAlertView show];
}];
}
// Remote Notifications
if (![UIApplication.sharedApplication isRegisteredForRemoteNotifications]) {
[self registrationForPushWithSuccess:^{
DDLogInfo(@"Push notification were succesfully re-enabled");
} failure:^{
DDLogError(@"The phone could not be re-registered for push notifications."); // Push tokens are not changing on the same phone, just user notification changes so it's not very important.
}];
}
}
}
- (void)askForPushRegistrationWithSuccess:(void (^)())success failure:(void (^)())failure{
self.PushRegisteringSuccessBlock = success;
self.PushRegisteringFailureBlock = failure;
[self askForPushRegistration];
}
- (void)askForPushRegistration{
- (void)registrationWithSuccess:(void (^)())success failure:(void (^)())failure{
if(SYSTEM_VERSION_LESS_THAN(_iOS_8_0)){
[UIApplication.sharedApplication registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
if (SYSTEM_VERSION_LESS_THAN(_iOS_8_0)) {
// On iOS7, we just need to register for Push Notifications (user notifications are enabled with them)
[self registrationForPushWithSuccess:success failure:failure];
} else{
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1
UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new];
action_accept.identifier = @"Signal_Call_Accept";
action_accept.title = @"Pick up";
action_accept.activationMode = UIUserNotificationActivationModeForeground;
action_accept.destructive = YES;
action_accept.authenticationRequired = NO;
UIMutableUserNotificationAction *action_decline = [UIMutableUserNotificationAction new];
action_decline.identifier = @"Signal_Call_Decline";
action_decline.title = @"Pick up";
action_decline.activationMode = UIUserNotificationActivationModeForeground;
action_decline.destructive = YES;
action_decline.authenticationRequired = NO;
// On iOS 8+, both Push Notifications and User Notfications need to be registered.
UIMutableUserNotificationCategory *callCategory = [UIMutableUserNotificationCategory new];
callCategory.identifier = @"Signal_IncomingCall";
[callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextDefault];
NSSet *categories = [NSSet setWithObject:callCategory];
[UIApplication.sharedApplication registerForRemoteNotifications];
[UIApplication.sharedApplication registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound) categories:categories]];
#endif
[self registrationForPushWithSuccess:^{
[self registrationForUserNotificationWithSuccess:success failure:^{
[self.missingPermissionsAlertView show];
failure();
}];
} failure:failure];
}
self.retries = 3;
}
- (void)registerForPushWithToken:(NSData*)token{
#pragma mark Private Methods
#pragma mark Register Push Notification Token with server
-(TOCFuture*)registerForPushFutureWithToken:(NSData*)token{
self.registerWithServerFutureSource = [TOCFutureSource new];
[CallServerRequestsManager.sharedInstance registerPushToken:token success:^(NSURLSessionDataTask *task, id responseObject) {
if ([task.response isKindOfClass: NSHTTPURLResponse.class]){
NSInteger statusCode = [(NSHTTPURLResponse*) task.response statusCode];
if (statusCode == 200) {
DDLogInfo(@"Device sent push ID to server");
[Environment.preferences setRevokedPushPermission:NO];
if (self.PushRegisteringSuccessBlock) {
self.PushRegisteringSuccessBlock();
self.PushRegisteringSuccessBlock = nil;
}
[self.registerWithServerFutureSource trySetResult:@YES];
} else{
[self registerFailureWithToken:token];
DDLogError(@"The server returned %@ instead of a 200 status code", task.response);
[self.registerWithServerFutureSource trySetFailure:@NO];
}
} else{
[self.registerWithServerFutureSource trySetFailure:@NO];
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
[self registerFailureWithToken:token];
[self.registerWithServerFutureSource trySetFailure:@NO];
}];
return self.registerWithServerFutureSource.future;
}
#pragma mark Register device for Push Notification locally
-(TOCFuture*)registeriOS7PushNotificationFuture{
self.pushNotificationFutureSource = [TOCFutureSource new];
[UIApplication.sharedApplication registerForRemoteNotificationTypes:(UIRemoteNotificationType)[self mandatoryNotificationTypes]];
return self.pushNotificationFutureSource.future;
}
-(TOCFuture*)registerPushNotificationFuture{
self.pushNotificationFutureSource = [TOCFutureSource new];
[[UIApplication sharedApplication] registerForRemoteNotifications];
return self.pushNotificationFutureSource.future;
}
-(TOCFuture*)registerForUserNotificationsFuture{
self.userNotificationFutureSource = [TOCFutureSource new];
[UIApplication.sharedApplication registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] categories:[NSSet setWithObject:[self userNotificationsCallCategory]]]];
return self.userNotificationFutureSource.future;
}
- (void)registrationForPushWithSuccess:(void (^)())success failure:(void (^)())failure{
TOCFuture *requestPushTokenFuture;
if (SYSTEM_VERSION_LESS_THAN(_iOS_8_0)) {
requestPushTokenFuture = [self registeriOS7PushNotificationFuture];
} else{
requestPushTokenFuture = [self registerPushNotificationFuture];
}
[requestPushTokenFuture catchDo:^(id failureObj) {
failure();
if (SYSTEM_VERSION_LESS_THAN(_iOS_8_0)) {
[self.missingPermissionsAlertView show];
} else{
DDLogError(@"This should not happen on iOS8. No push token was provided");
}
}];
[requestPushTokenFuture thenDo:^(NSData* pushToken) {
TOCFuture *registerPushTokenFuture = [self registerForPushFutureWithToken:pushToken];
[registerPushTokenFuture catchDo:^(id failureObj) {
UIAlertView *failureToRegisterWithServerAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"REGISTRATION_ERROR", @"") message:NSLocalizedString(@"REGISTRATION_BODY", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil];
[failureToRegisterWithServerAlert show];
failure();
}];
[registerPushTokenFuture thenDo:^(id value) {
success();
}];
}];
}
- (void)registrationForUserNotificationWithSuccess:(void (^)())success failure:(void (^)())failure{
TOCFuture *registrerUserNotificationFuture = [self registerForUserNotificationsFuture];
[registrerUserNotificationFuture catchDo:^(id failureObj) {
[self.missingPermissionsAlertView show];
failure();
}];
[registrerUserNotificationFuture thenDo:^(id types) {
if ([self isMissingMandatoryNotificationTypes:[UIApplication.sharedApplication currentUserNotificationSettings].types]) {
[self.missingPermissionsAlertView show];
failure();
} else{
success();
}
}];
}
/**
* Token was not sucessfully register. Try again / deal with failure
*
* @param token Token to register
*/
- (void)registerFailureWithToken:(NSData*)token{
if (self.retries > 0) {
[self registerForPushWithToken:token];
self.retries--;
} else{
if (self.PushRegisteringFailureBlock) {
self.PushRegisteringFailureBlock();
self.PushRegisteringFailureBlock = nil;
}
[Environment.preferences setRevokedPushPermission:YES];
}
-(UIUserNotificationCategory*)userNotificationsCallCategory{
UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new];
action_accept.identifier = Signal_Accept_Identifier;
action_accept.title = NSLocalizedString(@"ANSWER_CALL_BUTTON_TITLE", @"");
action_accept.activationMode = UIUserNotificationActivationModeForeground;
action_accept.destructive = NO;
action_accept.authenticationRequired = NO;
UIMutableUserNotificationAction *action_decline = [UIMutableUserNotificationAction new];
action_decline.identifier = Signal_Decline_Identifier;
action_decline.title = NSLocalizedString(@"REJECT_CALL_BUTTON_TITLE", @"");
action_decline.activationMode = UIUserNotificationActivationModeBackground;
action_decline.destructive = NO;
action_decline.authenticationRequired = NO;
UIMutableUserNotificationCategory *callCategory = [UIMutableUserNotificationCategory new];
callCategory.identifier = @"Signal_IncomingCall";
[callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextMinimal];
[callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextDefault];
return callCategory;
}
-(BOOL)isMissingMandatoryNotificationTypes:(int)notificationTypes{
int mandatoryTypes = [self mandatoryNotificationTypes];
return ((mandatoryTypes & notificationTypes) == mandatoryTypes)?NO:YES;
}
-(int)allNotificationTypes{
return (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
}
-(int)mandatoryNotificationTypes{
return (UIUserNotificationTypeAlert | UIUserNotificationTypeSound);
}
@end

View File

@ -37,4 +37,5 @@
- (IBAction)answerButtonTapped;
- (IBAction)rejectButtonTapped;
@end

View File

@ -199,19 +199,16 @@
}];
[futureChallengeAcceptedSource.future thenDo:^(id value) {
[PushManager.sharedManager askForPushRegistrationWithSuccess:^{
[PushManager.sharedManager registrationWithSuccess:^{
[Environment setRegistered:YES];
[registered trySetResult:@YES];
[Environment.getCurrent.phoneDirectoryManager forceUpdate];
[self dismissView];
} failure:^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE message:REGISTER_ERROR_ALERT_VIEW_BODY delegate:nil cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS otherButtonTitles:nil, nil];
[alertView show];
_challengeButton.enabled = YES;
[_challengeActivityIndicator stopAnimating];
}];
}];
}
- (void)showViewNumber:(NSInteger)viewNumber {

View File

@ -0,0 +1,38 @@
//
// PushManagerTest.m
// Signal
//
// Created by Frederic Jacobs on 12/09/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
@interface PushManagerTest : XCTestCase
@end
@implementation PushManagerTest
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
/**
* This test verifies that the enum containing the notifications types doesn't change for iOS7 support.
*/
- (void)testNotificationTypesForiOS7 {
XCTAssert(UIRemoteNotificationTypeAlert == UIUserNotificationTypeAlert, @"iOS 7 <-> 8 compatibility");
XCTAssert(UIRemoteNotificationTypeSound == UIUserNotificationTypeSound, @"iOS 7 <-> 8 compatibility");
XCTAssert(UIRemoteNotificationTypeBadge == UIUserNotificationTypeBadge, @"iOS 7 <-> 8 compatibility");
}
@end

Binary file not shown.