Introduction
The embedded agent is a bridge between your mobile application and the App47 service. It provides an easy to use API for recording session times, log messages and performance events. Once you've added your iOS App to the App47 Dashboard, be sure to record the App ID as it will be used to configure the agent after installation.
iOS Agent Version 4
Download the iOS Embedded Agent, install and configure it in your iOS mobile App.
Note: If you are using a version prior to 4.0, please consult the iOS Agent 2.X or legacy page for additional information. Please upgrade at your earliest convenience to the latest iOS agent.
Required steps:
- Download the embedded agent
- Include agent framework in your project (either directly or using CocoaPods)
- Configure the embedded agent
Optional steps:
- Update other Agent Configuration Settings on Server
- Add Crash Log Management
- Add logging statements to capture both debug and error conditions
- Add timed events to capture performance data
- Add generic events to capture user behavior
- Using configuration groups
All of the steps above are further explained in the corresponding sections below.
The Required Steps -- Explained
1. Download the embedded agent
- Download the embedded agent compressed disk image (DMG file) from the App47 Resource center.
- When the download is complete, open the DMG file and you should see the following files:
File descriptions
File | Description | Required? |
---|---|---|
EmbeddedAgent.Framework | Multi platform framework for the App47 service. | Yes |
EmbeddedAgentSettings.plist | Optional way to set application ID | No |
apache_license.txt | License software for the EmbeddedAgent.framework | No |
pl_crash_reporter_license.txt | License file for the PL Crash Reporter | No |
2. Include embedded agent framework in your project
To Include the Agent Directly
- Add the EmbeddedAgent.Framework to you project.
- Click on the Main Project navigation tree, and then on the application's target.
- In the general tab you will find a section called Embedded Binaries near the bottom. Drag the framework to this location.
- Once you drop the framework in this area, you will be prompted with the following dialog:
- Click on the Finish button. your General tab should now have the framework included in the Embedded Binaries and Linked Frameworks and in Libraries.
Using the Agent via CocoaPods
The Agent can also be installed using CocoaPods instead of directly adding the framework to your project.
- Assuming that you have CocoaPods installed you can add the Agent to your project by adding a Podfile in the Xcode project directory.
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0' target 'MyApp' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
source 'https://github.com/App47/PodSpecs.git'
source 'https://github.com/CocoaPods/Specs.git' # Pods for MyApp
pod 'EmbeddedAgent' end
- You then need to install the pod by using:
$ pod install
- You now need to use the Xcode workspace instead of the project file to build your project.
Using the Agent from Swift
The Agent is written in Objective-C, so to use from a Swift application you will need to first create a bridging header for the project. Xcode will do this for you after you have added the framework to your project but you need to add an Objective-C file to the project temporarily.
- Right-click on your Project and select New File... From the template chooser select an Objective-C file:
- Name the file anything as you will delete it soon, and finish creating the file. Xcode will then prompt to create the bridging header:
- Select Create Bridging Header and the file will be created and added to the project named AppName-Bridging-Header.h. Now you can delete and move to trash the .m file that you created.
3. Configure the embedded agent
The simplest way to configure the embedded agent is to include the “EmbeddedAgent.h” file and use the configureAgentWithAppID: selector with the App ID obtained from the App47 Dashboard.
This configuration will record session start, duration, location and capture relevant device and App information.
#import "MyAppAppDelegate.h" #import "MyAppViewController.h" #import <EmbeddedAgent/EmbeddedAgent.h> @implementation MyAppAppDelegate @synthesize window=_window; @synthesize viewController=_viewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgentWithAppID:@"4d556ab4530a69fb4b000002"]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
From Swift the configuration would be:
import UIKit import EmbeddedAgent
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_application: UIApplication, didFinishLauchingWithOption launchOptions: [UIApplicationLauchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
EmbeddedAgent.configureAgent(withAppID: "5887955ee609983cf6001de9")
return true
}
}
Use EmbeddedAgentSettings.plist for App ID
The agent can also be configured by storing the App ID in the optional EmbeddedAgentSettings.plist file and using the generic configuration API. First, add the EmbeddedAgentSettings.plist and add your application ID:
Now configuration can be done without requiring the AppID in the API call:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
The following parameters are recognized in the EmbeddedAgentSettings.plist
Parameter Name | Description |
application id | The application identifier for your mobile app, used to configure the agent at run time to pull configuration information as well as associate analytics. |
configuration endpoint |
The API configuration end point for your environment. This is optional and will be determined at run time if you do not specify this parameter. If you need this information for your environment, please contact support and we are happy to help you use this parameter. |
The Optional Steps -- Explained
Update other Agent Configuration Settings on Server
The other settings for the Agent are configured on the server from the App/Edit settings in the Agent tab. This allows for dynamic configuration of the Agent instead of settings being put in the resources or part of the configuration API call in code. Changes to settings will be acquired by the app the next time a configuration update is done, if you always want the app to have the latest settings set Agent Check in frequency to Every time.
Add Crash Log Management
There are three ways to capture crash log information for your iOS application, please choose one of the methods below, do not implement multiple methods within the sam application.
Manual capture
If you want crash log information captured and send to the App47 service, add the following “handleUncaughException” handler to your application delegate. This will capture any crash log information locally. The crash log information will then be uploaded the next time application is started. This will use the Google Toolkit Method of capturing crash logs.
void handleUncaughtException(NSException *exception) { EALogCrashException(exception, @"Application Crashed"); } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; NSSetUncaughtExceptionHandler(&handleUncaughtException); self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
GTM capture
To capture all crash exceptions, use the InstallExceptionHandlers method to register default handlers for uncaught exceptions and signal handlers. This is the same as setting "Google Toolbox" in the Capture Crash Logs setting.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [EmbeddedAgent configureAgent]; [EmbeddedAgent InstallExceptionHandlers]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
symbolicate capture
To capture the crash log in the iOS crash log format, and have it symbolicated by the service select the "Symbolicated (iOS Only)" option in the Capture Crash Logs setting.
This will use the PL Crash Reporter Library to capture the crash locally on the device. The crash log will be uploaded to the server the next time the application is started. It does not prompt the user to upload the crash log.
If your crash log is not fully symbolicated, please see our iOS symbolication trouble shooting guide.
Adding logging statements to your App
Additional level logging can be added to your App to capture debug, info, warn, error and crash log information. Log information is recorded locally and then uploaded to the service the next time the application resumes the active state or is started. Examples of logging statements:
// // MyAppViewController.m // MyApp // // #import "MyAppViewController.h" #import "EmbeddedAgent.h" @implementation MyAppViewController - (void)dealloc { [super dealloc]; } - (void)didReceiveMemoryWarning { // Warn level log statement EALogWarn(@"Received memory warning"); // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { // List of tags can be added to log statements for additional // search criteria in the web app. EALogInfoWithTags([NSArray arrayWithObject:@"MyTag"], @"View is being loaded"); [super viewDidLoad]; } - (void)viewDidUnload { [super viewDidUnload===== Level 2 Headline ===== ]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // All log macros allow for standard string format replacements // found in NSLog and stringWithFormat EALogDebug(@"View is being asked to rotate to interface orientation %d", interfaceOrientation); // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end
With Swift the macro helpers are not available so logging methods have to be called directly. Examples of logging statements in Swift:
// // MyAppViewController.swift // MyApp // // import EmbeddedAgent
class MyAppViewController: UIViewController {
override func didReceiveMemoryWarning { // Warn level log statement EmbeddedAgent.logWarning(withMessage:"Received memory warning", fileName: #file lineNumber: #line) // Releases the view if it doesn't have a superview. super.didReceiveMemoryWarning() // Release any cached data, images, etc that aren't in use. } // Implement viewDidLoad to do additional setup after loading the view override func viewDidLoad() { // List of tags can be added to log statements for additional // search criteria in the web app.
EmbeddedAgent.logInfo(withTags: ["MyTag"], message:"View is being loaded", fileName: #file lineNumber: #line) super.viewDidLoad() }
}
Add timed events to capture performance data
Timed events allow you to measure and record events in your application along with the duration of the event. Timed events are sent to the service immediately upon completion. If the agent is unable to send the event immediately, it is cached locally and then sent at the next App startup or activation. However, Timed Events are not written to disk. So if an application crashes, or is stopped, all cached time events are removed. A simple example of using timed events in your application would look like the following code:
- (void) performMyTransaction{ NSString *eventID = [EmbeddedAgent startTimedEvent:@"Transaction"]; // Perform some business logic to complete the transaction // … // [EmbeddedAgent endTimedEvent:eventID]; }
Timed events can be cleared before sending to the service using the clearTimedEvent: method or clear all events using the clearTimedEventsOlderThanTimeInterval: method.
- (void) performMyTransaction{ BOOL successful = NO; NSString *eventID = [EmbeddedAgent startTimedEvent:@"Transaction"]; // Perform some business logic to complete the transaction // … // if (successful) [EmbeddedAgent endTimedEvent:eventID]; else [EmbeddedAgent clearTimedEvent:eventID]; }
… OR …
- (void) clearAllTimedEvents { [EmbeddedAgent clearTimedEventsOlderThanTimeInterval:0]; }
To use a timed event in Swift:
func performMyTransaction() { let eventID = EmbeddedAgent.startTimedEvent("Transaction") // Perform some business logic to complete the transaction // … // EmbeddedAgent.endTimedEvent(eventID) }
Add generic events to capture user behavior
Generic Events are like Timed Events, but with no duration. Generic Events are sent to the service immediately upon request. If the agent is unable to send the event immediately, it is cached locally and then sent at the next App startup or activation. A simple example of using Generic Events in your application would look like the following code in Objective-C:
- (void) handleMyEvent{ [EmbeddedAgent sendGenericEvent:@"myEventName"]; // Perform some business logic to handle the event // … // }
and using Swift:
func handleMyEvent() { EmbeddedAgent.sendGenericEvent("myEventName") // Perform some business logic to handle the event // … // }
Using Configuration Groups in your App
Configuration Groups allows you to set a collection of key value pairs through the main web interface that are then downloaded by the agent at initial startup, and then subsequently at a frequency set by the “configuration update frequency” parameter in the EmbeddedAgentSettings.plist file. Configuration items must be requested by group name and key name. A default value may be given to be used in the event that the configuration group does not contain an item with the requested key name. If a default value is not given, and the key does not exist in the group, the value nil is returned. Configuration groups can be assigned to agents based on app version, os version and platform.
A simple example of using Configuration Groups in your application would look like the following code:
(void) myMethod{ NSString *serverURLString = [EmbeddedAgent configurationStringForKey:@"server url" group:@”Server Info” defaultValue:@”http://myserver.abc.com/restapi”]; // Use the serverURLString to perform additional work... // … // }
In Swift:
func myMethod() { let serverURLString:String? = EmbeddedAgent.configurationString(forKey:"server url" group:”Server Info” defaultValue:”http://myserver.abc.com/restapi”); // Use the serverURLString to perform additional work... // … // }
Receiving Configuration Group Notifications
The Embedded Agent will send notifications using NSNotificationCenter when new configuration settings are received from the service. The following messages are sent when the configuration change are received.
Name | Description |
---|---|
EmbeddedAgentAppConfigurationGroupDidInsert | A configuration group was added. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupDidUpdate | A configuration group was updated. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupDidDelete | A configuration group was deleted. The name of the group is included in the userInfo notification object with the key: EmbeddedAgentAppConfigurationGroupNameKey. |
EmbeddedAgentAppConfigurationGroupNameKey | A configuration group was changed, either added, updated or deleted. |
(void) updateViewFromConfigurationChange:(NSNotification *) notification{ NSDictionary *userInfo = [notification userInfo]; NSString *groupName = [[userInfo valueForKey:EmbeddedAgentAppConfigurationGroupNameKey]]; // // Update view based on groupName // ... } (void) viewDidLoad{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateViewFromConfigurationChange:) name:EmbeddedAgentAppConfigurationGroupDidUpdate object:nil]; [super viewDidLoad]; }
Releases
4.5
- Fix for authorized user policy
- Add configuration file parameter for configuration end point back to agent.
4.4
- Fix for version upgrade
4.2.7
-
Fix for agent migration, do not use previous version for 4.X!!
4.2.6 through 4.2.0 (Do not use)
- Pin code support
- Bug fixes on pin code
4.1.0 (Do not use)
- Dynamic configuration - Receive updates from the API to independently turn on (or off) sessions, logs, events and security policies.
4.0.0 (Do not use)
- Agent with dynamic configuration.
Comments
0 comments
Please sign in to leave a comment.