Wiki

Clone wiki

Pinch.InstallPackage / Home

Pinch SDK Native implementation guide for iOS and Android

N|Solid

PinchSDK is available for Android 4.3+ (API level 18) and iOS 8.0 (iPhone 4S or later). For Android, devices running on API level prior to API level 18, will have Pinch disabled. The minimum level for building PinchSDK is 14.

Pinch SDK Cordova Pinch Proximity Plugin implementation guide are available on our wiki pages: https://bitbucket.org/fluxloop/cordova-plugin-pinch#readme

###Downloads:

iOS - Version 1.9.16 [changelog]

Android - Version 1.9.97 [changelog]

Prerequisites

In order to use the PinchSDK with your own application, you need to obtain a AppId and AppSecret from fluxLoop. Contact support@fluxloop.com

Implementing on iOS

Download the latest PinchSDK. The SDK contains a PinchLibrary.framework and Pinch.bundle

Unzip the installation package and drag and drop the framework and bundle files into your project in xcode.

Linker flags

Set "Build Settings -> Linking -> Other Linker Flags" to "-ObjC"

settings.bundle

To give the users the ability to delete all data registered about the user, you need to add the following to settings.bundle

  • Add Item Group with Title "Lokasjonsbasert kommunikasjon"
  • Item Switch with Identifier "EnablePinch", Default Value "YES", Title "Brukertilpasset innhold".
  • Item Switch with Identifier "DeletePinchData", Default Value "NO", Title "Slett mine data".
App delegate
#import <PinchLibrary/PinchLibrary.h>

// Forward didReceiveLocalNotification to PinchSDK
- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification {  
    [[PinchLibrary sharedInstance] pinchDidReceiveLocalNotification:notification];
}

// Forward didReceiveRemoteNotification to PinchSDK
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [[PinchLibrary sharedInstance] pinchDidReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];

 }

// Forward didFailToRegisterForRemoteNotificationsWithError to PinchSDK
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

    [[PinchLibrary sharedInstance] pinchDidFailToRegisterForRemoteNotificationsWithError:error];

}

// Forward didRegisterForRemoteNotificationsWithDeviceToken to PinchSDK
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [[PinchLibrary sharedInstance] pinchDidRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

}

// Forward didRegisterUserNotificationSettings to PinchSDK
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    //register to receive notifications
    [application registerForRemoteNotifications];
}
Starting Pinch

Pinch will not start location ranging until it's started. Start Pinch with the following code

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    // Your application code
    // ...
    // ...

    [[PinchLibrary sharedInstance] start];
}
Registering user data

User data makes it possible to create custom audiences based on data about the user. This could be gender, home city, age, etc. Data is sent as an NSDictionary and may contain any data and nested dictionaries. userDataModelName is the model name for the entity and you may use multiple userDataModels in an application. Usually you would have userDataModel named "UserData" containing more or less static information about the user, while you could have a userDataModel with latest purchase history in a userModelCalled "LatestPurchases".

// Example user data
NSDictionary *userData = @{@"Gender": @"male", @"Age": @36, @"MemberId": @"23423423"};

[[PinchLibrary sharedInstance] pinchRegisterUserData:userData userDataModelName:@"UserData"];
Pinch.plist

The Pinch.plist inside Pinch.bundle is used for configuring the application. Add your own texts to suit your application.

The most important settings here are AppID and AppSecret. These are used to identify your application in the cloud.

<key>NSLocationWhenInUseUsageDescription</key>
<string>Applikasjonen bruker din lokasjon for å kunne gi deg tilpasset informasjon og unike tilbud.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Applikasjonen bruker din lokasjon for å kunne gi deg tilpasset informasjon og unike tilbud.</string>
<key>NSLocationUsageDescription</key>
<string>Applikasjonen bruker din lokasjon for å kunne gi deg tilpasset informasjon og unike tilbud.</string>
<key>PinchLibrary</key>
<dict>
  <key>AppSecret</key>
  <string>YOUR-APP-SECRET</string>
  <key>AppID</key>
  <string>YOUR-APP-ID</string>
  <key>UseAuthorizationUI</key>
  <true/>
  <key>AuthorizeOnStartup</key>
  <true/>
  <key>InitViewsOnStartup</key>
  <true/>
  <key>HandleAuthorization</key>
  <true/>
  <key>DialogLocationImageName</key>
  <string>location_image.png</string>
  <key>DialogNotificationImageName</key>
  <string>messages_image.png</string>
  <key>DialogTitleColor</key>
  <string>#333333</string>
  <key>DialogRadioButtonColor</key>
  <string>#85CFEF</string>
  <key>DialogButtonColor</key>
  <string>#444444</string>
  <key>DialogButtonCornerRadius</key>
  <string>0</string>
  <key>EventBubbleBackgroundColor</key>
  <string>#85CFEF</string>
  <key>EventBubbleBorderColor</key>
  <string>#FFFFFF</string>
  <key>EventBubbleForegroundColor</key>
  <string>#FFFFFF</string>
  <key>RangingTimeSeconds</key>
  <integer>60</integer>
  <key>CloseButtonBackgroundColor</key>
  <string>#FFFFFF</string>
  <key>CloseButtonForegroundColor</key>
  <string>#000000</string>
  <key>CloseButtonOpacity</key>
  <integer>100</integer>
  <key>CloseButtonTriggersAlertDialog</key>
  <false/>
  <key>DisableEventBubble</key>
  <false/>
  <key>EnableRegisterEvents</key>
  <false/>  
<key>DisableDebugLogging</key>
<false/>  
</dict>

App.plist

  • Make sure the "App downloads content from the network" subkey is added for "Required background modes" in application.plist.
  • Enable following "Background fetch" under Project Capabilities
  • If set, change "Application does not run in background" to "NO"
  • Set NSLocationWhenInUseUsageDescription to a description of your choice
  • Set NSLocationAlwaysUsageDescription to a description of your choice
  • Set Privacy - Location Usage Description to a description of your choice

Push notifications

Create sandbox and production certificates for push notifications (https://developer.apple.com/account/ios/certificate/certificateList.action) add to keychain and send your certificates as p12 to support@fluxloop.com If everything is configured correctly, you should see didRegisterForRemoteNotificationsWithDeviceToken (YOUR-TOKEN) in your log. Also make sure you've added the Push Notifications entitlement.

Pinch events

You can subscribe to Pinch events by using observers. PinchEventOnGlobalEvent will subscribe to all events, but you may want to listen to specific events as well.

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignReceivedHandler:) name:PinchEventOnCampaignReceived object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignClosedHandler:) name:PinchEventOnCampaignClosed object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignDeletedHandler:) name:PinchEventOnCampaignDeleted object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignExpiredHandler:) name:PinchEventOnCampaignExpired object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignOpenedHandler:) name:PinchEventOnCampaignOpened object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignReadyHandler:) name:PinchEventOnCampaignReady object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchCampaignGoalAchieved:) name:PinchEventOnCampaignGoalAchieved object:nil];    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pinchEventHandler:) name:PinchEventOnGlobalEvent object:nil];

Implementing on Android

Add the res and pinch-library folders from the package to your project. The contents in the res folder should be copied to your applications res-folder.

build.gradle

Add the following dependencies to your build.gradle

dependencies {
   compile fileTree(include: ['*.jar'], dir: 'libs')

   compile 'com.android.support:appcompat-v7:+'
   compile 'com.google.android.gms:play-services-gcm:+'
   compile 'com.google.android.gms:play-services-ads:+'
   compile 'com.squareup.retrofit:retrofit:1.8.0'
   compile 'org.altbeacon:android-beacon-library:2.12.2'
   compile (name:'pinch', ext:'aar')
}

/res/values/pinch.xml

Make sure you change any colors and texts for your application. AppID and AppSecret must be obtained by contacting support@fluxloop.com

If you want to configure AppId and AppSecret through code instead of pinch.xml, you may do so with the PinchConfig class.

        PinchConfig config = new PinchConfig();
        config.setAppId("YOUR-APP-ID");
        config.setAppSecret("YOUR-APP-SECRET");
        config.setDisableEventBubble(false);
        config.setHandleAuthorization(true);

        PinchManager.getInstance().initAndStartAsync(this, config);

This is the default pinch.xml from the package:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="AppID"></string>
    <string name="AppSecret"></string>
    <string name="TermsColor">#009BDE</string>
    <string name="TermsImage">location_image.png</string>
    <string name="TermsUrl">http://tc.pinch.no</string>
    <string name="RangingTimeSeconds">60</string>
    <string name="LowPowerRangingSeconds">5</string>
    <string name="LowLatencyRangingSeconds">1</string>
    <string name="HandleAuthorization">true</string>
    <string name="DisableEventBubble">false</string>
    <string name="EnableRegisterEvents">false</string>
    <string name="app_name"></string>
    <string name="location_title">Din posisjon</string>
    <string name="location_description">Ved at du gir oss tilgang til din posisjon kan vi gi deg tilpasset informasjon på mobilen og andre flater.\n\nVed å klikke neste, godtar du også applikasjonens </string>
    <string name="location_checkbox_label">Vis min posisjon</string>
    <string name="terms_and_conditions">vilkår og betingelser</string>
    <string name="location_next">Neste</string>
    <string name="campaign_dialog_title">Slett denne eller bare lukke den inntil videre?</string>
    <string name="campaign_dialog_close">Lukk</string>
    <string name="campaign_dialog_delete">Slett</string>
    <string name="bluetooth_enable_title">Blåtann er deaktivert</string>
    <string name="bluetooth_enable_content">Skru på blåtann for å få stedsbasert informasjon i applikasjonen.</string>
    <string name="bluetooth_enable_ok">OK</string>
    <string name="pinch_disabled_title">Blåtann er deaktivert</string>
    <string name="pinch_disabled_description">Skru på blåtann for å få stedsbasert informasjon i applikasjonen.</string>
    <string name="pinch_disabled_cancel">Blåtann er deaktivert</string>
    <string name="pinch_disabled_link_cancel">Avbryt</string>
    <string name="pinch_disabled_link_ok">Innstillinger</string>
    <color name="default_pinch">#009BDE</color>
</resources>

images and layouts

The package contains a default set of images and layouts. These may be overridden by copying optional-res-overrides to your applications res folder.

TIP: The notification icon for notifications is your app icon. You may override this by calling PinchManager.getInstance().setNotificationResId() or by adding an icon file named ic_pinch_notification.png in your drawable res folder

android.manifest

Add the following intent-filter to your android.manifest

            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="${applicationId}" android:host="${applicationId}" />
            </intent-filter>

The android:scheme and android:host must be unique for this application. eg mypinchapp://my.pinch.app If you want to use your own urlscheme, you may do so by providing a custom url scheme in pinch.xml with the key "UrlScheme" or by calling PinchManager.getInstance().setUrlScheme(). With the intent-filter in the example above, it will use your applicationId from your apps gradle file.

MainApplication.java

If you don't have an application class in your project, you need to create one. If PinchManager is started in the MainActivity, you won't be able to get location events unless the application is running. You should also add a reference to the BackgroundPowerSaver in your main application.

In the onCreate method in MainApplication.java. Add this to initialize and start the PinchManager.

public class MainApplication extends Application {

@Override
protected void onCreate(Bundle savedInstanceState) {
    PinchManager.getInstance().initAndStartAsync(this);
}

@Override
   public void onTerminate() {
       PinchManager.getInstance().clear();
       super.onTerminate();
   }

In your activity (deprecated from versjon 1.9.94)

To make sure the PinchSDK is not displaying campaigns outside the activity context, pause and resume the PinchManager onPause and onResume.

 @Override
   protected void onResume() {
       super.onResume();
       PinchManager.getInstance().onResume();
   }


   @Override
   protected void onPause() {
       super.onPause();
       PinchManager.getInstance().onPause();
   }

Requesting and withdrawing permissions

IMPORTANT! If you want to use the default onboarding for Pinch, you need to set HandleAuthorization = true in pinch.xml, and when ready call PinchManager.getInstance().askPermissionsIfNotAsked();

This will trigger the soft screen asking for permissions and present the user with the OS locationAuthorization dialog if the user accepts Pinch. Make sure you then go through all relevant strings in pinch.xml if you use the default onboarding.

If you don't want to use the default onboarding, make sure you call PinchManager.getInstance().setEnabled(true/false) depending on if the user accepts or rejects Pinch. The SDK will not send any locationevents unless you call PinchManager.getInstance().setEnabled(true). You may disable Pinch at any time by calling PinchManager.getInstance().setEnabled(false) and location events should stop immediately.

PinchManager.getInstance().getEnabled() may be used to see if the user has enabled or disabled Pinch.

Clear cloud data

If the user for some reason wants to clear all personal information in the Pinch Cloud, you may do this by calling PinchManager.getInstance().pinchClearCloudUserData()

The method has an optional callback to make sure the request was sent successfully

      PinchManager.getInstance().pinchClearCloudUserData(new PinchResponseCallback() {
            @Override
            public void onSuccess(String content) {
                // The request was successful
            }

            @Override
            public void onFailure(String content) {
               // The request failed
            }
        });

Events

PinchEvents can be subscribed to through the PinchManager listener.

   PinchManager.getInstance().setListener(new PinchEventListener() {
        @Override
        public void onEvent(String name, String data) {
            // ...
        }
    });

Registering user data

User data makes it possible to create custom audiences based on data about the user. This could be gender, home city, age, etc. Data is sent as an JsonObject and may contain any data and nested objects. modelName is the model name for the entity and you may use multiple modelNames in an application. Usually you would have modelName named "UserData" containing more or less static information about the user, while you could have a modelName with latest purchase history in a modelName "LatestPurchases".

User data that could be used to better target users with relevant information should be sent through this method. Typically this is things like firstname (gender is extracted from the name), birthyear, postal code or any other information that might help giving relevant information without identifying the user.

PinchManager.getInstance().pinchRegisterUserData(JsonObject data, String modelName);

Proguard

If you are using proguard, make sure you exclude com.pinch.library and retrofit:

-keep class com.pinch.library.** { *; }
-keep class retrofit.** { *; }

Updated