When customers upload a new Application Configuration Profile to the SAP Mobile Platform server, the application has to fetch the new configuration as soon as possible.
Therefore, app developers must check whether a new ACP is available. To check it, fetch the ACP bundle ID from the server and compare it with the one previously stored on the client (if any). Whenever a new ACP version is available, the application has to download it, and pass the compressed data to the Extensibility Framework. Implement the ACP check and download logic so that it executes whenever the app is started or becomes active.
/** * Checks whether a new ACP version is available on the SMP server * @return the updated ACP bundle ID if a new ACP has been uploaded to the SMP server or nil otherwise */ -(NSString*) getUpdatedACPBundleID:(SMPAppSettings*)appSettings_in currentBundleID:(NSString*)bundleID_in { NSString* newBundleID = nil; // get current bundle name from SMP server NSError* error = nil; newBundleID = [appSettings_in getConfigProperty:@"d:CustomizationBundleId" error:&error]; if( error ) { NSLog(@"Could not fetch ACP bundle ID. %@", error.description); } else { // check whether a new ACP is available by comparing the stored bundle ID with the fetched one if ( [newBundleID isEqualToString:bundleID_in] ) { NSLog(@"No %@ ACP available on SMP server.", newBundleID ? @"" :@"new"); } else { NSLog(@"New ACP available on SMP server with ID %@. ", newBundleID); } } return newBundleID; } /** * Updates the local ACP bundle if a new version is available on the SMP server * @remark Call this whenever the application becomes active, usually after a succesful login */ -(void) fetchACPFromSMP { // initialize SMP connection SMPClientConnection* clientConn = [SMPClientConnection initializeWithAppID:self.applicationId domain:@"default" secConfiguration:self.securityConfig]; // [clientConn enableHTTP:self.enableHTTP]; [clientConn setConnectionProfileWithUrl:self.applicationUrl]; [clientConn setApplicationConnectionID:self.appConnId]; // check whether there is a new ACP on the SMP server // get application settings from SMP SMPAppSettings* appSettings = [SMPAppSettings initializeWithConnection:clientConn userName:_userName password:_pwd]; NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; //get previously stored bundle version if any NSString* currentBundleID = [userDefaults objectForKey:@"CustomizationBundleId"]; // check for new ACP version on the server NSString* newBundleID = [self getUpdatedACPBundleID:appSettings currentBundleID:currentBundleID]; if( newBundleID ) { // fetch the udpated ACP bundle NSError* error = nil; NSData* acpData = [appSettings getCustomizationResourceBundleWithCustomizationResource:newBundleID error:&error]; if( error ) { NSLog(@"Could not fetch ACP bundle. %@", error.description); } else if( acpData ) { // unzip and store ACP bundle [self storeCustomConfiguration:acpData]; // update bundle id in user defaults [userDefaults setObject:newBundleID forKey:@"CustomizationBundleId"]; [userDefaults synchronize]; } else { UIAlertView* alertView = [[[UIAlertView alloc] initWithTitle:@"Warning!" message:[NSString stringWithFormat:@"Could not get application bundle with SMP. Error:%@", [error description] ] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil] autorelease]; [self performSelectorOnMainThread:@selector(showAlertView:) withObject:alertView waitUntilDone:NO]; } } } /** * Uncompresses and stores the compressed resource payload * @remark Changes won't be reflected till the next application start. * @see loadMAFExtConfig */ - (void) storeCustomConfiguration:(NSData*)customResourceData { // write out temporary because the zipmodule works only on disk files #warning adapt compressed payload name to your app specific one NSString *tmpFilePath = [[NSTemporaryDirectory() stringByExpandingTildeInPath] stringByAppendingPathComponent:@"zippedBundle.tar"]; [customResourceData writeToFile:tmpFilePath atomically:YES]; // pass the compressed configuration data // MAF will decompress it and place it in the predefined directory [[MAFCore sharedInstance] passConfigurationBundle:tmpFilePath]; [[[[UIAlertView alloc] initWithTitle: NSLocalizedString(@"Configuration change", nil) message: NSLocalizedString(@"New configuration from SMP has been downloaded.", nil) delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil, nil] autorelease] show]; }
The new configuration is applied when the Extensibility Framework gets initialized after executing the above logic. See Loading the Library.
dispatch_queue_t ACPProvisioningQueue = dispatch_queue_create("ACPProvisioningQueue", DISPATCH_QUEUE_SERIAL); dispatch_async(ACPProvisioningQueue, ^{ [self fetchACPFromSMP]; }); dispatch_release(ACPProvisioningQueue);
GCD automatically creates an autorelease pool per queue. However, if you span a thread using NSThread, NSOperation or performSelectorInBackground, you need create an NSAutoreleasePool for that thread.
Consider using the MAF Reuse Logon Manager and the MAF Logon UI.