From 9c1eb3335a5a70b4b1a5ddf882e09986d25a68d4 Mon Sep 17 00:00:00 2001 From: Gautier Pelloux-Prayer Date: Wed, 15 Apr 2015 12:53:57 +0200 Subject: [PATCH] InAppProducts: add in app feature --- Classes/InAppProductsManager.h | 27 ++++++++++++ Classes/InAppProductsManager.m | 66 ++++++++++++++++++++++++++++++ Classes/LinphoneManager.h | 3 +- Classes/LinphoneManager.m | 25 +++++------ in_app_products.plist | 7 ++++ linphone.xcodeproj/project.pbxproj | 43 +++++++++++++++---- 6 files changed, 150 insertions(+), 21 deletions(-) create mode 100644 Classes/InAppProductsManager.h create mode 100644 Classes/InAppProductsManager.m create mode 100644 in_app_products.plist diff --git a/Classes/InAppProductsManager.h b/Classes/InAppProductsManager.h new file mode 100644 index 000000000..e5a3c369e --- /dev/null +++ b/Classes/InAppProductsManager.h @@ -0,0 +1,27 @@ +/* InAppProductsManager.h + * + * Copyright (C) 2012 Belledonne Comunications, Grenoble, France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import +#import + +@interface InAppProductsManager : NSObject { + NSArray *inAppProducts; +} + +@end diff --git a/Classes/InAppProductsManager.m b/Classes/InAppProductsManager.m new file mode 100644 index 000000000..9bcc0a40b --- /dev/null +++ b/Classes/InAppProductsManager.m @@ -0,0 +1,66 @@ +/* InAppProductsManager.h + * + * Copyright (C) 2012 Belledonne Comunications, Grenoble, France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import "InAppProductsManager.h" +#import "Utils.h" + +@implementation InAppProductsManager { + bool ready; +} + +- (instancetype)init { + if ((self = [super init]) != nil) { + [self loadProducts]; + ready = false; + } + return self; +} + +- (void)loadProducts { + if (! [SKPaymentQueue canMakePayments]) { + return; + } + + NSURL *url = [[NSBundle mainBundle] URLForResource:@"in_app_products" + withExtension:@"plist"]; + + inAppProducts = [NSArray arrayWithContentsOfURL:url]; + + SKProductsRequest *productsRequest = [[SKProductsRequest alloc] + initWithProductIdentifiers:[NSSet setWithArray:inAppProducts]]; + productsRequest.delegate = self; + [productsRequest start]; +} + +- (void)productsRequest:(SKProductsRequest *)request + didReceiveResponse:(SKProductsResponse *)response { + inAppProducts = response.products; + LOGI(@"Found %lu products purchasable", inAppProducts.count); + + for (NSString *invalidIdentifier in response.invalidProductIdentifiers) { + LOGE(@"Product Identifier with invalid ID %@", invalidIdentifier); + } + ready = true; +} + +- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { + +} + +@end \ No newline at end of file diff --git a/Classes/LinphoneManager.h b/Classes/LinphoneManager.h index daa3c4779..f2fc082c0 100644 --- a/Classes/LinphoneManager.h +++ b/Classes/LinphoneManager.h @@ -31,6 +31,7 @@ #import "IASKAppSettingsViewController.h" #import "FastAddressBook.h" #import "Utils.h" +#import "InAppProductsManager.h" #include "linphone/linphonecore.h" #include "linphone/linphone_tunnel.h" @@ -202,6 +203,6 @@ typedef struct _LinphoneManagerSounds { @property (copy) void (^silentPushCompletion)(UIBackgroundFetchResult); @property (readonly) BOOL wasRemoteProvisioned; @property (readonly) LpConfig *configDb; - +@property (readonly) InAppProductsManager *iapManager; @end diff --git a/Classes/LinphoneManager.m b/Classes/LinphoneManager.m index 2f5606027..b5cd31873 100644 --- a/Classes/LinphoneManager.m +++ b/Classes/LinphoneManager.m @@ -466,7 +466,7 @@ exit_dbmigration: if( configDb == nil ) return; if( lp_config_get_int(configDb, LINPHONERC_APPLICATION_KEY, migration_flag, 0) ){ - Linphone_log(@"UserPrefs migration already performed, skip"); + LOGI(@"UserPrefs migration already performed, skip"); return; } @@ -477,11 +477,11 @@ exit_dbmigration: @"start_at_boot_preference" :@YES}; BOOL shouldSync = FALSE; - Linphone_log(@"%lu user prefs", (unsigned long)[defaults_keys count]); + LOGI(@"%lu user prefs", (unsigned long)[defaults_keys count]); for( NSString* userpref in values ){ if( [defaults_keys containsObject:userpref] ){ - Linphone_log(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]); + LOGI(@"Migrating %@ from user preferences: %d", userpref, [[defaults objectForKey:userpref] boolValue]); lp_config_set_int(configDb, LINPHONERC_APPLICATION_KEY, [userpref UTF8String], [[defaults objectForKey:userpref] boolValue]); [[NSUserDefaults standardUserDefaults] removeObjectForKey:userpref]; shouldSync = TRUE; @@ -492,7 +492,7 @@ exit_dbmigration: } if( shouldSync ){ - Linphone_log(@"Synchronizing..."); + LOGI(@"Synchronizing..."); [[NSUserDefaults standardUserDefaults] synchronize]; } // don't get back here in the future @@ -985,7 +985,7 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat + (void)kickOffNetworkConnection { static BOOL in_progress = FALSE; if( in_progress ){ - Linphone_warn(@"Connection kickoff already in progress"); + LOGW(@"Connection kickoff already in progress"); return; } in_progress = TRUE; @@ -1003,7 +1003,7 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat time_t loop_time; if( res == FALSE ){ - Linphone_log(@"Could not open write stream, backing off"); + LOGI(@"Could not open write stream, backing off"); CFRelease(writeStream); in_progress = FALSE; return; @@ -1027,10 +1027,10 @@ static void linphone_iphone_is_composing_received(LinphoneCore *lc, LinphoneChat CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff)); } else if( !timeout_reached ){ CFErrorRef error = CFWriteStreamCopyError(writeStream); - Linphone_dbg(@"CFStreamError: %@", error); + LOGD(@"CFStreamError: %@", error); CFRelease(error); } else if( timeout_reached ){ - Linphone_log(@"CFStream timeout reached"); + LOGI(@"CFStream timeout reached"); } CFWriteStreamClose (writeStream); CFRelease(writeStream); @@ -1283,6 +1283,7 @@ static LinphoneCoreVTable linphonec_vtable = { [_contactSipField release]; _contactSipField = [[self lpConfigStringForKey:@"contact_im_type_value" withDefault:@"SIP"] retain]; + _iapManager = [[InAppProductsManager alloc] init]; fastAddressBook = [[FastAddressBook alloc] init]; @@ -1313,7 +1314,7 @@ static LinphoneCoreVTable linphonec_vtable = { const char* addr = linphone_proxy_config_get_addr(proxy); // we want to enable AVPF for the proxies if( addr && strstr(addr, "sip.linphone.org") != 0 ){ - Linphone_log(@"Migrating proxy config to use AVPF"); + LOGI(@"Migrating proxy config to use AVPF"); linphone_proxy_config_enable_avpf(proxy, TRUE); } proxies = proxies->next; @@ -1328,7 +1329,7 @@ static LinphoneCoreVTable linphonec_vtable = { const char* addr = linphone_proxy_config_get_addr(proxy); // we want to enable quality reporting for the proxies that are on linphone.org if( addr && strstr(addr, "sip.linphone.org") != 0 ){ - Linphone_log(@"Migrating proxy config to send quality report"); + LOGI(@"Migrating proxy config to send quality report"); linphone_proxy_config_set_quality_reporting_collector(proxy, "sip:voip-metrics@sip.linphone.org"); linphone_proxy_config_set_quality_reporting_interval(proxy, 180); linphone_proxy_config_enable_quality_reporting(proxy, TRUE); @@ -1560,7 +1561,7 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) { //first, make sure this callid is not already involved in a call MSList* calls = (MSList*)linphone_core_get_calls(theLinphoneCore); if (ms_list_find_custom(calls, (MSCompareFunc)comp_call_id, [callid UTF8String])) { - Linphone_warn(@"Call id [%@] already handled",callid); + LOGW(@"Call id [%@] already handled",callid); return; }; if ([pushCallIDs count] > 10 /*max number of pending notif*/) @@ -1588,7 +1589,7 @@ static int comp_call_id(const LinphoneCall* call , const char *callid) { - (void)playMessageSound { BOOL success = [self.messagePlayer play]; if( !success ){ - Linphone_err(@"Could not play the message sound"); + LOGE(@"Could not play the message sound"); } AudioServicesPlaySystemSound([LinphoneManager instance].sounds.vibrate); } diff --git a/in_app_products.plist b/in_app_products.plist new file mode 100644 index 000000000..d269bc27a --- /dev/null +++ b/in_app_products.plist @@ -0,0 +1,7 @@ + + + + + test.tunnel + + diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj index b5be344a4..dce290b01 100755 --- a/linphone.xcodeproj/project.pbxproj +++ b/linphone.xcodeproj/project.pbxproj @@ -122,6 +122,9 @@ 639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB081A1DF4F1004DE38F /* UIChatRoomCell.xib */; }; 639CEB091A1DF4FA004DE38F /* UIChatCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */; }; 63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */; }; + 63E59A3A1ADE6A0100646FB3 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E59A391ADE6A0100646FB3 /* StoreKit.framework */; }; + 63E59A3C1ADE6E5C00646FB3 /* in_app_products.plist in Resources */ = {isa = PBXBuildFile; fileRef = 63E59A3B1ADE6E5C00646FB3 /* in_app_products.plist */; }; + 63E59A3F1ADE70D900646FB3 /* InAppProductsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */; }; 63FB30351A680E73008CA393 /* UIRoundedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FB30341A680E73008CA393 /* UIRoundedImageView.m */; }; 70571E1A13FABCB000CDD3C2 /* rootca.pem in Resources */ = {isa = PBXBuildFile; fileRef = 70571E1913FABCB000CDD3C2 /* rootca.pem */; }; 7066FC0C13E830E400EFC6DC /* libvpx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7066FC0B13E830E400EFC6DC /* libvpx.a */; }; @@ -1036,6 +1039,10 @@ 639CEB0D1A1DF52C004DE38F /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/UICallCell.strings; sourceTree = ""; }; 63CD4B4D1A5AAC8C00B84282 /* DTAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAlertView.h; sourceTree = ""; }; 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTAlertView.m; sourceTree = ""; }; + 63E59A391ADE6A0100646FB3 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + 63E59A3B1ADE6E5C00646FB3 /* in_app_products.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = in_app_products.plist; sourceTree = ""; }; + 63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsManager.h; sourceTree = ""; }; + 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsManager.m; sourceTree = ""; }; 63EF7FDC1A24B5810017A416 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/AboutViewController.strings; sourceTree = ""; }; 63FB30331A680E73008CA393 /* UIRoundedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIRoundedImageView.h; sourceTree = ""; }; 63FB30341A680E73008CA393 /* UIRoundedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIRoundedImageView.m; sourceTree = ""; }; @@ -1893,6 +1900,7 @@ D37EE10916032DA4003608A6 /* libmediastreamer_base.a in Frameworks */, D37EE10A16032DA4003608A6 /* libmediastreamer_voip.a in Frameworks */, 226F2ED81344B0EF00F6EF27 /* libmsamr.a in Frameworks */, + 63E59A3A1ADE6A0100646FB3 /* StoreKit.framework in Frameworks */, 223148E61178A09900637D6A /* libmsilbc.a in Frameworks */, 226183B0147259670037138E /* libmssilk.a in Frameworks */, 22AA8AFE13D7125600B30535 /* libmsx264.a in Frameworks */, @@ -2035,6 +2043,8 @@ 22405EFD1601C19000B92522 /* ImageViewController.h */, 22405EFE1601C19100B92522 /* ImageViewController.m */, D37EE11016035793003608A6 /* ImageViewController.xib */, + 63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */, + 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */, D31AAF5C159B3919002C6B02 /* InCallTableViewController.h */, D31AAF5D159B3919002C6B02 /* InCallTableViewController.m */, D3F83EE91582021700336684 /* InCallViewController.h */, @@ -2230,6 +2240,7 @@ F0B89C2518DC973E0050B60E /* wizard_linphone_create.rc */, F0B89C2618DC973E0050B60E /* wizard_linphone_existing.rc */, F0B89C2718DC973E0050B60E /* wizard_remote.rc */, + 63E59A3B1ADE6E5C00646FB3 /* in_app_products.plist */, ); name = Resources; sourceTree = ""; @@ -2237,6 +2248,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 63E59A391ADE6A0100646FB3 /* StoreKit.framework */, F0FF66AA1ACAEEB0008A4486 /* IOKit.framework */, F0B026F21AA710AF00FF49F7 /* libiconv.dylib */, F05BAA611A5D594E00411815 /* libz.dylib */, @@ -3184,6 +3196,11 @@ TargetAttributes = { 1D6058900D05DD3D006BFB54 = { DevelopmentTeam = Z2V957B3D6; + SystemCapabilities = { + com.apple.InAppPurchase = { + enabled = 1; + }; + }; }; F08F118319C09C6A007D70C2 = { DevelopmentTeam = Z2V957B3D6; @@ -3351,6 +3368,7 @@ D3F83F5A1582223B00336684 /* numpad_five_over.png in Resources */, D3F83F5C1582223B00336684 /* numpad_six_default.png in Resources */, 636316D91A1DECC90009B839 /* PhoneMainView.xib in Resources */, + 63E59A3C1ADE6E5C00646FB3 /* in_app_products.plist in Resources */, D3F83F5E1582223B00336684 /* numpad_six_over.png in Resources */, D3F83F601582223B00336684 /* numpad_seven_default.png in Resources */, D3F83F621582223B00336684 /* numpad_seven_over.png in Resources */, @@ -3993,6 +4011,7 @@ D37C639515AADDAF009D0BAC /* UIContactDetailsHeader.m in Sources */, D37C639B15AADEF6009D0BAC /* ContactDetailsTableViewController.m in Sources */, 636316DE1A1DEF2F0009B839 /* UIButtonShrinkable.m in Sources */, + 63E59A3F1ADE70D900646FB3 /* InAppProductsManager.m in Sources */, D3C6526715AC1A8F0092A874 /* UIEditableTableViewCell.m in Sources */, D378906515AC373B00BD776C /* ContactDetailsLabelViewController.m in Sources */, D3E8F68615ADE05B0065A226 /* UIContactDetailsFooter.m in Sources */, @@ -4515,6 +4534,7 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_UNREACHABLE_CODE = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COMPRESS_PNG_FILES = NO; @@ -4533,7 +4553,8 @@ DEBUG, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/liblinphone-sdk/apple-darwin/include", "$(SRCROOT)/Classes/Utils/NinePatch/", @@ -4599,9 +4620,10 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_UNREACHABLE_CODE = NO; CODE_SIGN_ENTITLEMENTS = ""; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COMPRESS_PNG_FILES = NO; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ""; @@ -4617,7 +4639,8 @@ HAVE_OPENH264, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/liblinphone-sdk/apple-darwin/include", "$(SRCROOT)/Classes/Utils/NinePatch/", @@ -4683,6 +4706,7 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_UNREACHABLE_CODE = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COMPRESS_PNG_FILES = NO; @@ -4699,7 +4723,8 @@ HAVE_SSL, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/liblinphone-sdk/apple-darwin/include", "$(SRCROOT)/Classes/Utils/NinePatch/", @@ -4765,9 +4790,10 @@ ARCHS = "$(ARCHS_STANDARD)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_UNREACHABLE_CODE = NO; CODE_SIGN_ENTITLEMENTS = ""; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COMPRESS_PNG_FILES = NO; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ""; @@ -4782,7 +4808,8 @@ HAVE_SSL, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( "$(SRCROOT)/liblinphone-sdk/apple-darwin/include", "$(SRCROOT)/Classes/Utils/NinePatch/",