Shows notification or popup when the account is about to expire.

This commit is contained in:
Simon Morlat 2016-08-12 16:14:35 +02:00
parent 6ca2279bf8
commit 6f86bc95c7
7 changed files with 112 additions and 34 deletions

View file

@ -45,6 +45,8 @@ typedef NSString *IAPPurchaseNotificationStatus;
// paid_account_id=test.autorenew_7days
// receipt_validation_url=https://www.linphone.org/inapp.php
// products_list=test.autorenew_7days
// expiry_check_period = 86400
// warn_before_expiry_period = 604800
// Note: in Sandbox mode (test), autorenewal expire time is speed up (see
// http://stackoverflow.com/questions/8815271/what-expiry-date-should-i-see-for-in-app-purchase-in-the-application-sandbox)
// so that 7 days renewal is only 3 minutes and:
@ -57,11 +59,19 @@ typedef NSString *IAPPurchaseNotificationStatus;
@interface InAppProductsManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver> {
NSString *latestReceiptMD5;
time_t lastCheck;
time_t expiryTime;
}
@property(nonatomic, strong) IAPPurchaseNotificationStatus status;
@property(nonatomic, strong) NSMutableArray *productsAvailable;
@property(nonatomic, strong) NSMutableArray *productsIDPurchased;
//Period of time between each expiration check. Default value is given in linphonerc.
@property time_t checkPeriod;
//Period of time before expiration during which we warn the user about the need to renew the account.
@property time_t warnBeforeExpiryPeriod;
//The notification category to use for displaying notification related to account expiry.
@property NSString *notificationCategory;
// TRUE when in app purchase capability is available - not modified during runtime
@property(readonly) BOOL enabled;
@ -92,6 +102,9 @@ typedef NSString *IAPPurchaseNotificationStatus;
// Warning: on first run, this will open a popup to user to provide iTunes Store credentials
- (BOOL)retrievePurchases;
//Check if account is about to expire, and if yes launch a notification.
- (void)check;
// internal API only due to methods conflict
- (void)XMLRPCRequest:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response;
// internal API only due to methods conflict

View file

@ -18,6 +18,7 @@
*/
#import "InAppProductsManager.h"
#import "ShopView.h"
// In app purchase are not supported by the Simulator
#import <XMLRPCConnection.h>
@ -36,8 +37,14 @@
@property(nonatomic, strong) InAppProductsXMLRPCDelegate *xmlrpc;
@end
@implementation InAppProductsManager
@synthesize checkPeriod;
@synthesize warnBeforeExpiryPeriod;
@synthesize notificationCategory;
// LINPHONE_CAPABILITY_INAPP_PURCHASE must be defined in Linphone Build Settings
#if 1
@ -48,6 +55,14 @@
_initialized = false;
_available = false;
_accountActivationInProgress = false;
checkPeriod = [LinphoneManager.instance lpConfigIntForKey:@"expiry_check_period" inSection:@"in_app_purchase"];
warnBeforeExpiryPeriod = [LinphoneManager.instance lpConfigIntForKey:@"warn_before_expiry_period" inSection:@"in_app_purchase"];
lastCheck = 0;
int testExpiry = [LinphoneManager.instance lpConfigIntForKey:@"expiry_time_test" inSection:@"in_app_purchase"];
if (testExpiry > 0){
expiryTime = time(NULL) + testExpiry;
}else expiryTime = 0;
if (_enabled) {
self.xmlrpc = [[InAppProductsXMLRPCDelegate alloc] init];
_status = kIAPNotReady;
@ -301,13 +316,9 @@
NSString *phoneNumber = @"";
LinphoneProxyConfig *config = linphone_core_get_default_proxy_config(LC);
if (config) {
const char *identity = linphone_proxy_config_get_identity(config);
const LinphoneAddress *identity = linphone_proxy_config_get_identity_address(config);
if (identity) {
LinphoneAddress *addr = linphone_core_interpret_url(LC, identity);
if (addr) {
phoneNumber = [NSString stringWithUTF8String:linphone_address_get_username(addr)];
linphone_address_destroy(addr);
}
phoneNumber = [NSString stringWithUTF8String:linphone_address_get_username(identity)];
}
}
return phoneNumber;
@ -476,6 +487,64 @@
NSDictionary *dict = @{ @"error_msg" : errorString };
[self postNotificationforStatus:kIAPReceiptFailed withDict:dict];
}
- (void) presentNotification:(int64_t) remaining{
if (notificationCategory == nil) return;
int days = (int)remaining / (3600 * 24);
NSString * expireText;
if (remaining >= 0){
expireText = [NSString stringWithFormat:NSLocalizedString(@"Your account will expire in %i days.", nil), days];
}else{
expireText = [NSString stringWithFormat:NSLocalizedString(@"Your account has expired.", nil), days];
}
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground){
UILocalNotification *notification = [[UILocalNotification alloc] init];
if (notification) {
notification.category = notificationCategory;
notification.repeatInterval = 0;
notification.applicationIconBadgeNumber = 1;
notification.alertBody = expireText;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
}else{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Account expiring"
message:expireText
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* buyAction = [UIAlertAction actionWithTitle:@"Buy" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[PhoneMainView.instance changeCurrentView:ShopView.compositeViewDescription];
}];
UIAlertAction* laterAction = [UIAlertAction actionWithTitle:@"Later" style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
// [alert dismissViewControllerAnimated:FALSE];
}];
[alert addAction:buyAction];
[alert addAction:laterAction];
[PhoneMainView.instance presentViewController:alert animated:YES completion:nil];
}
}
- (void) check{
if (!_available) return;
if (expiryTime == 0 || checkPeriod == 0) return;
time_t now = time(NULL);
if (now < lastCheck + checkPeriod) return;
if (now >= expiryTime - warnBeforeExpiryPeriod){
lastCheck = now;
int64_t remaining = (int64_t)expiryTime - (int64_t)now;
[self presentNotification: remaining];
}
}
#else
- (void)postNotificationforStatus:(IAPPurchaseNotificationStatus)status {
_status = status;

View file

@ -18,6 +18,7 @@
*/
#import "PhoneMainView.h"
#import "ShopView.h"
#import "linphoneAppDelegate.h"
#import "AddressBook/ABPerson.h"
@ -99,6 +100,7 @@
[self fixRing];
}
}
[LinphoneManager.instance.iapManager check];
}
#pragma deploymate push "ignored-api-availability"
@ -170,6 +172,14 @@
return localRingNotifAction;
}
- (UIUserNotificationCategory *)getAccountExpiryNotificationCategory {
UIMutableUserNotificationCategory *expiryNotification = [[UIMutableUserNotificationCategory alloc] init];
expiryNotification.identifier = @"expiry_notification";
return expiryNotification;
}
- (void)registerForNotifications:(UIApplication *)app {
LinphoneManager *instance = [LinphoneManager instance];
@ -179,7 +189,7 @@
UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
NSSet *categories =
[NSSet setWithObjects:[self getCallNotificationCategory], [self getMessageNotificationCategory], nil];
[NSSet setWithObjects:[self getCallNotificationCategory], [self getMessageNotificationCategory], [self getAccountExpiryNotificationCategory], nil];
UIUserNotificationSettings *userSettings =
[UIUserNotificationSettings settingsForTypes:notifTypes categories:categories];
[app registerUserNotificationSettings:userSettings];
@ -224,6 +234,7 @@
}];
[LinphoneManager.instance startLinphoneCore];
LinphoneManager.instance.iapManager.notificationCategory = @"expiry_notification";
// initialize UI
[self.window makeKeyAndVisible];
[RootViewManager setupWithPortrait:(PhoneMainView *)self.window.rootViewController];
@ -357,6 +368,11 @@
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
LOGI(@"%@ - state = %ld", NSStringFromSelector(_cmd), (long)application.applicationState);
if ([notification.category isEqual:LinphoneManager.instance.iapManager.notificationCategory]){
[PhoneMainView.instance changeCurrentView:ShopView.compositeViewDescription];
return;
}
[self fixRing];

View file

@ -1741,6 +1741,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
LOGW(@"It seems that Linphone BG mode was deactivated, just skipping");
return;
}
[_iapManager check];
// kick up network cnx, just in case
[self refreshRegisters];
linphone_core_iterate(theLinphoneCore);
@ -2396,7 +2397,7 @@ static int comp_call_state_paused(const LinphoneCall *call, const void *param) {
- (void)inappReady:(NSNotification *)notif {
// Query our in-app server to retrieve InApp purchases
[_iapManager retrievePurchases];
//[_iapManager retrievePurchases];
}
#pragma mark -

View file

@ -1,23 +0,0 @@
//
// RenewalManager.h
// linphone
//
// Created by Simon Morlat on 11/08/2016.
//
//
#ifndef RenewalManager_h
#define RenewalManager_h
@interface RenewalManager : NSObject {
@protected
@private
@public
}
#endif /* RenewalManager_h */

View file

@ -34,4 +34,8 @@ display_filter_auto_rotate=0
enabled=1
paid_account_id=sipAccount_12m
receipt_validation_url=https://www.linphone.org/inapp.php
products_list=sipAccount_12m
products_list=sipAccount_12m
expiry_check_period=30
warn_before_expiry_period=160
expiry_time_test=180

View file

@ -943,7 +943,6 @@
570742631D5A1860004B9C84 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ShopView.strings; sourceTree = "<group>"; };
570742651D5A1868004B9C84 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/ShopView.strings; sourceTree = "<group>"; };
570742661D5A63DB004B9C84 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
570742681D5C852B004B9C84 /* RenewalManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenewalManager.h; sourceTree = "<group>"; };
630589DE1B4E810900EFAE36 /* ChatTester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChatTester.h; sourceTree = "<group>"; };
630589DF1B4E810900EFAE36 /* ChatTester.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChatTester.m; sourceTree = "<group>"; };
630589E01B4E810900EFAE36 /* ContactsTester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsTester.h; sourceTree = "<group>"; };
@ -2053,7 +2052,6 @@
D326483415887D4400930C67 /* Utils */,
34216F3E1547EBCD00EA9777 /* VideoZoomHandler.h */,
34216F3F1547EBCD00EA9777 /* VideoZoomHandler.m */,
570742681D5C852B004B9C84 /* RenewalManager.h */,
);
path = Classes;
sourceTree = "<group>";