CocoaPods trunk is moving to be read-only. Read more on the blog, there are 9 months to go.
Well, I know nobody will actually read this. But, to be a good developer I'm writing this document.
This is a SDK (a.k.a Software Development Kit), which means you can build your own application with this kit much more simpler way. So, this is just a tool for you to build something of your own.
This SDK will make you less painful when you play around IoT devices.
But this SDK will only work fully with the server that controls contents and rules. The first thing SDK does when it's started is asking to server about how this SDK will react on IoT devices. Such as 'should SDK scan iBeacon?' or 'How long interval for sending logs?'. So, without the server it's not that very useful. Well, almost nothing will work but debugging stuffs.
So, go to iCIGNAL and get an API key.
Drag and drop, the install is done. No dependency or build setting problems. As long as you meet the requirements, you are good to go. The methods you mostly use are less than 10. Actually all public methods are less than 100 including getter/setter and debugging utils.
What you need to do is, design how and what your app will do when they got pre-defined tasks.
It's a little bit bigger than other kits, but it's well-structured. What you can get it from? Not so much. Except if there is some critical bug hidden somewhere, we could fix it faster, easier. This promises you long-term care and more experiments to be additional features.
Do you realize what will be happened if you just started from scratch? All the IoT devices will broadcast their signals toward you and you will end up with full of thread related issues. Of course, we believe that you can build something awesome even alone. But, we did all the messy jobs for you. Why would you do it all from the beginning?
The signals from the devices will be collected and tasks will be queued to be executed by you. You just tell SDK your job is done, then SDK will give you next one.
All the actions consume energy. As mobile application developer as us, we call it battery. And we all know it's very precious.
When we first started this project, battery drain was not in our mind. But, think of it tones of signals and processing? We really need to manage it for real world use.
We simplified the processes and tried hard not to use any unnecessary resources. Instead of scanning full time, SDK will take pause whenever it's possible.
Whether you designed your app well or not, you don't have to re-deploy to change the contents or trigger points. Even more, you can just stop monitoring certain IoT signals or change the collecting behavior of SDK. You can do it with the web based manager.
We provide multi-level debug message with console, file, and screen. You can see what you can't see usually via debugging messages. We know that it's much harder to figure out what's wrong when it's invisible like your signals. Now, you can see your signals and correct your source code or sensor setting.
Currently, we are covering 3 different signals. Of course, it's just beginning. The experiments keep going.
iBeacon is BLE(Bluetooth low energy a.k.a bluetooth 4.0) broadcast protocol invented by Apple. This protocol includes the identifier and its proximity. In other words, you can tell when the people get near a specific spot such as your product to advertise. It was very exciting news for the marketing scene but its possibility is much bigger.
Then we should think about why iBeacon became the key to contextual delivers? Because even now days, we can't know where exactly you are. Especially, when you are in the buildings. But, when you are not in the buildings we can track you with reasonable high accuracy even when you forgot to turn your bluetooth on.
You can set the virtual boundaries on the geographical region. Whenever people cross the boundaries, they will get your pre-defined tasks.
If you know which WiFi AP near by, you can determine where they are. In iOS, you can scan the WiFi only via private frameworks which means Apple will not allow you to submit your app to App Store. But you can see when they actually connect to the WiFi. It's less magical but it still gives you the same context.
Yes, many more will come...
There are two kind of requirements to consider. A development environment for you, and the runtime environment for the users.
Just drag & drop, it's almost done.
If your deployment version is 8.0, then you can use dynamic framework. (Drag & drop
/Dynamic/iCignalSDK.frameworkfile)
When you submit your app to the App Store, you need one more step for it, because of a bug from Apple.
Create a newRun Script Phasein your app’s target’sBuild Phases. And add the following code.
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/iCignalSDK.framework/strip-archs.sh"
If you made your project as Enable Modules (C and Objective-C) enabled in Build Settings then you can use frameworks like @import UIKit;.
And of course, you can use iCiganlSDK like @import iCignalSDK;. But there are two frameworks you need to manually add. JavaScriptCore and/or sqlite3.
We couldn't find cleaner way to use sqlite3 in our framework yet(you know the dependency and things..). It's bothersome but you need to add libsqlite3.tbd.
And don't forget that the linking should be Optional.
You need to add following frameworks manually.
iCignalSDK.framework
Foundation.framework
UIKit.framework
CoreBluetooth.framework
CoreLocation.framework
CoreMotion.framework
MapKit.framework
JavaScriptCore.framework
Security.framework
SystemConfiguration.framework
MobileCoreServices.framework
libsqlite3.dylib
MessageUI.framework
Twitter.framework
QuartzCore.framework
Accelerate.framework
If you don't know hot to use cocoapods, please visit here.
It's simple. add
pod 'iCignalSDK'
in your Podfile. And
pod install
In your code, you can import as #import <iCignalSDK/iCignalSDK.h> or @import iCignalSDK;.
Most of configurations for your app is in Info.plist. And there are things for the SDK too.
To make this SDK executes properly in background, you need to assign UIBackgroundModes key in your app's Info.plist file.
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>location</string>
<string>remote-notification</string>
</array>
The other options are optional, but location is crucial for background execution.
If no UIBackgroundModes key assigned, your app can't be executed over 180 seconds in background.
To handle requests from URL, you need to specify your custom scheme in Info.plist file of your app.
The scheme can be created using API key like icignal-yourAPIkey.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>icignal-53e18abc0cf29fcb62a82312</string>
</array>
</dict>
</array>
There are many options and configs you may need. It's all in the plist file, so no need of coding.
All the Keys are defined in ICCommon.h header file.
| Key | Value | Description |
|---|---|---|
| iCignal API Key | String | The key you got from iCIGNAL. If it's wrong or empty then SDK will not work. |
| iCignal Debug Level | Integer | Debugging level. (0 : Off, 1 : Error, 2 : Warning, 3 : Info, 4 : Debug, 5 : Verbose) You must set this 0 before you deploy. |
| iCignal Debug on Console | Boolean | If YES the debugging log will be presented on Xcode console. |
| iCignal Debug on File | Boolean | If YES the debugging log will be created as files in your app's Documents directory. |
| iCignal Debug on Screen | Boolean | If YES the debugging log can be presented on your app screen with [iCignalManager showOrHideLogWindow] method. |
| iCignal Log Enable Battery | String | If YES the battery usage will be collected. |
| iCignal Network URL - Base URL | String | The server's URL. Check if you set this correctly before you deploy |
| all the other paths... | String | You can set these paths as you want for debugging purpose, or other usages. |
<key>iCignal Configuration</key>
<dict>
<key>iCignal API Key</key>
<string>53e18abc0cf29fcb62a82312</string>
<key>iCignal Debug Level</key>
<integer>5</integer>
<key>iCignal Debug on Console</key>
<true/>
<key>iCignal Debug on File</key>
<true/>
<key>iCignal Debug on Screen</key>
<true/>
<key>iCignal Log Enable Battery</key>
<true/>
<key>iCignal Network URL - Base URL</key>
<string>http://devcloud.icignal.com</string>
<key>iCignal Network URL - Get Beacon Workflow rules</key>
<string>beacon/mbl/getWFRule.do</string>
<key>iCignal Network URL - Get Direct Message</key>
<string>beacon/mbl/getDirectMsg.do</string>
<key>iCignal Network URL - Get Location Workflow rules</key>
<string>beacon/mbl/getWFLocationRule.do</string>
<key>iCignal Network URL - Get Preferences</key>
<string>beacon/mbl/getPreferences.do</string>
<key>iCignal Network URL - Get Task Info</key>
<string>beacon/mbl/getTask.do</string>
<key>iCignal Network URL - Get WiFi Workflow rules</key>
<string>beacon/mbl/getWFWifiRule.do</string>
<key>iCignal Network URL - Update Workflow rule</key>
<string>beacon/mbl/getUpdateWFRule.do</string>
<key>iCignal Network URL - Upload Logs</key>
<string>beacon/mbl/traceLog.do</string>
</dict>
Describes the reason why the app accesses the user’s location information.
When the system prompts the user to allow access, this string is displayed as part of the alert panel.
Ignored in iOS 8 and later.
<key>NSLocationUsageDescription</key>
<string> *DESCRIPTION* </string>
From iOS 8, all the apps using location service need to explain how/why they use location of users. It is mandatory, not optional.
You can set both, or one of two. The user can choose from what you set. Which means what you didn't set won't show.
<key>NSLocationAlwaysUsageDescription</key>
<string> *DESCRIPTION* </string>
<key>NSLocationWhenInUseUsageDescription</key>
<string> *DESCRIPTION* </string>
Reference : Document / Video (WWDC 2014-706) / Video (WWDC 2014-715)
From iOS 11, all the apps using location service need to explain how/why they use location of users. It is mandatory, not optional.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string> *DESCRIPTION* </string>
From iOS 9, Apple prevented HTTP connections. But we may need to connect, and NSAppTransportSecurity will describe your app's exceptions.
Setting NSAllowsArbitraryLoads as false will make ATS disabled. (It's useful only when you can't decide which URL you would get)
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>icignal.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
</dict>
Reference : Document / Video (WWDC 2015-711)
From iOS 10, even more limitation of accessing private data, and you need to describe why you need it. It is mandatory, not optional.
This property describes why we need the motion activity data. We need it to avoid the battery drain when the user is not moving.
If this is not set, then we only use the accelerator.
<key>NSMotionUsageDescription</key>
<string> *DESCRIPTION* </string>
Reference : Document / Video (WWDC 2016-709)
In most of cases, you don't need anything. Just import iCignalSDK then it will work.
But if it's not working, you can try Bridging Header. Most simply way to make this is adding dummy Objective-C file in your project. Xcode will ask if you will configure bridging header.
YES! and add #import <iCignalSDK/iCignalSDK.h> in yourProjectName-Bridging-Header.h. Then you are good to go.
Here you can see how to use this SDK.
Most of time, you will need only few methods to be implemented.
The apps have life cycle, how they started and how they paused or backgrounded, and how they terminated. And you need to let the SDK know when and how.
SDK can detect most of events but there are some SDK cannot.
You only need to know one class. iCignalManager.
+ handlingLaunchingWithOptions:
application:didFinishLaunchingWithOptions: method in AppDelegate.launcingOption should be given by AppDelegate in order to wake SDK up correctly.Boolean type which determined if SDK can be enabled.- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if ([iCignalManager handlingLaunchingWithOptions:launchOptions]) {
[iCignalManager requestNotificationAuthorizationWithDelegate:self];
[iCignalManager requestLocationAuthorization];
[iCignalManager requestMotionActivityAuthorization];
[iCignalManager setDeviceUUID];
[iCignalManager setDelegate:self];
[iCignalManager start];
}
else {
NSLog(@"iCignal SDK is not available");
}
// Do your stuffs here...
return YES;
}
+ handlingRemoteNotification:fetchCompletionHandler:
application:didReceiveRemoteNotification:fetchCompletionHandler: method in AppDelegate.userInfo and completionHandler to SDK.Boolean type which determined if SDK can handle the push notification.- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if (![iCignalManager handlingRemoteNotification:userInfo fetchCompletionHandler:completionHandler]) {
NSLog(@"remote notification received but not for iCignal.");
// Do your own work here....and call completionHandler with result of your work.
completionHandler(UIBackgroundFetchResultNoData);
}
}
+ handlingOpenURL:sourceApplication:annotation:
application:openURL:sourceApplication:annotation: method in AppDelegate.Boolean type which determined if SDK can handle the given URL.- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [iCignalManager handlingOpenURL:url sourceApplication:sourceApplication annotation:annotation];
}
+ handlingOpenURL:options: (iOS9 or above)
+ handlingOpenURL:sourceApplication:annotation: which is deprecated after iOS 9.+ handlingOpenURL:sourceApplication:annotation: method.- (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options
{
return [iCignalManager handlingOpenURL:url options:options];
}
+ handlingPerformFetchWithCompletionHandler:
application:performFetchWithCompletionHandler: method in AppDelegate.- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[iCignalManager handlingPerformFetchWithCompletionHandler:^(UIBackgroundFetchResult resultFromICignal) {
// Do your things. and get a result...
UIBackgroundFetchResult yourResult = UIBackgroundFetchResultNoData;
completionHandler(MIN(resultFromICignal, yourResult));
}];
}
+ setDelegate:
application:didFinishLaunchingWithOptions: method.+ requestLocationAuthorization
Always or When in Use which described in your plist file respectively.+ requestNotificationAuthorizationWithDelegate: or + requestNotificationAuthorization
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) types. Also this method needs delegate as a parameter which will be delivered UNUserNotificationCenterDelegate events.(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) types.+ requestMotionActivityAuthorization
+ start
application:didFinishLaunchingWithOptions: method.+ finish
applicationWillTerminate: method.- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[iCignalManager finish];
}
+ kill
+ setEnabled: or other ability toggle methods, SDK may work again.+ currentTask
-[ICTask setObject:] for more details).Configuration methods are all in iCignalManager class, as class method.
You can selectively set Boolean value to configure which functionalities you want to turn on.
There are two way of setting, you can set default functionalities on the server. And prompt to user as following methods.
The functionality will be enabled only if server and app's configuration both enabled.
+ setEnabled:
+ setBeaconEnabled:
+ setLocationEnabled:
+ setWifiEnabled:
We already provides changeable properties on the server side. Use this methods only for debugging.
+ setBaseUrl:
+ setNetworkTimeout:
+ setNetworkRetry:
+ setNetworkRetryInterval:
It is more powerful when you know which user get closer to which point.
You could simply know some random people's approaching without any configuration.
But when you simply give SDK specific ID of user, you can personalize the contents or analyze them.
You need to specify the device along side of user. Because your app may allow to multi user log-in.
And sometimes, you may need to target at devices, not users.
+ setDeviceUUID
NSString specifying device.+ setDeviceUUID:
nil will remove UUID from the device.+ removeDeviceUUID
It's all about recognizing a person of interest. You can even let the SDK know the login status by passing nil.
+ setMemberID:
NSString object which can specify a user.nil SDK recognize it as logout.If you are using remote notification or if you want to use some more functionalities from iCignal, you need to pass the token to SDK.
By doing so, you can send notification to the users only in the specific areas or give them scheduled workflows.
+ setPushToken:
NSData type as you get it from your app's delegate.application:didRegisterForRemoteNotificationsWithDeviceToken: method.nil to unsubscribe.- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[iCignalManager setPushToken:deviceToken];
}
All the events from SDK will be delivered via iCignalManagerDelegate protocol.
The methods are all Optional.
These methods are hearts of your app's workflow. Delivered object is ICTask and you can determine what to do with it.
How well-made and flexible is decided from these methods.
- workflowDidReceiveTask:
completeHandler() function.completeHandler() function, next task will not be executed.ICTask class for more detail.- workflowDidCancelTask:
- workflowDidTimeoutTask:
When you use templates from iCignal server, you should handle the WebView.
- webViewShouldOpenURL:withParameters:
WebView for the URL, or use included one if you want.- webViewShouldCloseWithParameters:
We recommend not to imply these methods for performance improvement. Use them only when you need to debug.
- beaconDataWillBeCollected:
NSDictionary class.NSArray contains NSDictionary which describes the signal changing.- locationDataWillBeCollected:
NSArray class contains NSDictionary.- wifiDataWillBeCollected:
NSDictionary class.-1 or -999 now. -1 is connected and -999 is disconnected.You can use these methods to figure out what going on inside of the SDK.
More informations are always better, when you know what to do with it.
- authorizationStatusDidChange:
ICLocationAuthorizationStatus for more details.- bluetoothDidUpdateStateOn:
- motionActivityDidChange:
ICMotionActivityType for more details.- motionActivityRemaining:asActivityType:
ICMotionActivityType for the activity type.- beaconDidStartUpdating
- beaconDidStopUpdating
- beaconRangingRegionCountDidChange:
- beaconDidStartAdvertisingWithError:
- locationDidSuspendUpdating
- locationDidResumeUpdating
- locationDidStartUpdating
- locationDidStopUpdating
- locationStayingDurationDidChange:
- locationManualUpdatingDidFinish:withError:
- wifiDidStartUpdating
- wifiDidStopUpdating
- wifiDidConnectToSSID:andBSSID:
- wifiDidDisconnectFromSSID:andBSSID:
Most errors will be delivered. Even network or location or more.
See ICError for more details.
- managerDidFailWithError:
NSError object will be delivered.kICErrorNoWorkflow or kICErrorConcurrentCall can be occurred but it's not an error just information.You may want some configs to be changed via Settings.bundle.
There are some pre-defined identifiers which you can add on your Settings.bundle.
These values will overwrite any other value you set in your code.
All the identifiers will be synchronized when the SDK launched.
(If you changed any value while the SDK working, the value will be applied on next launching)
The identifiers can be added in future when it's needed.
All the values will be removed when app is removed.
If you want to know more about Settings.bundle visit here.
ICProperties_APIKey
API Key in your plist.String type.ICProperties_BaseURL
Base URL in your plist.String type.ICProperties_MemberID
Member ID in your app.String type.ICProperties_UserBeaconFlag
[iCignalManager setBeaconEnabled:] method in SDK.Boolean type.ICProperties_UserGeofenceFlag
[iCignalManager setLocationEnabled:] method in SDK.Boolean type.ICProperties_UserWifiFlag
[iCignalManager setWifiEnabled:] method in SDK.Boolean type.<InfavorBeacon/InfavorBeacon.h> -> <iCignalSDK/iCignalSDK.h><Twitter/Twitter.h> and <MessageUI/MessageUI.h> have added. for ICWebViewControllerInfavor Beacon to iCignalInfavor Beacon Debug has gone. Use iCignal Debug Level. You can set 0 to OFFInfavor Beacon Network URL - URL of Coupon Detail View has gone.iCignal Network URL - Get WiFi Workflow rules has added.Infavor Beacon Network URL - Get Workflow rules -> iCignal Network URL - Get Beacon Workflow rulesUIBackgroundModes array, fetch added.QI to ICQIBeaconManager (or BeaconManager) -> iCignalManagerQITask -> ICTask+[QIBeaconManager getVersion] -> +[iCignalManager sdkVersion]+[QIBeaconManager setPushDeviceToken:] -> +[iCignalManager setPushToken:]+[QIBeaconManager setMemberId:] -> +[iCignalManager setMemberID:]+[QIBeaconManager setBeaconDetectModeDynamic:] -> +[iCignalManager setPausesBeaconAutomatically:]+[QIBeaconManager handlingRemoteNotification:fetchCompletionHandler:] -> +[iCignalManager handlingRemoteNotification:fetchCompletionHandler:]
-[QITask type] -> [ICTask taskType]-[QITask parsedUrl] -> [ICTask taskURL]-[QITask content] -> [ICTask taskContent]-[QITask resumeTaskWithResponse:] -> -[ICTask completeHandler()]ICTaskReadyNotification -> iCignalManagerWorkflowDidReceiveTaskNotificationICTaskTimeoutNotification -> iCignalManagerWorkflowDidReceiveTaskNotificationICTaskCancelNotification -> iCignalManagerWorkflowDidReceiveTaskNotificationQIAuthorizationStatus -> ICLocationAuthorizationStatusQIBluetoothState -> +[iCignalManager isBluetoothPoweredOn]Metadata Rejected happens. Before it happened, put the info in Note.0.4.0 BEFORE YOU SUBMIT: INFO NEEDED, you need to provide the needed info.Information Needed
We began the review of your app but aren't able to continue because we need >additional information about your app. At your earliest convenience, please >review the following questions and provide as much detailed information as you can.
Please reply to this message in the Resolution Center with the requested information.
The additional informations you may request are below.
- Does this app detect startMonitoringForRegion:, startRangingBeaconsInRegion:, or both?
> We use both methods.
- What is the user experience when the app detects the presence of a beacon?
> If the beacon is registered on the server with a specific workflow, app will execute the workflow (predefined types of tasks).
- What features in this app use background location?
> When the user come around the geometric boundary, it will start updating location for more fine accuracy. And then, execute workflow as above.
- If this app uses 3rd party SDKs for iBeacons, please provide links to their documentation showing that background location is required for it to function.
> Not only iBeacon, but also Location features are included in SDK. http://www.quintet.co.kr/product/icignal or http://cocoadocs.org/docsets/iCignalSDK
Description."Continued use of GPS running in the background can dramatically decrease battery life."
If there is any problem, report here.
Download iCIGNAL Demo App
Or, pod try iCignalSDK.