Supported baseline: Android API 23+, Java 11 bytecode. The supplied AAR contains Kotlin/Java wrappers, consumer R8 rules, and native libraries for arm64-v8a, armeabi-v7a, x86, and x86_64.
Install the private AAR
Section titled “Install the private AAR”Your onboarding instructions provide a private Maven repository or a local repository directory.
dependencyResolutionManagement { repositories { maven { url = uri(requireNotNull(System.getenv("P2PSDK_MAVEN_URL"))) credentials { username = System.getenv("P2PSDK_MAVEN_USER") password = System.getenv("P2PSDK_MAVEN_TOKEN") } } google() mavenCentral() }}dependencies { implementation("com.p2psdk:p2p-sdk-android:1.0.0")}For a local onboarding repository, replace the private repository block with maven { url = uri("../p2psdk-maven") }. Do not add mavenLocal() to production builds unless your release process intentionally publishes there.
The consent URL, revoke URL, version, and public verification key are compiled into the delivered AAR. Application code cannot replace them at runtime.
Manifest permissions
Section titled “Manifest permissions”Every integration needs:
<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />Background mode additionally requires:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" /><uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application> <service android:name="com.p2psdk.P2PSdkBackgroundService" android:exported="false" android:foregroundServiceType="specialUse"> <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Maintains the user-visible P2P SDK connection while app UI is minimized." /> </service></application>Review Google Play foreground-service declarations when distributing an app that enables this mode. On Android 13+, request notification permission where your product flow requires it.
Kotlin integration
Section titled “Kotlin integration”Create from a visible Activity whenever consent may need to be shown. Own the accepted instance in an application-level controller or service, not a short-lived composable.
class SdkController( private val scope: CoroutineScope,) { private var sdk: P2PSdkKt? = null
suspend fun start(activity: Activity, apiKey: String) { when (val result = P2PSdkKt.create(activity, apiKey) { debug(BuildConfig.DEBUG) operationDispatcher(Dispatchers.IO) callbackDispatcher(Dispatchers.Main.immediate) onConnect { Log.i("P2PSDK", "connected") } onDisconnect { reason -> Log.w("P2PSDK", "disconnected: $reason") } callbackErrorHandler { callback, error -> Log.e("P2PSDK", "callback failed: $callback", error) } }) { is P2PSdkKt.InitResult.Accepted -> { sdk = result.sdk scope.launch { result.sdk.events.collect { event -> // Drive product state from lifecycle events. } } check(result.sdk.connect()) { "P2PSDK supervisor did not start" } } else -> Log.i("P2PSDK", "consent result: $result") } }
fun close() { sdk?.close() sdk = null }}connect() is a suspend function in the Kotlin wrapper. A successful return does not mean online; wait for LifecycleEvent.Connected or observe the wrapper state.
Java integration
Section titled “Java integration”public final class SdkController implements AutoCloseable { private P2PSdk sdk;
public void start(Activity activity, String apiKey) { P2PSdk.builder(activity, apiKey) .debug(BuildConfig.DEBUG) .callbackExecutor(activity.getMainExecutor()) .onConnect(() -> Log.i("P2PSDK", "connected")) .onDisconnect(reason -> Log.w("P2PSDK", "disconnected: " + reason)) .callbackErrorHandler((callback, error) -> Log.e("P2PSDK", "callback failed: " + callback, error)) .create(result -> { if (!result.isAccepted()) { Log.i("P2PSDK", "consent result: " + result.status()); return; } sdk = result.sdk(); if (!sdk.connect()) { sdk.close(); sdk = null; throw new IllegalStateException("P2PSDK supervisor did not start"); } }); }
@Override public void close() { if (sdk != null) { sdk.close(); sdk = null; } }}Background mode
Section titled “Background mode”Background mode is disabled by default. Enable it only when product policy and store review allow an ongoing foreground service.
P2PSdk.BackgroundNotificationOptions notification = P2PSdk.BackgroundNotificationOptions.builder() .channelId("p2psdk_connection") .channelName("SDK connection") .title("Connection active") .text("Background network participation is active") .smallIconResId(R.drawable.ic_stat_p2psdk) .build();
P2PSdk.builder(activity, apiKey) .enableBackgroundMode(true) .backgroundNotificationOptions(notification) .create(callback);Call connect() from an OS-allowed foreground path. Android 12+ can reject background foreground-service starts. The SDK does not survive force-stop, add boot autostart, or keep the device awake.
Revoke and shutdown
Section titled “Revoke and shutdown”sdk.revokeConsent(result -> { if (result.isRevoked()) { sdk = null; // The successful revoke closed the instance. } else { Log.e("P2PSDK", "revoke failed: " + result.status(), result.error()); }});Use disconnect() to pause a reusable instance and close() for terminal release. Do not call methods after close() or successful revoke.
Android verification
Section titled “Android verification”- Test phone and tablet consent layouts, rotation, cancel, decline, accept, and an invalid/expired decision.
- Confirm callbacks arrive on the configured executor and exceptions reach the error handler.
- Test minimize, screen off, denied notification permission, and rejected service start.
- Verify
close()removes callbacks, stops any SDK foreground-service session, and frees the native handle.