We’ve migrated our documentation to a new site, which means some URLs have changed.
Subscriptions

Implementing Piano's SDK

1. iOS SDK

2. Android SDK

3. FAQ

iOS SDK

iOS requirements

These versions of iOS and applications are supported:

  • iOS 12.0+ (tested on iOS 15+)

  • Xcode 15.3

  • Swift 5.10

We do not currently support earlier versions of Swift.

iOS implementation

The unabridged iOS SDK and implementation instructions are found in Piano's Github repository. The readme.md file explains the implementation in full.  Here are some highlights of that information.

The SDK is dependent on CocoaPods. This must be installed in your environment.

Ensure you have CocoaPods by adding the following code to your Podfile.

use_frameworks!

pod 'PianoComposer', '~> 2.6.1'
pod 'PianoTemplate', '~> 2.6.1'
pod 'PianoTemplate.ID', '~> 2.6.1'
pod 'PianoOAuth', '~> 2.6.1'
pod 'PianoC1X', '~> 2.6.1'

Then run pod install. For details on the installation and usage of CocoaPods, visit the official website here.

Swift Package Manager

Add the components you need from the repository:

URL: https://gitlab.com/piano-public/sdk/ios/package
Version: 2.6.1

Our iOS SDK collects the following information about users:

  • Device model

  • OS version

Composer in iOS

When using mobile experiences in Composer in the Piano Dashboard to manage the user experience, four steps are required to link between Composer and an application.

  1. Initialize Piano Composer in the SDK.

  2. Set up variables.

  3. Define the Piano AID and environment.

  4. Execute Composer.

  5. Set up Composer events.

Initializing Piano Composer

Import
// swift
import PianoComposer

// objective-c
@import PianoComposer;

Initializing parameters when loading an article

Initialize parameters and pass page settings and variables as parameters when loading an article. These are the possible parameters and their argument’s data type. 

tag(_ tag: String)

tags(_ tagCollection: Array<String>)

customVariable(name: String, value: String)

customParams(_ customParams: CustomParams)       

url(_ url: String)

userToken(_ userToken: String)

referrer(_ referrer: String)       

zoneId(_ zoneId: String)       

debug(_ debug: Bool)   

contentCreated(_ contentCreated: String)       

contentAuthor(_ contentAuthor: String)       

contentSection(_ contentSection: String)       

contentIsNative(_ contentIsNative: Bool?)              

delegate(_ delegate: PianoComposerDelegate?)       

gaClientId(_ gaClientId: String)

This is a code example of parameters passed in the Composer function: 

var composer = PianoComposer(aid: "<PUBLISHER_AID>")
.delegate(self) // conform PianoComposerDelegate protocol
.tag("tag1") // add single tag
.tag("tag2") // add single tag
.tags(["tag3", "tag4"]) //add array of tags
.zoneId("Zone1") // set zone
.referrer("http://sitename.com") // set referrer
.url("http://pubsite.com/page1") // set url
.customVariable(name: "customId", value: "1") // set custom variable
.userToken("userToken") // set user token

PianoComposer.clearStoredData() can be used to clear all stored cookies - xbc, tbc, tac. Please note that to clear any of the variables defined above, they should either be set to “ ” or be reset with a new value when Composer is executed again. Otherwise, there is the possibility that Composer will segment with incorrect values. Meter values are stored in the UserDefaults properties with keys io.piano.composer.

Defining AID and environment

The snippet below changes the Piano environment between Sandbox for testing, or production for implementation. The live production environment is the default in the absence of configuration.

PianoComposer(aid: "<PUBLISHER_AID>") // Production endpoint is used by default (PianoEndpoint.production)
// or
PianoComposer(aid: "<PUBLISHER_AID>", endpoint: PianoEndpoint.sandbox)
Endpoints
PianoEndpoint.production // Production endpoint
PianoEndpoint.productionAustralia // Production endpoint for Australia region
PianoEndpoint.productionAsiaPacific // Production endpoint for Asia/Pacific region
PianoEndpoint.productionEurope // Production endpoint for Europe region
PianoEndpoint.sandbox // Sandbox endpoint

Executing Composer

In order to finally have the execution of the Experience happen, once the environment variables are set and the app knows whether to connect to Production or the Sandbox, you can execute the experiences with the following method:

composer.execute()

It is required to run this code every time you would like Piano to measure the app equivalent of a new page view or whenever you want the meter to increment.

Events

The following events are available in the iOS SDK in the PianoComposerDelegate protocol. These events fire when the corresponding action takes place in Composer. For example, tracking events could be linked to the showTemplate event.

Adding your own code to the events can be done in the Sources/Composer/Composer/PianoComposerDelegate.swift.

These events are supported: 

// Client actions
optional func composerExecutionCompleted(composer: PianoComposer)

// Composer actions from server 
optional func showLogin(composer: PianoComposer, event: XpEvent, params: ShowLoginEventParams?)
optional func showTemplate(composer: PianoComposer, event: XpEvent, params: ShowTemplateEventParams?)
optional func showForm(composer: PianoComposer, event: XpEvent, params: ShowFormEventParams?)
optional func showRecommendations(composer: PianoComposer, event: XpEvent, params: ShowRecommendationsEventParams?)
optional func nonSite(composer: PianoComposer, event: XpEvent)
optional func userSegmentTrue(composer: PianoComposer, event: XpEvent)
optional func userSegmentFalse(composer: PianoComposer, event: XpEvent)    
optional func meterActive(composer: PianoComposer, event: XpEvent, params: PageViewMeterEventParams?)
optional func meterExpired(composer: PianoComposer, event: XpEvent, params: PageViewMeterEventParams?)    
optional func experienceExecute(composer: PianoComposer, event: XpEvent, params: ExperienceExecuteEventParams?)

Events can be handled with the following steps: 

1) Set delegate property of an instance of class PianoComposer:

composer.delegate = self

2) Declare the method of PianoComposerDelegate related to the event:

// e.g. showLogin event handling

func showLogin(composer: PianoComposer, event: XpEvent, params: ShowLoginEventParams?) {

//TODO: handle showLogin event

}

For more information about templates, see the documentation under this link.

Piano ID in iOS

When Piano ID is initialized, it is possible to use the SDK to log the user in, sign up for a new account, refresh the user token and determine token expiration date. 

Actions that are available in the SDK for Piano ID include:

  1. Login

  2. Registration

  3. Social login

  4. Logout

Before any ID features can be used, the PianoID.shared object must be initialized.

// swift
import PianoOAuth

// objective-c
@import PianoOAuth;

Piano ID requires a custom URL Scheme to be added to your project. To add it: open your project configuration select your app from the TARGETS section, then select the Info tab, and expand the URL Types section.

Set io.piano.id. as the URL scheme.

Piano ID requires adding a custom Redirect URI io.piano.id.://success to the Authorized Redirect URIs in the Piano ID configuration in the Publisher dashboard, especially if the "Authorize the list" toggle is enabled.

To enable social login, you must configure the Piano ID shared instance before usage.

PianoID.shared.aid = "<PUBLISHER_AID>"
PianoID.shared.delegate = self

Also you must implement the application(_:open:options:) method of your app delegate:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    return PianoOAuth.PianoIDApplicationDelegate.shared.application(app, open: url, options: options)
}

For SceneDelegate(iOS 13+) implement the scene(_,openURLContexts) method:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    ...

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let url = URLContexts.first?.url else {
            return
        }

        _ = PianoIDApplicationDelegate.shared.application(
            UIApplication.shared,
            open: url,
            sourceApplication: nil,
            annotation: [UIApplication.OpenURLOptionsKey.annotation]
        )
    }
}

For SwiftUI (iOS 14+) you must implement the onOpenURL(perform) method of your ContentView:

@available(iOS 14.0, *)
struct MyApp: App {
    
    ...
    
    var body: some Scene {
        WindowGroup {
            ContentView().onOpenURL { url in
                PianoIDApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: nil)
            }
        }
    }
}

Login

To log in, the following method should be used. It will return activeToken which can then be used through the application:

PianoID.shared.signIn()

Now you can obtain token.accessToken, token.refreshToken, token.expiresIn using the following function:

func pianoID(_ pianoID: PianoID, didSignInForToken token: PianoIDToken!, withError error: Error!)

Once you have the tokens, you should store the token.accessToken, token.refreshToken in persistent storage on the device e.g. keychain.

When the initial token will expire, it should be refreshed with: 

https://api.piano.io/api/v3/oauth/authToken?client_id=<AID>&grant_type=refresh_token&refresh_token=<REFRESH_TOKEN>

This API endpoint will return the new tokens, which should once again be stored.

Additional settings:

PianoID.shared.isSandbox = true // for using sandbox application
PianoID.shared.widgetType = .login // or .register for choosing default screen 
PianoID.shared.signUpEnabled = false // for enabling/disabling signUp

Registration

To register, the following methods should be used:

PianoID.shared.widgetType = .login // or .register for choosing the default screen

PianoID.shared.signUpEnabled = true // can also be used in cases where you want to allow readers to navigate from the login to the registration screen

Logout

Logging out is straightforward, using the accessToken as below:

PianoID.shared.signOut(token: "<TOKEN>")

You may want to manually reset the web view after a user has been logged out.

Social sign-in

The mobile SDK supports Google and Facebook native login, in addition to Twitter, Apple, and LinkedIn social sign-in.

Native social sign-in

Facebook sign-in

You must implement the application(_:didFinishLaunchingWithOptions:) method of your app delegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {    
    PianoOAuth.PianoIDApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
    return true
}

Also, you should configure your application as described in the Facebook documentation here.

Google sign-in

Add before the PianoIDApplicationDelegate.shared.application function call:

// iOS 14+
@main
struct MyApp: App {
    init() {
        PianoID.shared.add(socialProvider: PianoIDGoogleProvider())
    }
}

// iOS 13 and earlier versions
class AppDelegate: UIResponder, UIApplicationDelegate {
    override init() {
        super.init()
        PianoID.shared.add(socialProvider: PianoIDGoogleProvider())
    }
    ...
}

The PianoID.shared.googleClientID would need to be customized via Info.plist.

Information about the Google client ID can be found here. 

Also, you should configure the URL scheme as described here.

Passwordless Login in SDK

These settings should be configured in Piano ID according to this documentation. The current configuration is applied in the mobile application without additional settings.

PianoIDDelegate protocol
func signIn(result: PianoIDSignInResult!, withError error: Error!);

func signOut(withError error: Error!);

func cancel();
User information

To get user information, use the PianoID.userInfo function:

PianoID.shared.userInfo(aid: "<YOUR_AID>", accessToken: "<USER_ACCESS_TOKEN>", formName: "<FORM_NAME>") { result, err in
    if let e = err {
        // handle error
        return
    }
    
    // handle user information result
}

An example of the data points returned by this function can be found below:

class PianoUserProfile(
    val email: String,
    val uid: String,
    val firstName: String,
    val lastName: String,
    val aid: String,
    val updated: Date,
    val token: String?,
    val linkedSocialAccounts: List<String>?,
    val passwordAvailable: Boolean,
    val customFields: List<CustomField>?,
    val allCustomFieldsFilled: Boolean?,
    val needResendConfirmationEmail: Boolean,
    val changedEmail: Boolean,
    val passwordless: Boolean
)

For updating user information, use the function PianoID.putUserInfo:

putUserInfo(
    aid: "<AID>",
    accessToken: "<USER_ACCESS_TOKEN>",
    formName: "<FORM_NAME>",
    customFields: [
        "<FIELD_NAME>": "<FIELD_VALUE>"
    ]
) { result, error in
    if let error {
        // handle error
        return
    }
    
    // handle updated user information result
}

Composer 1x

For more information about the Composer 1x integration, see the documentation under this link.

Android SDK

Android requirements

Piano ID supports this version of the Android mobile OS:

  • Android 4.4+ (Android SDK v19)

Android implementation

Latest release: GitHub release (latest SemVer)

Below is a list of artifacts available in our Android SDK:

io.piano.android:composer contains implementation for Composer
io.piano.android:composer-show-template contains ShowTemplateController, which helps with "show template" event
io.piano.android:show-custom-form contains ShowFormController, which helps with "show form" event
io.piano.android:composer-c1x contains Composer 1x integration
io.piano.android:id contains implementation for Piano ID
io.piano.android:id-oauth-facebook contains FacebookOAuthProvider, which implements native auth via Facebook account
io.piano.android:id-oauth-google contains GoogleOAuthProvider, which implements native auth via Google account

Our Android SDK collects the following information about users:

  • Manufacturer

  • Device model

  • Android version (as part of user-agent in Composer)

Composer in Android

Dependencies

Maven Central

The Piano Composer Android SDK is available as an AAR via mavenCentral. To add dependencies, open your project’s build.gradle and update the repositories and dependencies blocks as follows:

repositories {
   // ... other project repositories
   mavenCentral()
}

// ...
android {
	...
	compileOptions {
              sourceCompatibility JavaVersion.VERSION_1_8
              targetCompatibility JavaVersion.VERSION_1_8
	}
}
dependencies {
   // ... other project dependencies
   implementation 'io.piano.android:composer:$VERSION'
}

If you're using Auth Sync or UserRef as your user management system, you will need to set the access token as follows:

// Kotlin

Composer.getInstance().userToken(accessToken)

initializeparameters

Initialize the parameters when loading an article

Initialize parameters, and pass page settings and variables as parameters when loading an article. These are the possible parameters and their argument’s data type:

contentAuthor(String contentAuthor)
Any author(s) associated with the given content.

contentCreated(String contentCreated)
Date and time of the creation of the given content (UTC, ISO 8601).

contentCreated(Date contentCreated)
Date and time of the creation of the given content (doesn't require format as method above)

contentIsNative(Boolean contentIsNative)
Given content is created editorially or is sponsored content.

contentSection(String contentSection)
Section of your site that your content has been assigned to.

customParams(CustomParams customParams)
Any active parameters for the given content.

customVariable(String key, String value)
Any custom variable that you have set on your content (can be called multiple).

customVariables(Map<String, String> customVariables)
Any custom variables that you have set on your content.

debug(boolean debug)
Determine if this execution is run in debug mode.

referer(String referer)
Content referrer.

tag(String tag)
Content tag (can be called multiple).

tags(Collection<String> tags)
Content tags.

url(String url)
Content URL from which composer execution has been triggered.

zone(String zone)
Specify zone of application of experience.

keyword(String keyword)
Specify the keyword for the request.

keywords(Collection<String> keywords)
Specify multiple keywords for the request.

title(String title)
Specify the article's title

description(String description)
Specify a description

contentId(String contentId)
Specify the content Id

contentType(String contentType)
Specify the content type

Events in Composer

These events are available to be configured in the mobile SDK for Composer:

ExperienceExecuteListener
//Composer execution has been finished.

MeterListener
//PageViewMeter active or expired, check event.eventData.state.

NonSiteListener
//NonSite action.

SetResponseVariableListener
//Set response var action.

ShowFormListener
//Show custom form action.

ShowLoginListener
//Show login action.

ShowRecommendationsListener
//Show recommendations action.

ShowLoginListener
//Show login action.

ShowTemplateListener
//Show template action.

UserSegmentListener
//UserSegment failed or passed, check event.eventData.state.

For more details on the ShowTemplate event please follow this link.

Executing Composer experiences

You must configure Composer and add event listeners before executing:

val customParameters = CustomParameters()
       .content("contentKey", "contentValue0")
       .content("contentKey", "contentValue1")
       .user("userKey", "userValue")
       .request("requestKey", "requestValue1")
       .request("requestKey", "requestValue2")
       .request("requestKey", "requestValue3")

val request = ExperienceRequest.Builder()
        .url("https://example.com")
        .referer("https://google.com")
        .tag("tag")
        .debug(true)
        .customParams(customParameters)
        .build()

val listeners: Collection<EventTypeListener<out EventType>> = listOf(
        ExperienceExecuteListener { event: Event<ExperienceExecute> ->
            // process event
        },
        UserSegmentListener { event: Event<UserSegment> ->
            // process event, useful data is event.eventData.state
        },
        ShowLoginListener { event: Event<ShowLogin> ->
            // process event
        },
        MeterListener { event: Event<Meter> ->
            // process event, useful data in event.eventData fields
            if (event.eventData.state == Meter.MeterState.ACTIVE) {
                // Meter is Active
            } else {
                // Meter is Expired
            }
        },
        ShowTemplateListener { event: Event<ShowTemplate> ->
            // process event, for example
            showTemplateController = ShowTemplateController.show(
                this,
                event,
                object : ComposerJs() {
                    @JavascriptInterface
                    override fun customEvent(eventData: String) {
                        // process custom event by name here
                    }

                    @JavascriptInterface
                    override fun login(eventData: String) {
                        // process login request from template
                    }
                }
            )
        },
        NonSiteListener { event: Event<NonSite> ->
            // process Non Site event
        }
)
Composer.getInstance().getExperience(request, listeners) { exception: ComposerException ->
        // process exception
    }
}

Composer 1x

Maven Central

The Piano Composer C1x is available as an AAR via Maven Central. To add dependencies, open your project’s build.gradle/build.gradle.kts and update the dependencies block as follows:

dependencies {
    implementation("io.piano.android:composer-c1x:$VERSION")
}

Steps how to use Composer 1x:

  1. Replace your Composer.init(context, aid, endpoint) with PianoC1X.init(context, siteId, aid, endpoint), where siteId is Cxense Site ID

  2. Add url parameter to all your experience's requests to Composer

  3. Don't send Cxense PV events from screens with Composer

To show Content recommendations via the built-in controller you should add the following code:

// Kotlin
ShowRecommendationsController(event).show(activity)

Below you can find a code example of how to display Content recommendations from Composer 1x on mobile devices for more complex cases (e.g. displaying Content recommendations in RecyclerView):

// Kotlin
class RecommendationsAdapter(
    private val clickListener: (WidgetItem, String) -> Unit
): ListAdapter<WidgetItem, RecommendationViewHolder>(DIFF_CALLBACK) {
    private var trackingId = ""

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        RecommendationViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.recommendation_item, parent)) {
            clickListener(it, trackingId)
        }

    override fun onBindViewHolder(holder: RecommendationViewHolder, position: Int) {
        holder.updateView(getItem(position))
    }

    fun submitRecommendations(trackingId: String, data: List<WidgetItem>?) {
        this.trackingId = trackingId
        submitList(data)
    }

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<WidgetItem>() {
            override fun areItemsTheSame(oldItem: WidgetItem, newItem: WidgetItem): Boolean {
                // implement it for your case
                TODO("Not yet implemented")
            }

            override fun areContentsTheSame(oldItem: WidgetItem, newItem: WidgetItem): Boolean {
                // implement it for your case
                TODO("Not yet implemented")
            }

        }
    }
}

class RecommendationViewHolder(
    containerView: View,
    clickListener: (WidgetItem) -> Unit
): RecyclerView.ViewHolder(containerView) {
    lateinit var item: WidgetItem

    init {
        containerView.setOnClickListener { clickListener(item) }
    }

    fun updateView(widgetItem: WidgetItem) {
        item = widgetItem
        // update items
    }
}


// Kotlin
class RecommendationsDisplayActivity : AppCompatActivity() {
    val adapter = RecommendationsAdapter { item, trackingId ->
        // tracking for C1X
        CxenseSdk.getInstance().trackClick(item, object : LoadCallback<Unit> {
            override fun onError(throwable: Throwable) {
                Timber.e(throwable, "Can't track click on recommendation")
            }
            override fun onSuccess(data: Unit) {
                Timber.d("Tracked click on recommendation")
            }
        })
        Composer.getInstance().trackRecommendationsClick(trackingId, item.url)
        // process recommendation click. for example, start playing video, display news, etc...
    }
    val recommendationsListener = ShowRecommendationsListener { event: Event<ShowRecommendations> ->
        CxenseSdk.getInstance().loadWidgetRecommendations(
            widgetId = event.eventData.widgetId,
            experienceId = event.eventExecutionContext.experienceId,
            callback = object : LoadCallback<List<WidgetItem>> {
                override fun onError(throwable: Throwable) {
                    // process error at loading recommendations here
                    Timber.e(throwable, "Can't load widget recommendations")
                }
                override fun onSuccess(data: List<WidgetItem>) {
                    // recommendations are loaded, we can show them, for example via RecyclerView
                    val trackingId = event.eventExecutionContext.trackingId
                    adapter.submitRecommendations(trackingId, data)
                    Composer.getInstance().trackRecommendationsDisplay(trackingId)
                }
            }
        )
    }
    // other code here
}

Piano ID in Android

Dependencies

Maven Central

The Piano ID Android SDK is available as an AAR via mavenCentral. To add dependencies, open your project’s build.gradle and update the repositories and dependencies blocks as follows:

repositories {
   // ... other project repositories
   mavenCentral() // add it if you do not have it
}

// ...
android {
	...
	compileOptions {
              sourceCompatibility JavaVersion.VERSION_1_8
              targetCompatibility JavaVersion.VERSION_1_8
	}
}
dependencies {
   // ... other project dependencies
   implementation 'io.piano.android:id:$VERSION'
}

Piano ID requires adding a custom Redirect URI piano.id.oauth.://success to the Authorized Redirect URIs in the Piano ID configuration in the Publisher dashboard, especially if the "Authorize the list" toggle is enabled.

Endpoints

To interact with the Piano ID, you can use the endpoints defined in the constants. The Piano dashboard you’re using determines your ID endpoint: 

PianoId.ENDPOINT_PRODUCTION // Production endpoint
PianoId.ENDPOINT_PRODUCTION_EUROPE // Europe production endpoint
PianoId.ENDPOINT_PRODUCTION_AUSTRALIA // Australia production endpoint
PianoId.ENDPOINT_PRODUCTION_ASIA_PACIFIC // Asia/Pacific production endpoint
PianoId.ENDPOINT_SANDBOX // Sandbox endpoint

Initialization

Before using the Piano ID, you must initialize the settings:

class MyApplication : Application() {

   override fun onCreate() {
       super.onCreate()
       PianoId.init(PianoId.ENDPOINT_PRODUCTION, BuildConfig.PIANO_AID)
   }
}

Sign-in

Register processing for auth result (see here for more info).

private val authResult = registerForActivityResult(PianoIdAuthResultContract()) { r ->
    when (r) {
        null -> { /* user cancelled Authorization process */ }
        is PianoIdAuthSuccessResult -> {
            val token = r.token
            val isNewUserRegistered = r.isNewUser
            if (token.emailConfirmationRequired) {
                // process enabled Double opt-in
            }
            // process successful authorization 
        }
        is PianoIdAuthFailureResult -> {
            val e = r.exception
            // Authorization failed, check e.cause for details
        }
    }
}

Start auth with displaying UI to user:

authResult.launch(
    PianoId.signIn()
    // ... configure "Sign In" ...
)

Please note, that the activity loads pre-configured templates from the dashboard. Links in the template are processed differently:

  • normal link - opens within the app instead of the current page, user can return back via system button (the page will be reloaded)

  • link with target="_blank" - opens externally in browser

Sign-in settings

Change sign-in settings with these methods:

.widget(String widget)

Sets the screen when opening Piano ID. Use PianoId.WIDGET_LOGIN to open the login screen or PianoId.WIDGET_REGISTER to open the registration screen.

.disableSignUp()

Turns off the registration screen.

.stage(String stage)

Sets the stage directive element value, which can be used for showing or hiding parts of a template.

Override the progress bar by changing the style in xml:

HTML
<style name="Theme.Piano.IdAuth">
<item name="piano_id_progressbar_color">#FF6D00</item>
</style>

Social sign-in

Google sign-in

For authorization through Google, we recommend using the Google SDK for Android. The Piano SDK allows you to enable the Google SDK for authorization in the Piano ID. To do this, you must include dependencies and configure your application for Google Sign-In. Then enable the Google SDK support in the Piano SDK.

Google dependencies
Maven Central

To add dependencies, open your project’s build.gradle and update the repositories and dependencies blocks as follows:

dependencies {
   // ... other project dependencies
   implementation 'io.piano.android:id-oauth-google:$VERSION'
}
Google SDK support

To enable the Google SDK, you need to add the GoogleOAuthProvider class while setting up the Piano ID SDK:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        PianoId.init(...).with(GoogleOAuthProvider())
    }
}

Facebook sign-in

To use Facebook authorization, we highly recommend using the Facebook SDK for Android. The Piano SDK allows you to enable the Facebook SDK for authorization in the Piano ID. To do this, you must include dependencies and configure your application for Facebook. Then enable the Facebook SDK support in the Piano SDK.

Facebook dependencies
Maven Central

To add dependencies, open your project’s build.gradle and update the repositories and dependencies blocks as follows:

dependencies {
   // ... other project dependencies
   implementation 'io.piano.android:id-oauth-facebook:$VERSION'
}
Facebook SDK support

To enable the Facebook SDK, you need to add the FacebookOAuthProvider class while setting up the Piano ID SDK:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        PianoId.init(...).with(FacebookOAuthProvider())
    }
}

User information

To get user information, use the PianoID.getUserInfo function:

    PianoId.getUserInfo(token.accessToken) { r ->
            val customFields = r.getOrNull()
                ?.customFields
                ?.joinToString(prefix = "[", postfix = "]") { "${it.fieldName} = ${it.value}" }
            Timber.d("User custom fields = $customFields")
        }

An example of the data points returned by this function can be found below:

class PianoUserProfile(
    val email: String,
    val uid: String,
    val firstName: String,
    val lastName: String,
    val aid: String,
    val updated: Date,
    val token: String?,
    val linkedSocialAccounts: List<String>?,
    val passwordAvailable: Boolean,
    val customFields: List<CustomField>?,
    val allCustomFieldsFilled: Boolean?,
    val needResendConfirmationEmail: Boolean,
    val changedEmail: Boolean,
    val passwordless: Boolean
)

For updating user information, use the function PianoID.putUserInfo:

 val newUserInfo = PianoUserInfo("new_form")
            .customField("test0", listOf("value"))
            .customField("test1", "test")
            .customField("test2", true)
            .customField("test3", 5)
        PianoId.putUserInfo(token.accessToken, newUserInfo) { r2 ->
            val newCustomFields = r2.getOrNull()
                ?.customFields
                ?.joinToString(prefix = "[", postfix = "]") { "${it.fieldName} = ${it.value}" }
            Timber.d("Updated user custom fields = $newCustomFields")
        }

FAQ

Does the SDK apply to mobile web browser views?

No, the standard Composer script will function in all mobile web browsers.  

How do I remove the tinypass.com prompt?

To remove the consent from tinypass.com (Piano's SDK host), set the following method:

PianoID.shared.forceSFSafariViewControllerUsage = true;

How do I set the mobile session token length?

The token will be set to expire based on the Piano ID configuration in the Piano Dashboard.

Can I handle in-app purchases using the SDK?

In-app purchases are handled between an application and the device's App Store. There is no link between the mobile SDK and in-app purchases; these should be handled as separate processes completely.

Do you offer native login for apps besides Facebook and Google?

No, our SDK currently only offers native login for Facebook and Google. We also support Twitter, LinkedIn, and Apple social sign in.

Can the same user's session persist between a desktop and mobile device?

While users can log into multiple devices from the same account, sessions are separate between devices.

How to style templates (login and others) on mobile apps?

The SDK loads these templates as webpages, so embedded CSS is used. Note: The loading progress bar color for the Piano ID login should be customized on the app's side (Android example)

How does DOI (Double-opt in) work in apps?

Your app can check the "DOI enabled" flag after successful authentication. (Android example)

Can we use custom fields in the native apps?

Yes, you can use a ShowForm event to load a custom form as a webpage and show it inside the app. Custom fields on the Piano ID registration page are supported as well.

Is there any sample app for Android available?

Yes, you can access it here.

How can I ensure identity events are properly linked to visitors in Piano Analytics when using Auth Sync in a mobile app?

When using Auth Sync in a mobile app and calling the /identity/token/validation endpoint from a custom script, you must include the Device-Id header in the request to ensure identity.create events are associated with visitors in Piano Analytics.

On iOS, the device ID can be retrieved using PianoConfiguration.shared.deviceId. On Android, where no public API is currently available, the device ID can be read from SharedPreferences as a workaround. More details are available here.

Last updated: