Was this helpful?

Deprecated

Mobile Analytics is now App Monitoring and content about Mobile Analytics is deprecated. For documentation related to these features, please see App Monitoring content, such as:

For information on migrating to App Monitoring, see Migrating from Mobile Analytics to App Monitoring.

Here's how to integrate Mobile Analytics monitoring and configuration functionality into your iOS application using the Mobile Analytics iOS SDK.

Another line.

Step 1: Sign in to Apigee Mobile Analytics

Sign in or create a new account if you do not already have one.

Step 2: Add an app

Click Add New App and give your app a name. Click Save. Mobile Analytics will generate unique identification keys for your application. The keys are: App Id, Consumer Key, and Secret Key. You'll need to use them when you initialize the SDK.

Step 3: Download the Mobile Analytics SDK 

  1. Download the Mobile Analytics iOS SDK and unzip the ZIP file. The SDK is available as a framework against which you link your application.

When you expand the ZIP file, you should see the following structure :

ApigeeMobileAnalytics_iOS-[major].[minor]                        
                        \InstaOpsSDK.framework                   
  1. The framework you will be using is the InstaOpsSDK.framework

Step 4: Add the SDK to your project

  1. In the Project Navigator, click on your project file, and then the Build Phases tab. Expand Link Binary With Libraries.
  2. Click the '+' button on the bottom of the Link Binary With Libraries dialog. Then choose Add Other.
  3. Navigate to the directory that contains InstaOpsSDK.framework, and choose the InstaOpsSDK.framework folder
  4. Add the following iOS frameworks if these are not already part of your project.
  • UIKit.framework
  • SystemConfiguration.framework
  • CoreGraphics.framework
  • CoreLocation.framework
  • CoreTelephony.framework 

In XCode, you can optionally drag InstaOpsSDK.framework into the Frameworks group created by Xcode. You can do this instead of performing steps 2, 3, 4 ..

Step 5: Change your Linker Flags

  1. In the Build Settings panel, add or modify -ObjC -value under Other Linker Flags.
  2. Double Check to make sure that flags are set for both DEBUG and RELEASE.

Step 6: Initialize the SDK

  1. Add the following line under any existing imports in your application's delegate header (the file whose default name is <YouApplication>AppDelegate.h):
      #import <InstaOpsSDK/InstaOps.h> 
    

    Then add the following property in the property section:

      @property (strong, nonatomic) InstaOpsAppMonitor *instaOpsAppMonitor;  
    
  2. Add the following line to the start of applicationDidFinishLaunching in your application's delegate header (the file which default name is <YouApplication>AppDelegate.m)
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
          self.instaOpsAppMonitor = [[InstaOpsAppMonitor alloc] 
                                      initWithAppId:@"<app_id_from_console>"
                                      consumerKey:@"<consumer_key_from_console>"
                                      secretKey:@"<secret_key_from_console>"];
          ...
    }      
    

    Replace the values while retaining the surrounding quotes for <app_id_from_console>,<consumer_key_from_console>,<secret_key_from_console> with the App IdConsumer Key and Secret Key that you copied from Step 2.

Step 7: Build and test your app

Compile your app and run it in the simulator. Go to the App Usage page and verify that a new session is detected. It will take approximately 2 minutes before the first data point appears.

Your app is now sending analytics data to the dashboard!

Optional: Log Capture

Although your app is now collecting metrics, there are additional Mobile Analytics functions that your app might want to take advantage of, such as accessing information in the error log based on log levels. Enabling this additional functionality is optional, but requires some additional code and configuration.

Adding advanced logging

The logging API is designed to allow you to capture various levels of information based on the "Log Capture Levels" configuration setting on the dashboard for your application. The levels function similarly to log levels from many of the frameworks you have likely used. Log level filtering is based on the log level you choose. Each level is inclusive of the levels below it, that is, each level includes itself and any lower level. The available levels are:

  • InstaOpsLogAssert
  • InstaOpsLogError
  • InstaOpsLogWarn
  • InstaOpsLogInfo
  • InstaOpsLogDebug
  • InstaOpsLogVerbose

For example, choosing a log level of Warn would include logging statements made at Assert, Error, and Warn levels.

Import the InstaOpsLogger.h file in your implementation. You can log in one of two ways. The easiest way is to add the following macros in any classes in your app where you want advanced logging performed:

  InstaOpsLogAssert(TAG, ...)
  InstaOpsLogError(TAG, ...)
  InstaOpsLogWarn(TAG, ...)
  InstaOpsLogInfo(TAG, ...)
  InstaOpsLogDebug(TAG, ...)
  InstaOpsLogVerbose(TAG, ...)

where TAG is the category used to identify a susbsystem or class of messages, and ... is the standard variable argument list as used in NSLog.

Example:

InstaOpsLogAssert(@"Tag", @"A message containing %d arguments: %@", 2, @"my second argument");

You can also use the Objective-c API that supports the macros. However you will not automatically get the function context. Use the Objective-c API if you don't need the calling context in your log messages. If you use the Objective-c API, add the following code to any class where you want advanced logging:

 + (InstaOpsLogger *) logger;

  ...

  - (void) assert:(NSString *) tag format:(NSString *) format, ...)
  - (void) error:(NSString *) tag format:(NSString *) format, ...)
  - (void) warn:(NSString *) tag format:(NSString *) format, ...)
  - (void) info:(NSString *) tag format:(NSString *) format, ...)
  - (void) debug:(NSString *) tag format:(NSString *) format, ...)
  - (void) verbose:(NSString *) tag format:(NSString *) format, ...)

@end

Example:

[[[InstaOpsLogger] logger] info:@"My Tag" format:@"My message constructed from %d arguments: %@", 2, @"the rest of the message"];

Optional: Network Metrics Capture

The default SDK initializer enables automatic interception of network calls for performance tracking.  This feature instruments all network calls made using NSURLConnection (directly or indirectly).  If you want to disable the automatic network instrumentation feature, simply use the alternate initializer, as follows:

 (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        iopsAppMonitor = [[InstaOpsAppMonitor alloc] initWithAppId:@"<app_id_from_console>"
                         consumerKey:@"<consumer_key_from_console>"
                         secretKey:@"<secret_key_from_console>"
                         crashReporting:YES
                         interceptNetworkCalls:NO];

Adding advanced networking

Although the SDK provides functionality (by default) to automatically capture network performance metrics for all calls made through NSURLConnection, you may decide that you want to selectively capture network performance metrics. To do this, use the InstaOps categories provided for NSString, NSData, and NSURLConnection, as well as a subclass of NSURLConnection (InstaOpsURLConnection). The overhead for recording the network latency is minimal. Timestamps are recorded for the calls, and forwarded to a background thread, which pushes the data to the portal.

InstaOpsUIWebView. The UIWebView class has been extended to measure the latency of network calls made through this control. The UIWebView delegate records the start and finish times of the request. To use the control, either:

  • Create a UIWebView instance programmatically and add it as a subview to your view controller's main view, or
  • Drag a UIWebView class into your view, go to the identity inspector, and change the class from UIWebView to InstaOpsUIWebView.

No other calls are needed. Just use the control as you normally would, and latency metrics will be pushed to your portal for calls loaded through the control.

NSString

A category is provided on NSString for methods that initialize a string from a URL, while capturing latency metrics for the underlying network calls. The following methods are available through the category:

+ (id) stringWithTimedContentsOfURL:(NSURL *) url encoding:(NSStringEncoding) enc error:(NSError **) error;
+ (id) stringWithTimedContentsOfURL:(NSURL *) url usedEncoding:(NSStringEncoding *) enc error:(NSError **) error;
- (id) initWithTimedContentsOfURL:(NSURL *) url encoding:(NSStringEncoding) enc error:(NSError **) error;
- (id) initWithTimedContentsOfURL:(NSURL *) url usedEncoding:(NSStringEncoding *) enc error:(NSError **) error;
- (BOOL) timedWriteToURL:(NSURL *) url atomically:(BOOL) useAuxiliaryFile encoding:(NSStringEncoding) enc error:(NSError **) error;

NSData

A category is provided on NSData for methods that initialize a raw data from a URL, while capturing latency metrics for the underlying network calls. The following methods are available through the category:

+ (id) timedDataWithContentsOfURL:(NSURL *) url options:(NSDataReadingOptions) readOptionsMask error:(NSError **) errorPtr;
+ (id) timedDataWithContentsOfURL:(NSURL *) url;
- (id) initWithTimedContentsOfURL:(NSURL *) url options:(NSDataReadingOptions) readOptionsMask error:(NSError **) errorPtr;
- (id) initWithTimedContentsOfURL:(NSURL *) url;
- (BOOL) timedWriteToURL:(NSURL *) url atomically:(BOOL) atomically;
- (BOOL) timedWriteToURL:(NSURL *) url options:(NSDataWritingOptions) writeOptionsMask error:(NSError **) errorPtr;

NSURLConnection

A category is provided on NSURLConnection for methods that make network requests, while capturing latency metrics for the underlying network calls. The following methods are available through the category:

+ (NSURLConnection*) timedConnectionWithRequest:(NSURLRequest *) request delegate:(id < NSURLConnectionDelegate >) delegate;
+ (NSData *) timedSendSynchronousRequest:(NSURLRequest *) request returningResponse:(NSURLResponse **) response error:(NSError **) error;
+ (void) timedSendAsynchronousRequest:(NSURLRequest *) request queue:(NSOperationQueue *) queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*)) handler;
- (id) initTimedConnectionWithRequest:(NSURLRequest *) request delegate:(id < NSURLConnectionDelegate >) delegate;
- (id) initTimedConnectionWithRequest:(NSURLRequest *) request delegate:(id < NSURLConnectionDelegate >) delegate startImmediately:(BOOL) startImmediately;

A subclass of the NSURLConnection is also provided, called InstaOpsURLConnection. As with InstaOpsUIWebView, InstaOpsURLConnection doesn't override any behavior of the parent class. Instead, it uses the NSURLConnectionDataDelegate protocol to capture metrics. The subclass calls the delegate set, just as in the case of NSURLConnection, but records information from the necessary callbacks in the protocol before forwarding the message to the original delegate. The delegate property on the subclass is optional, as with NSURLConnection. Latency metrics are captured with or without the delegate being set.

 

Optional: Refresh configuration parameters while app is running

If you'd like to refresh (re-read) your configuration parameters after your application has already been initialized and is running, you may refresh it as follows:

if ([[InstaOpsAppMonitor sharedInstance] refreshConfiguration]) {
    InstaOpsLogInfo("MY_TAG","configuration refreshed");
} else {
    InstaOpsLogInfo("MY_TAG","unable to refresh configuration");
}

This method call (refreshConfiguration) is synchronous.

Optional: Enable application-specific configuration

To access custom configuration parameters that are set in the Mobile Analytics console, obtain a reference to the InstaOpsAppMonitor instance for your application. Then loop through the following collection available through the activeSettings property:

InstaOpsAppDelegate *appDelegate = [ [UIApplication sharedApplication] delegate];
for (InstaOpsCustomConfigParam *param in appDelegate.iopsAppMonitor.activeSettings.customConfigParams)
{
NSString *paramCategory = param.category;
NSString *paramKey = param.key;
NSString *paramValue = param.value;
}
Add the code to any class in your app where you need custom configuration.

Congratulations! You are all set to use Apigee Mobile Analytics.

[Alternative Integration Approach] Adding the Mobile Analytics SDK as a static library

In XCode, you can optionally drag the library file in the Project Navigator to the group created for Mobile Analytics. You can do this instead of performing steps 5, 6, and 7.

Troubleshooting

Q: I have an HTML5 app based on a mobile development framework such as PhoneGap, Appcelerator, or Trigger.io. Is such an app supported?

A: No, apps built on an HTML5 framework are not supported at this time.

Q: My App is crashing or I get a weird "unrecongnized selector sent to class" exception. What's going on?

A: You probably did not change your linker flags as described in Step 5. Double check the linker flags to make sure that -ObjC -all_load  is set for both DEBUG and RELEASE modes. 

    1. Launch your project in Xcode.
    2. Create a group in your XCode project to contain the headers and library for Mobile Analytics..
    3. Right click the new group in your Xcode project and choose Add files to [Project Name].
    4. Navigate to the ApigeeMobileAnalytics-[major].[minor] folder on your disk and select the Headers folder (allow groups to be created for folders).
    5. In the Project Navigator, click on your project file, and then the Build Phases tab. Expand Link Binary With Libraries.
    6. Click the '+' button on the bottom of the Link Binary With Libraries dialog. Then choose Add Other. 
    7. In the Build Settings panel, add -ObjC -all_load under Other Linker Flags.

Help or comments?

  • Something's not working: See Apigee Support
  • Something's wrong with the docs: Click Send Feedback in the lower right.
    (Incorrect? Unclear? Broken link? Typo?)