Viewing the SUP101Appdelegate Files

The SUP101Appdelegate.h and SUP101Appdelegate.m files are created when you create the Xcode project; however, you deleted the automatically generated versions and replaced them with the ones added from the source code ZIP file.

The SUP101Appdelegate files make use of the SUPApplication and SUPDataVault APIs to show how to store and retrieve sensitive data (such as Sybase Unwired Platform credentials) using a PIN.

The applicationDidFinishLaunching method checks to see if the application has been run before, then prompts the device user for a PIN to unlock the application; the Sybase Unwired Platform user's password is also requested.

Control passes to the initializeSUP101 method. This code sample does one of two things, depending on whether the application has been run before:

SUPDataVault *sup101vault = nil;
SUPDataVault *messagingvault = nil;

// Make sure to set the application identifier same as the project name. This is case sensetive.
// Setting the identifer first is essential to getting any information from the SUPApplication class
// about registration, connection and context.

SUPApplication* app = [SUPApplication getInstance];
if (!SUPApplication.applicationIdentifier)
{
app.applicationIdentifier = @"SUP101";
}

if(self.firstRun)
{
NSLog(@"Running the app for the first time.");



// If the application is being run for the first time, we do the following:
// 1. Remove the messaging data vault created by earlier versions of the application, if it exists.
// 2. Remove the SUP101 data vault created by earlier versions of the application, if it exists.
// 3. Create the messaging vault using the PIN as the password, leaving it unlocked for use by the messaging layer.
// 4. Create the SUP101 data vault using the PIN as the password, and store the SUP username/password credentials 
// and a database encryption key in the vault.
// 
@try
{ 
NSLog(@"Delete preexisting messaging vault");
[SUPDataVault deleteVault:kMessagingDataVaultID];
}
@catch(NSException *e)
{ 
// Ignore any exception
}
@try {
NSLog(@"Delete preexisting SUP101 data vault");
[SUPDataVault deleteVault:kSUP101DataVaultID];
}
@catch(NSException *e)
{ 
// Ignore any exception
}

@try {
NSLog(@"Create new SUP101 data vault and store credentials and a generated encryption key");
sup101vault = [SUPDataVault createVault:kSUP101DataVaultID withPassword:self.pin withSalt:kSUP101DataVaultSalt]; // creates the vault
[sup101vault setString:@"password" withValue:self.password];
if (![sup101vault isLocked])
{
[sup101vault lock];
}
}
@catch (NSException *exception) {
NSLog(@"Exception in creating new SUP101 data vault: %@: %@",[exception name], [exception reason]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}
@try {
NSLog(@"Create new messaging vault and leave it unlocked");
messagingvault = [SUPDataVault createVault:kMessagingDataVaultID withPassword:self.pin withSalt:kDVStandardSalt];
}
@catch (NSException *exception) {
NSLog(@"Exception in creating new messaging data vault: %@: %@",[exception name], [exception reason]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}

}
else
{
// If the application has been run before, we get the PIN from the user, and use it to unlock the existing messaging data vault
// (otherwise the messaging layer cannot start).
NSLog(@"App has been run before.");
@try {
NSLog(@"Unlock messaging vault");
messagingvault = [SUPDataVault getVault:kMessagingDataVaultID];
if ([messagingvault isLocked])
{
[messagingvault unlock:self.pin withSalt:kDVStandardSalt];
}
}
@catch (NSException *exception) {
NSLog(@"Exception unlocking messaging data vault: %@: %@",[exception name],[exception reason]);
[self showNoTransportAlert:kSUP101ErrorBadPin];
return;
}

}

This code sample sets up the notification observers and the Application API settings for connection to the Unwired Server and registers with the Unwired Server.

// Add the observer to listen for ON_REGISTER_SUCCESS or ON_CONNECT_SUCCESS if its the first run or
// subsequent runs respectively.Refer the comments in registerObserverForCallbackNotifications.
// The observer must be added before the call to registerApplication, but after applicationIdentifier is
// set and the messaging vault unlocked. (AppIdentifier being set and vault being unlocked are prerequisites to
// calling [SUPApplication isRegistered]which is used in registerObserverForCallbackNotifications.
UIViewController *sController = [self.navController visibleViewController];

if ([sController respondsToSelector:@selector(registerObserverForCallbackNotifications)])
{
[sController performSelector:@selector(registerObserverForCallbackNotifications)];
}


// When we get a connection failure or a registeration failure, the callbacks are triggered, which then send out the
// appropriate notifications. Register the observers here to handle the notifications.
// See onFailure: for more information on handling these failures..
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFailure:) name:ON_REGISTER_FAILURE object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFailure:) name:ON_CONNECT_FAILURE object:nil];


@try {
sup101vault = [SUPDataVault getVault:kSUP101DataVaultID];
if ([sup101vault isLocked])
{
[sup101vault unlock:self.pin withSalt:kSUP101DataVaultSalt];
}

// Register callback handlers. This should be done before any other SUP code is called.
[SUP101SUP101DB registerCallbackHandler:[CallbackHandler getInstance]];
[app setApplicationCallback:[ApplicationCallbackHandler getInstance]];


// Setup the connection properties and login credentials required for registration.
SUPConnectionProperties* props = app.connectionProperties;
[props setServerName:self.serverName];
[props setPortNumber:[self.serverPort intValue]];
[props setUrlSuffix:@""];
[props setFarmId:self.farmID];

SUPLoginCredentials* login = [SUPLoginCredentials getInstance];
if(self.manualRegistration)
{
login.username = self.connectionName;
login.password = nil;
props.activationCode = self.activationCode;
}
else
{
login.username = self.userName;
login.password = [sup101vault getString:@"password"];
props.activationCode = nil;
}
props.loginCredentials = login;

// Get the connection profile for the database.
SUPConnectionProfile *cp = [SUP101SUP101DB getConnectionProfile];
[cp enableTrace:NO];

// Delete any existing database from previous versions.
if(self.firstRun && [SUP101SUP101DB databaseExists])
{
[SUP101SUP101DB deleteDatabase];
}


// Create the database if required and set the encryption key.
if(![SUP101SUP101DB databaseExists])
{
[SUP101SUP101DB createDatabase];
// We need to generate a new encryption key to encrypt the DB
[SUP101SUP101DB generateEncryptionKey];
// Store the encryption key in the data vault for future use.
SUPConnectionProfile *cp = [SUP101SUP101DB getConnectionProfile];
[sup101vault setString:@"encryptionkey" withValue:[cp getEncryptionKey]];
}
else
{
// When we are create the database from scratch, we set the database encryption key in generateEncryptionKey.
// If we were using the database from a previous run of the app and not creating it each time, an application should
// run the code below instead to successfully access a previously encrypted database by retrieving the encryption key
// from the datavault and setting it in the connection profile.
NSString *key = [sup101vault getString:@"encryptionkey"];
NSLog(@"Got the encryption key: %@",key);
[cp setEncryptionKey:key];
}

// Set the synchronization configuration required to sync with the server.
SUPConnectionProfile *sp = [SUP101SUP101DB getSynchronizationProfile];
[sp setDomainName:@"default"];
[sp enableTrace:YES];
// by default the AsyncReplay is enabled. We will turn it off. This will make the next syncrhonization a blocking call.
[sp setAsyncReplay:NO];
[sp setUser:self.userName];
[sp setPassword:[sup101vault getString:@"password"]];


}
@catch (SUPPersistenceException * pe) {
NSLog(@"%@: %@", [pe name],[pe message]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}
@catch (NSException* e) {
NSLog(@"%@: %@", [e name],[e reason]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}
@finally
{
if (![sup101vault isLocked])
{
[sup101vault lock];
}
}

@try {
// Initialize generated package database class with this application instance.
[SUP101SUP101DB setApplication:app];

// Register the application with the server.
[app registerApplication:100];

// Update the value of self.firstRun, We have created the vault and registered with server at this point.
self.firstRun = (![MessagingClientLib isMessagingDBExist] ||
![SUPDataVault vaultExists:kSUP101DataVaultID]);

}
@catch (SUPApplicationTimeoutException* tex)
{
NSLog(@"%@: %@", [tex name],[tex message]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}
@catch (NSException *e)
{
// When we are faced with a registeration error or connection error, the 'onRegistrationStatusChanged'
// or on 'onConnectionStatusChanged' callbacks are triggered in which we send the ON_CONNECT_FAILURE
// notification or the ON_REGISTER_FAILURE notification to handle it
// and show the alert window to the user.So we don't have to do it again here.
// For all other failures, other than the timeout exception above , we will handle it here.
if ([SUPApplication registrationStatus] == SUPRegistrationStatus_REGISTRATION_ERROR)
{
return;
}
if ([SUPApplication connectionStatus] == SUPConnectionStatus_CONNECTION_ERROR)
{
return;
}

NSLog(@"%@: %@", [e name],[e reason]);
[self showNoTransportAlert:kSUP101ErrorFailure];
return;
}

On the first run, the onRegistrationStatusChanged method in the callback handler posts an ON_REGISTER_SUCCESS notification. For subsequent runs, the onConnectionStatusChanged method in the callback handler posts an ON_CONNECT_SUCCESS notification. Both notifications are mapped to SUP101AppDelegate's onConnectSuccess method. This method enables the synchronize button on screen.

If you are connecting to the Unwired Server through a Relay Server, then you must provide additional information for the database synchronization profile: