Skip to main content
The Android SDK is the library com.plugchoice:plugchoice, for Kotlin apps. It shows Link, the hosted flow at connect.plugchoice.com, in a full-screen activity, and does what a web page can’t: join a charger’s Wi-Fi, find and reach chargers on the local network, talk Bluetooth to them and scan a QR code.

Install

Requirements: Android 10 (API 29) or later (minSdk 29), compileSdk 36, and JDK 17. Bluetooth on Android 12 and later needs your app to target API 31 or later. Scanning a charger’s QR code uses Google Play services; on a device without them, the user types the code instead. The library is com.plugchoice:plugchoice on Maven Central. Make sure mavenCentral() is in your repositories (it usually is), then add the dependency to your app module:
The public API is in the package com.plugchoice.

Configure your app

Permissions

The library’s manifest adds every permission it uses to your app’s manifest. You don’t add any. The SDK asks for the runtime ones only when the flow needs them. Bluetooth LE is declared as an optional feature, so devices without it can still install your app. To leave Bluetooth out, remove the four Bluetooth permissions in your manifest with tools:node="remove"; the SDK then doesn’t offer it. Bluetooth on Android 12 and later also needs your app to target API 31 or later.

Plain HTTP to chargers

Some chargers serve their local API over plain HTTP on their own Wi-Fi: Peblar answers at http://172.16.0.1. Android blocks plain HTTP by default, and the SDK’s requests follow your app’s network security configuration, so allow it for that address only:
res/xml/network_security_config.xml
AndroidManifest.xml
If your app already has a network security configuration, add the domain-config to it. Without this, Peblar chargers can’t be set up in your app. The other chargers the SDK sets up today use HTTPS or Bluetooth.

Google Play data safety

Scanning a charger’s QR code uses Google’s code scanner from Google Play services. It needs no camera permission, but its ML Kit components send usage data to Google. Mention it in your app’s data safety form.

Create the SDK

Create one Plugchoice instance and keep it for your app’s lifetime, for example in your Application or a singleton. Give it a callback that fetches a client secret from your server:
The callback calls your own endpoint, which creates a client session scoped to the action and returns its secret. Get started shows that endpoint. The callback runs on the main thread, so make the call with a suspending client. With OkHttp, it can look like this:
The SDK calls fetchClientSecret when Link opens, while the hosted flow loads. It calls it again, with the same action, whenever the secret expires (after 60 minutes), so a user can take as long as they need. The secret never goes into a URL or an intent, and the SDK never logs it. Register the SDK’s activity result contract, then launch it with an action:
In Jetpack Compose:
Without the Activity Result API, start plugchoice.link.intent(context, action) for a result, and read it in onActivityResult with plugchoice.link.parseResult(resultCode, data). The actions: The SDK passes the action to the hosted flow without reading it, so a new action works through custom before it gets a helper. Your client session’s scope must cover the action’s charger or site. Actions explains each one. Link handles rotation, dark mode and keyboard changes itself, so the flow never reloads. It keeps the screen on while it’s open, because a charger’s Wi-Fi connection drops when the phone locks.

Handle the result

The contract returns a LinkResult:
LinkResult.Status
SUCCESS, CANCELLED or ERROR.
String
The action the link session did. The user may have picked another one from the list of what a charger can do; otherwise it’s the action you opened.
String?
The link session, when the hosted flow started one. null when Link closed before that.
List<Device>
The devices the link session reported, each Device(type, id). On SUCCESS, the devices it finished. type is "charger" (Device.TYPE_CHARGER) today; ignore types you don’t know.
LinkError?
On ERROR: a code, and a message for your logs.
The result is for your app’s UI. Before you rely on it, your server confirms it with Get a link session (GET /sdk/v1/link-sessions/{id}). Link sessions explains why.

Errors

On ERROR, result.error?.code says why. The SDK sets two codes itself: Every other code comes from the hosted flow. The one to know is clientSecretUnavailable (LinkError.CLIENT_SECRET_UNAVAILABLE): your fetchClientSecret threw, returned an empty string or took longer than 30 seconds. The user then sees this screen, with Try again, and the result reports clientSecretUnavailable if they close it. The same screen shows when Android recreated Link after your app’s process died: the Plugchoice instance is gone, so the user starts again from your app. Other codes are for your logs; don’t branch on them. Errors lists them.

Show actions where they work

Not every charger can do every action, and not every phone has what an action needs. Show a button only when both are true:
  • The charger’s capability for it is capable. Your server reads it with Get a charger.
  • Every transport in the capability’s needs is in Plugchoice.transports(context).
Plugchoice.transports(context) asks for no permission. It returns wifi (on a device with Wi-Fi), http, socket and lan, and ble when the device has Bluetooth LE and your app kept the SDK’s Bluetooth permissions.

Test on a real device

The emulator can open Link, but it can’t reach a charger. Use a phone for:
  • joining a charger’s Wi-Fi, and the system’s “connect to device” prompt
  • finding chargers on the home Wi-Fi
  • everything Bluetooth, and its permission prompts
  • scanning a QR code
The example app opens Link with a client secret you paste, for any action.