iOS SDK Guide
This document is written based on the latest version of the SDK.
SDK Information
SDK-supported version
-
Compilable iOS version: iOS 8.0 or higher
- In iOS 8.0, the API call doesn't work.
-
Actual working iOS version: iOS 9.0 or higher
SDK application
To use the loplat SDK, you must obtain a valid ID and Secret key provided by loplat.
To get a valid Id And Secret Key, please fill out the following information and send it to business@loplat.com.
- Name
- Company
- Purpose
Authority
Add Authority
To use loplat SDK, permission must be added. The required permissions are listed below.
-
Access WiFi Information
: iOS 12 or above is used to get the currently connected Wi-Fi information. (iOS 13 or later, location permission is required to operate.) -
Background Modes - Location Updates
: It is used to receive location information in the background.
Xcode Project > Capabilities Allow any permissions as shown below.
Request location permission from the user (required)
Please specify the reason for using location permission according to the service scenario.
If the reason for using the location permission is poor, approval could be rejected in the App Store review.
Be sure to explain detailed reasons for use to the user.
Detailed reason for use must include a legitimate reason for using the location in the background.
Therefore, please write the text that informs which benefits users would have by allowing location information.
Required to provide location-based events and benefit.
When you enter an affiliated store, we provide a coupon issuance or offline benefit-finding service.
If you select Always Allow, you will benefit without using the app.
Add the values below to your project's info.plist
file.
<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE plist PUBLIC "=//OBJECTIVE-C//DTD PLIST 1.0//EN" "http://www.OBJECTIVE-C.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- skip -->
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Example: To get 'all benefits' provided by the app, select 'Always' Allow.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Example: To get 'all benefits' provided by the app, select 'Always' Allow.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Example: To get benefits provided by the app, select location information as 'while using the app' and select 'always'</string>
<!-- skip -->
</dict>
</plist>
If you look at the above code in Xcode, it looks like this:
If you want to use the Core Location API according to the scenario of the app (ex: If you want to ask always permission in the foreground after login.) Please refer to the Core Location API documentation and make a request.
- OBJECTIVE-C
- swift
(void)Plengi.requestAlwaysLocationAuthorization;
Plengi.requestAlwaysLocationAuthorization()
Please call the above API when requesting location permission from the user according to your app's scenario.
Please refer to the example image below for scenarios where 'always' permission can be obtained for each iOS version.
ex1) Request for location permission on the first screen when the user initially installs the app
ex2) Request location permission when the user logs in
iOS 12 lower
The above screen is an example of the location permission request notification window (Prompt) in `iOS 12 or lower'.
iOS 13.0 ~ 13.3.1
The above screen is an example of the location permission request notification window (Prompt) in iOS 13.0 ~ 13.3.1
.
When a user selects 'Allow while using app'
in the foreground
When the SDK runs in the background, a notification window appears whether you want to change the location permission to 'always'
.
iOS 13.4 ~ 13.7
The image above is an example of the location permission request notification window (Prompt) in iOS 13.4 ~ 13.7
.
If the user selects 'Allow while using app'
, a notification window appears whether you want to change the location permission to 'always'
.
iOS 14.0 or higher
The image above is an example screen of the location permission request notification window (Prompt) in iOS 14.0 or later
.
If the user selects 'Allow while using app'
, a notification window appears whether you want to change the location permission to 'always'
.
With iOS 14.0, users can set 'On' or 'Off' for 'Precise Location'.
Request ATT(App Tracking Transparency) permission from users
Please specify the reason for requesting permission according to the service scenario.
‘If you allow it, you can receive appropriate information.’
Add the values below to your project's info.plist
file.
(Required) Even if the service scenario does not request permission, you must add it.
<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE plist PUBLIC "=//OBJECTIVE-C//DTD PLIST 1.0//EN" "http://www.OBJECTIVE-C.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- skip -->
<key>NSUserTrackingUsageDescription</key>
<string>Example: If you allow, you can receive appropriate information.</string>
<!-- skip -->
</dict>
</plist>
App Tracking Transparency import
Import the App Tracking Transparency by adding the following statement to the file requesting permission.
- OBJECTIVE-C
- swift
#import <AppTrackingTransparency/AppTrackingTransparency.h>
import AppTrackingTransparency
Request 'ATT' permission
Depending on the scenario of the app, add the following code to request ‘ATT’ permission.
- OBJECTIVE-C
- swift
- (void)requestIDFA {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
// Please write code according to your app scenario.
}];
}
func requestIDFA() {
ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
// Please write code according to your app scenario.
})
}
Below is an example image of a request.
IDFA can be used if the user selects ‘Allow ATT’.
Add loplat SDK to your project
Applying Cocoapod
Go to Add SDK
To use Cocoapods, install Cocoapod binaries on macOS.
Input the command below into the terminal.
$ sudo gem install cocoapods
If the installation is complete, activate the Cocoapod module in the project to which the loplat SDK will be applied.
Input the command below into the terminal.
$ cd $PROJECT_PATH
$ pod init
Add loplat SDK dependencies
loplat iOS SDK can be installed under the following prerequisites.
- Xcode 12.2+ (Xcode 12.2 or higher are compatible.)
- Cocoapod 1.9.0+
- Swift 5.4+ (with objc)
If you open the Podfile
in the project folder with the text editor, you will see the contents in the example format.
platform :ios, '8.0'
# use_frameworks!
target 'MyApp' do
pod 'AFNetworking', '~> 2.6'
pod 'ORStackView', '~> 3.0'
pod 'SwiftyJSON', '~> 2.3'
end
After entering the code below in the target
tag of Podfile
, save it.
pod 'MiniPlengi', '1.4.2'
Since the SDK uses Swift, uncomment # use_frameworks
in the Podfile. (delete the #)
Then, apply the library by entering the command into the terminal.
$ pod update
$ pod install
loplat SDK has been added to the project.
To open a project with Cocoapod applied, you must not open a file with an extension of .xcodeproj, but open a workspace file .xcworkspace file.
As shown in the image below, you must include the Swift standard library. Otherwise, the app itself may not run due to the inability to include the SDK on some iOS versions.
SDK initialization
To import
AppDelegate.h
(Objective-C) / AppDelegate.swift
(Swift) Add to the file.
- OBJECTIVE-C
- swift
#import <MiniPlengi/MiniPlengi-Swift.h>
import MiniPlengi
How to apply SDK
1. Initialize Plengi (required)
Plengi.initialize()
must be requested from AppDelegate
."SDK may not work if it is called from elsewhere.
Modify AppDelegate
class declaration as follows.
- OBJECTIVE-C
- swift
@interface AppDelegate : UIResponder <UIApplicationDelegate, PlaceDelegate>
class AppDelegate: UIResponder, UIApplicationDelegate, PlaceDelegate {
Then, add code to initialize the actual SDK to the AppDelegate
class.
- OBJECTIVE-C
- swift
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ********** skip ********** //
if ([Plengi initializeWithClientID:@"Client ID issued by Loplat"
clientSecret:@"Client key issued by Loplat"
echoCode:@"A code that can identify users by customer company (Please be careful about personal information)"] == Result.SUCCESS) {
// init success
} else {
// init failed
}
// ********** skip ********** //
}
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [IOApplicationLaunchOptionsKey: Any]?) -> Bool {
// ********** skip ********** //
if Plengi.initialize(clientID: "Client ID issued by Loplat",
clientSecret: "Client key issued by Loplat",
echoCode: "A code that can identify users by customer company (Please be careful about personal information)")
== PlengiResponse.Result.SUCCESS) {
// init success
} else {
// init failed
}
// ********** skip ********** //
}
echoCode
: ID for user identification (for management) and tracking in the app (ex, advertising id,id,....,etc.). If you do not want to manageechoCode
, you can enternil
value.
echoCode
should not contain personal information."Do not deliver personal information such as email and phone numbers.
2. Initialize Plengi - when the app comes alive in the background (very important)
This action is essential for the app to work automatically in the background. (Crash may occur if UI operation is entered into AppDelegate.
- OBJECTIVE-C
- swift
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions {
[Plengi initializeWithClientID:@"Client ID issued by Loplat"
clientSecret:@"Client key issued by Loplat"
echoCode:@"A code that can identify users by customer company (Please be careful about personal information)"];
// If there is a history of starting after agreeing to user terms in MainViewController
if ([Plengi getEngineStatus] == EngineStatusSTARTED ) {
[Plengi start];
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// When the app is restarted in background mode (not restarted if not required!!!!!)
_ = Plengi.initialize(clientID: "Client ID issued by Loplat",
clientSecret: "Client key issued by Loplat",
echoCode: "A code that can identify users by customer company (Please be careful about personal information)")
// If there is a history of starting after agreeing to user terms in MainViewController
if Plengi.getEngineStatus() == .STARTED {
_ = Plengi.start()
}
}
Register PlaceDelegate
Register PlaceDelegate
to receive events when a place recognition event is received from the server or a loplat X advertisement is received.
After Plengi.init
is called, call setDelegate
.
- OBJECTIVE-C
- swift
if ([Plengi setDelegate:self] == ResultSUCCESS) {
// setDelegate registration success
} else {
// Failed to register setDelegate
}
if Plengi.setDelegate(self) == .SUCCESS {
// setDelegate registration success
} else {
// Failed to register setDelegate
}
After that, implement PlaceDelegate
.
- OBJECTIVE-C
- swift
@implementation AppDelegate
- (void)responsePlaceEvent:(PlengiResponse *)plengiResponse {
if ([plengiResponse echoCode] != nil) {
// echoCode entered by the customer
}
if ([plengiResponse result] == ResultSUCCESS) {
// If you use the Lite plan, only advertisement information is provided according to the real-time location-based message sending function.
if ([plengiResponse advertisement] != nil) {
// When there is loplat X advertisement information,
// By default, the Plengi SDK handles advertising events as direct notifications.
// However, if the advertisement event is directly handled according to the setting value, the corresponding object is used.
}
// If you use the basic / premium plan, you can check the location recognition result data in addition to the features of the lite plan.
if ([plengiResponse place] != nil) {
if ([plengiResponse placeEvent] == PlaceEventENTER) {
// When a user enters a place
} else if ([plengiResponse placeEvent] == PlaceEventNEARBY) {
// When a user recognized as NEARBY
} else if ([plengiResponse placeEvent] == PlaceEventLEAVE) {
// When a user leaves a place
}
}
if ([plengiResponse complex] != nil) {
// When a complex is recognized
}
if ([plengiResponse area] != nil) {
// When commercial district are recognized
}
if ([plengiResponse geofence] != nil) {
// When geofence information is available
}
if ([plengiResponse location] != nil) {
// The latitude and longitude value of the device at the time of recognition
}
if ([plengiResponse district] != nil) {
// When there is district information
}
} else {
/* From here, it indicates error codes */
// [plengiResponse errorReason] contains location recognition failure/error reason
// FAIL : Location recognition Failed
// NETWORK_FAIL : Network Error
// ERROR_CLOUD_ACCESS : When the client ID/PW is incorrect or requested by an unauthenticated user
}
}
func responsePlaceEvent(_ plengiResponse: PlengiResponse) {
if plengiResponse.echoCode != nil {
// echoCode set by the customer
}
if plengiResponse.result == .SUCCESS {
if plengiResponse.place != nil {
if plengiResponse.placeEvent == .ENTER {
// If PlaceEvent is ENTER, the entered place information object will be delivered
} else if plengiResponse.placeEvent == .NEARBY {
//If the Place Event is NEARBY, the place information recognized as NEARBY will be delivered.
} else if plengiResponse.placeEvent == .LEAVE {
// If PlaceEvent is LEAVE, left place information object will be delivered.
}
}
if plengiResponse.complex != nil {
// When a complex is recognized
}
if plengiResponse.area != nil {
// When commercial district are recognized
}
if plengiResponse.advertisement != nil {
// When there is loplat X advertisement information
// By default, the Plengi SDK handles advertising events as direct notifications.
// However, if the advertisement event is directly handled according to the setting value, the corresponding object is used.
}
if plengiResponse.geofence != nil {
// When geofence information is available
}
if plengiResponse.location != nil {
// The latitude and longitude value of the device at the time of recognition
}
if plengiResponse.district != nil {
// When there is district information
}
} else {
/* From here, it indicates error codes */
// plengiResponse.errorReason contains location recognition failure/error reason
// FAIL : Location recognition Failed
// NETWORK_FAIL : Network Error
// ERROR_CLOUD_ACCESS : When the client ID/PW is incorrect or requested by an unauthenticated user
// Location Acquisition Fail : If you have only latitude and longitude values in plengiResponse.location
}
}
Running SDK
Start/Stop
- You can start or stop monitoring users' place/store visits. Call start after the user agrees to the location terms and conditions.
Even if start/stop is called repeatedly, it is implemented to be called only once within the SDK.
Do not call stop for exceptional cases. Call stop only when the user refuses to agree to the location agreement.
- The user's location information will be delivered to
PlaceDelegate
. - Start and stop monitoring is declared as follows.
- OBJECTIVE-C
- swift
[Plengi start]; //Monitoring Start
[Plengi stop]; //Monitoring Stop
Plengi.start() // Monitoring Start
Plengi.stop() // Monitoring Stop
Place recognition result
- Place recognition result value will be delivered as a
PlengiResponse
object.
Lite plan
-
Advertisement information is provided according to the real-time location-based message send function.
-
(Campaign result can be monitored on loplat X.)
-
Advertisement
: Advertising (PlengiResponse.Advertisement
Class,response.advertisement
Result)@objc public let body: String // Ad content
@objc public let campaign_id: Int // loplat X campaign id
@objc public let img: String // Image URLs included in ads
@objc public let intent: String // Ads event type (Url link or Deep link
@objc public let msg_id: Int // loplat X Ads Id
@objc public let target_pkg: String // The package name of the app corresponding to the advertisement
@objc public let title: String // Ads Title
@objc public let client_code: String // Ads Client Code
-
Basic / Premium Plan
-
In addition to the Lite plan, you can check the location recognition result.
"Different information is available in thePlengiResponse
object depending on the place recognition result."When recognizing a place,
area
(commercial district information) andcomplex
(complex mall) information are additionally delivered according to the result of the recognized place. If only the commercial district is recognized, theplace
information will be provided asnull
, so please be careful when writing the code. -
echoCode
( User identification code )@objc public var echoCode: String? // User identification echoCode
echo_code
will be delivered wheninit
is executed.
-
result
(Location recognition Success/Failure)@objc public var result: Result // report results
// Result.SUCCESS // Successful acquisition of requested location information
// Result.FAIL // Fail -
When location recognition fails
-
errorReason
: Location recognition failure reason@objc public var errorReason: String // Reason when result is FAIL
-
Failed to get current location:
Location Acquisition Fail
-
client authentication failed:
Not Allowed Client
-
-
If location recognition is successful
-
type
: location request type@objc public var type: ResponseType // request type
// ResponseType.PLACE // As a test, when refreshPlace() is requested
// ResponseType.PLACE_EVENT // Upon request, according to the set cycle -
placeEvent
: Recognized place event types (ENTER, NEARBY, LEAVE)@objc public var placeEvent: PlaceEvent // Recognized Place event types
// PlaceEvent.NOT_AVAILABLE // No Place information, not related to Area, Complex, or Geofence
// PlaceEvent.ENTER // Entered the place
// PlaceEvent.LEAVE // Left the Place
// PlaceEvent.NEARBY // Located near Place -
place
: Location information (PlengiResponse.Place
class,response.place
can be obtained)@objc public let loplat_id: Int // place ID
@objc public let name: String // place name
@objc public let tags: String? // tags related to places (Nullable)
@objc public let floor: Int // floor information
@objc public let lat: Double // latitude of place
@objc public let lng: Double // longitude of place
@objc public let accuracy: Double // Accuracy (accuracy > threshold comparison required)
@objc public let threshold: Double // Threshold
@objc public let client_code: String? // Customer Code (Nullable)
@objc public let category: String // place category
@objc public let category_code: String // Place category code
@objc public let address: String? // Place (Old) Address (Nullable)
@objc public let address_road: String? // Place (Street Name) Address (Nullable)
@objc public let post: String? // Location Postal Code (Nullable)accuracy > threshold
: If the user is placed inside of the current location- Elsewhere: If the user is placed nearby the current location
-
Area
: commercial district information (PlengiResponse.Area
class,response.area
can be obtained with)-
If the request is within the commercial district, it will be delivered along with the recognition result.
-
Latitude and longitude are delivered under the following conditions.
- If there is a place recognition result value -> Recognized place latitude/longitude
- If there is no place recognition result -> latitude/longitude of the device
@objc public let id: Int // commercial district ID
@objc public let name: String // commercial district name
@objc public let tag: String // commercial district tag
@objc public let lat: Double // commercial district Latitude
@objc public let lng: Double // commercial district Longitude -
-
Complex
: Complex(Complex mall) Information (PlengiResponse.Complex
class,response.complex
can be obtained)- If the recognized place is within a complex, its information will also be delivered.
@objc public let id: Int // Complex mall ID
@objc public let name: String // Complex mall name
@objc public let branch_name: String // Complex mall branch
@objc public let category: String // Complex mall category title
@objc public let category_code: String // Complex mall category code -
GeoFence
: Geofence & Fence (PlengiResponse.Geofence
class,response.geofence
delivery of results), fence information will be delivered in the geofenceclass GeoFence {
@objc public let lat: Double // Geofence Latitude
@objc public let lng: Double // Geofence Longitude
@objc public let fences: Array<Fence> // List of child fences
}
class Fence {
@objc public let gfid: Int // fence ID
@objc public let name: String // fence name
@objc public let dist: Double // fence distance between center coordinates and user position
@objc public let client_code: String // Client Code for Fences
} -
District
: administrative district (PlengiResponse.District
class,response.district
delivers results)class District {
@objc public let lv0_code: String // Country code, supported code only
@objc public let lv1_code: String // si, do
@objc public let lv1_name: String //
@objc public let lv2_code: String // si, gu, goon
@objc public let lv2_name: String //
@objc public let lv3_code: String // eup, dong, myeon
@objc public let lv3_name: String //
}
-
Integrating loplat X
Registration is required to use this service. For more detailed information, please get in touch with the loplat Business Team.
- To receive local notifications (not push messages using APNs) (advertisement and notification messages) through loplat X, the marketing notification setting and the code below must be written before Plengi.initialize.
- If you want to use Notification implemented yourself (refer to the code below), check Advertisement(
response.advertisement
) in the place recognition result for the advertisement information value.
When marketing notification setting is On - Enable loplat X
Call function to use loplat X in the SDK.
enableNoti
determines which advertising information will be processed.
If TRUE
, the SDK notifies advertisement information the user directly through iOS notification (default)
If FALSE
, advertisement notifications are managed directly in the client app and not be handled by SDK.
loplat X setting - Process advertising information directly from the client app
- OBJECTIVE-C
- swift
[Plengi enableAdNetwork:YES enableNoti:NO];
Plengi.enableAdNetwork(true, enableNoti: false)
loplat X setting - Processing advertising information in the SDK
- OBJECTIVE-C
- swift
[Plengi enableAdNetwork:YES enableNoti:YES];
Plengi.enableAdNetwork(true, enableNoti: true)
Marketing notifications setting is off - disable loplat X
If you do not allow to receive advertisements under certain scenarios, such as when the user does not agree to push notifications, Stop using loplat X by adding the code below.
- OBJECTIVE-C
- swift
[Plengi enableAdNetwork:NO enableNoti:NO];
Plengi.enableAdNetwork(false, enableNoti: false)
After notification permission is granted, events must be registered on the system to enable loplat X ad reception in the SDK.
Add the application_handleActionWithIdentifier
event to the AppDelegate
class and add the code below.
- OBJECTIVE-C
- swift
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter.currentNotificationCenter.delegate = self;
}
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forLocalNotification:(UILocalNotification *)notification
completionHandler:(void (^)())completionHandler {
[Plengi processLoplatAdvertisement:application
handleActionWithIdentifier:identifier
for:notification
completionHandler:completionHandler];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))
completionHandler API_AVAILABLE(ios(10.0)) {
completionHandler(UNNotificationPresentationOptionAlert |
UNNotificationPresentationOptionBadge |
UNNotificationPresentationOptionSound);
// allows notifications to be raised in the foreground, even on iOS 10 or higher
// (Badges, sounds, and warnings are used in the guide, but these options can be omitted depending on development conditions)
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)) {
[Plengi processLoplatAdvertisement:center
didReceive:response
withCompletionHandler:completionHandler];
completionHandler();
// loplat SDK to handle user notification tracking (Click, Dismiss)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}
func application(_ application: UIApplication,
handleActionWithIdentifier identifier: String?,
for notification: UILocalNotification,
completionHandler: @escaping () -> Void)
Plengi.processLoplatAdvertisement(application,
handleActionWithIdentifier: identifier,
for: notification,
completionHandler: completionHandler)
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
Plengi.processLoplatAdvertisement(center,
didReceive: response,
withCompletionHandler: completionHandler)
completionHandler()
// loplat SDK to handle user notification tracking (Click, Dismiss)
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
// allows notifications to be raised in the foreground even on iOS 10 or higher
// (Badges, sounds, and warnings are used in the guide, but these options can be omitted depending on development conditions)
}
sample app
- There are both loplat SDK sample apps for Objective-C and Swift.
- Feature-based sample apps are loplat SDK Sample for ObjC 2, Simple SDK Sample for Swift, The user consent-based scenario sample app is Simple SDK Sample for Swift
- The sample app also uses Cocoapod. Cocoapod user guide is specified in Adding loplat SDK to the project.
- If you want to call SDK API using React-Native, please refer to React Native - Native Module sample app