Getting started
Prerequisites
Section titled “Prerequisites”Flutter Requirements
Section titled “Flutter Requirements”- Flutter SDK 3.9.2 or higher
- Dart SDK 3.9.2 or higher
Android Requirements
Section titled “Android Requirements”- Minimum SDK: API Level 26 (Android 8.0)
- Target SDK: API Level 35 recommended
- Java: Java 8+ or Kotlin support
iOS Requirements
Section titled “iOS Requirements”- iOS Version: iOS 15.0 or later
- Xcode Version: Xcode 15.0 or later
Before you begin
Section titled “Before you begin”- Register both apps. A Flutter project is two apps on the portal, one for Android and one for iOS, each with its own API key. On portal.byterialab.com, Apps → Register App: once for Android (your
applicationId), once for iOS (your bundle identifier), and generate an API key for each. See How to Register Your App. - Export your registry key. On every path the SDK’s native binaries (
Alphyn.xcframeworkfor iOS, thecom.byterialab:alphyn-sdkAAR for Android) resolve from the Alphyn package registry at build time, so set your app API key in the build environment (and never commit it); see SDK Registry Access:
export ALPHYN_REGISTRY_KEY=<YOUR_APP_API_KEY>Install the SDK
Section titled “Install the SDK”The Alphyn Flutter SDK is a federated plugin of four packages (alphyn_sdk, alphyn_sdk_android,
alphyn_sdk_ios, alphyn_sdk_platform_interface), served from the Alphyn package registry rather
than pub.dev.
Option A: the Alphyn CLI (recommended)
Section titled “Option A: the Alphyn CLI (recommended)”One command adds the plugin, wires both native layers, and installs the build-registration hooks:
alphyn-cli integrate --android-api-key <ANDROID_APP_KEY> --ios-api-key <IOS_APP_KEY>flutter pub getalphyn-cli doctorIf you use the CLI, the Platform Setup and Register every build steps below are done for you; read on to see or customize them.
Option B: from the registry, by hand (no CLI)
Section titled “Option B: from the registry, by hand (no CLI)”Add the plugin as a hosted pub dependency, nothing to download. Register the pub token (it reads your key from ALPHYN_REGISTRY_KEY, so no secret is written to disk), add the dependency, and fetch:
dart pub token add https://packages.byterialab.com/pub --env-var ALPHYN_REGISTRY_KEYdependencies: alphyn_sdk: hosted: https://packages.byterialab.com/pub version: <version>To find the latest <version>, ask the registry GET https://packages.byterialab.com/pub/api/packages/alphyn_sdk and read .latest.version. Then fetch:
flutter pub getOn this manual path the Platform Setup, Initialization, and Register every build steps below are required (the CLI does them for you).
Platform Setup
Section titled “Platform Setup”Android
Section titled “Android”The SDK’s AAR declares every permission it needs and Android’s manifest merger adds them to your
app automatically. You do not need to copy them into android/app/src/main/AndroidManifest.xml.
For transparency, the merged set is:
Merged permissions
Section titled “Merged permissions”<!-- Internet access for security checks and threat detection --><uses-permission android:name="android.permission.INTERNET" />
<!-- Network state access to determine connectivity --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Certificate access for keystore operations --><uses-permission android:name="com.android.keystore.CERTIFICATE_ACCESS" />
<!-- Credential usage for secure operations --><uses-permission android:name="android.permission.USE_CREDENTIALS" />
<!-- Device identity used by the attestation payload --><uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Overlay protection (Android 12+) --><uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />What the merged manifest looks like
Section titled “What the merged manifest looks like”You write none of this; it is the result after the merger runs.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<!-- Required Permissions --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="com.android.keystore.CERTIFICATE_ACCESS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
<application android:label="your_app_name" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> <!-- Your application components --> </application></manifest>Permission Details:
INTERNET: Required for communicating with Alphyn security servicesACCESS_NETWORK_STATE: Needed to check network connectivity before performing security checksCERTIFICATE_ACCESS: Used for keystore certificate operations during security validationUSE_CREDENTIALS: Required for secure credential managementREAD_PHONE_STATE: Device identity used by the attestation payloadHIDE_OVERLAY_WINDOWS: Overlay protection on Android 12 and later
Gradle Configuration
Section titled “Gradle Configuration”Ensure your app uses the required minimum SDK and register the authenticated Alphyn registry in your Android Gradle repositories.
Minimum SDK
minSdkVersionmust be 26 or higher
Registry Maven (AAR)
The Android native (com.byterialab:alphyn-sdk) is served from the Alphyn package registry. Add the
authenticated registry to your Android build.gradle / build.gradle.kts; alphyn-cli integrate
writes this for you:
Groovy:
allprojects { repositories { google() mavenCentral() maven { url System.getenv('ALPHYN_REGISTRY_URL') ?: 'https://packages.byterialab.com/maven' credentials { username = 'x' password = System.getenv('ALPHYN_REGISTRY_KEY') ?: '' } } }}Kotlin DSL:
allprojects { repositories { google() mavenCentral() maven { url = uri(System.getenv("ALPHYN_REGISTRY_URL") ?: "https://packages.byterialab.com/maven") credentials { username = "x" password = System.getenv("ALPHYN_REGISTRY_KEY") ?: "" } } }}The build reads your app API key from ALPHYN_REGISTRY_KEY; see
SDK Registry Access.
ProGuard / R8 Configuration
Section titled “ProGuard / R8 Configuration”The Alphyn AAR ships consumer ProGuard rules that R8 applies to your app automatically, so no manual rules are required for a standard build. If your build pipeline strips consumer rules, add them manually:
Step 1: Create or edit android/app/proguard-rules.pro file:
# Alphyn SDK - Byteria# Keep all Alphyn SDK classes and methods-keep class com.byteria.sdk.** { *; }
# Keep classes annotated with @Keep-keep @androidx.annotation.Keep class * { *; }
# Keep methods annotated with @Keep-keepclassmembers class * { @androidx.annotation.Keep <methods>;}Step 2: Reference the ProGuard rules in your android/app/build.gradle (or build.gradle.kts):
For build.gradle (Groovy):
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } }}For build.gradle.kts (Kotlin DSL):
android { buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } }}Why These Rules Are Needed:
-
The SDK uses reflection and dynamic class loading for security features
-
ProGuard/R8 may remove or rename SDK classes, breaking functionality
-
These rules ensure the SDK’s security mechanisms work correctly in release builds
-
Without these rules, you may experience crashes or unexpected behavior in production
-
Always test your release build thoroughly after adding ProGuard rules
-
Manual rules are only needed if your build pipeline strips the AAR’s consumer rules
-
The SDK’s security features depend on proper class and method preservation
The iOS implementation requires two configurations in your ios/Runner/Info.plist file:
Podfile Platform Target
Section titled “Podfile Platform Target”Ensure your ios/Podfile sets the minimum iOS version:
# Uncomment this line to define a global platform for your projectplatform :ios, '15.0'1. Background Modes (Required)
Section titled “1. Background Modes (Required)”The SDK requires background modes to perform security checks. Add the following to your Info.plist:
Option A: Edit Info.plist directly
Add the following inside the main <dict> section:
<!-- Background Task Scheduler Permitted Identifiers --><key>BGTaskSchedulerPermittedIdentifiers</key><array> <string>com.byterialab.backgroundcheck</string></array>
<!-- Background Modes --><key>UIBackgroundModes</key><array> <string>fetch</string></array>Note: You can also configure this through Xcode if preferred, but editing Info.plist directly is simpler and ensures all required keys are properly set, especially the BGTaskSchedulerPermittedIdentifiers which is critical for background task registration.
2. Network Security Configuration
Section titled “2. Network Security Configuration”Add the following configuration to allow network access for security checks:
<key>NSAppTransportSecurity</key><dict> <key>NSExceptionDomains</key> <dict> <key>alphyn-attestation-api.byterialab.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSIncludesSubdomains</key> <true/> </dict> </dict></dict>3. URL Scheme Query Permissions (Required)
Section titled “3. URL Scheme Query Permissions (Required)”The SDK requires permission to query for jailbreak-related URL schemes to detect jailbreak apps on the device. Add the following to your Info.plist:
<!-- URL Scheme Query Permissions --><key>LSApplicationQueriesSchemes</key><array> <string>cydia</string> <string>sileo</string> <string>zbra</string> <string>filza</string> <string>undecimus</string> <string>installer</string> <string>taig</string> <string>dopamine</string> <string>trollstore</string> <string>trollstorehelper</string></array>Complete iOS Info.plist Example
Section titled “Complete iOS Info.plist Example”<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <!-- Existing keys... -->
<!-- Background Task Scheduler Identifiers --> <key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>com.byterialab.backgroundcheck</string> </array>
<!-- Background Modes --> <key>UIBackgroundModes</key> <array> <string>fetch</string> </array>
<!-- Network Security Configuration --> <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>alphyn-attestation-api.byterialab.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>
<!-- URL Scheme Query Permissions --> <key>LSApplicationQueriesSchemes</key> <array> <string>cydia</string> <string>sileo</string> <string>zbra</string> <string>filza</string> <string>undecimus</string> <string>installer</string> <string>taig</string> <string>dopamine</string> <string>trollstore</string> <string>trollstorehelper</string> </array></dict></plist>These configurations allow the SDK to:
- Register and schedule background tasks using
BGTaskScheduler(viaBGTaskSchedulerPermittedIdentifiers) - Perform background security checks and monitoring using
BGAppRefreshTask(viaUIBackgroundModeswithfetch) - Communicate with the Alphyn security services for threat detection and device verification (via
NSAppTransportSecurity) - Check for jailbreak apps on the device (via
LSApplicationQueriesSchemes)
Important Notes for Info.plist:
- The
BGTaskSchedulerPermittedIdentifierskey is required and must includecom.byterialab.backgroundcheck. - The
fetchbackground mode is required forBGAppRefreshTaskto allow background security checks. - The
LSApplicationQueriesSchemeslist is what the jailbreak detector probes.canOpenURLreturns false for any scheme the host app has not declared, so a shortened list silently narrows detection and produces no error. - The
NSAppTransportSecurityexception is required; the SDK cannot reach the backend without it. The attestation host presents a certificate from a private CA (CN=Byteria Root CA) that the system trust store does not carry, so without the exception the connection is refused inside ATS with TLS error-9802and the SDK’s own certificate check is never reached, so init fails at launch.NSExceptionAllowsInsecureHTTPLoadsis the key that carries the connection past ATS; the SDK then validates the chain itself against a root anchor bundled inAlphyn.framework, and that pinning stays the effective transport control. The exception is scoped to that one domain and weakens nothing else. - After adding these configurations, clean and rebuild your project. If you encounter registration errors related to background tasks, delete the app from your device/simulator and reinstall it.
4. AppDelegate Background Task Registration (Required)
Section titled “4. AppDelegate Background Task Registration (Required)”You must call AlphynSDK.register() synchronously in your AppDelegate.swift before Flutter starts. This registers background tasks with the iOS system.
Add the following to your AppDelegate.swift:
import Alphynimport Flutterimport UIKit
@main@objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // CRITICAL: Register background tasks BEFORE Flutter starts do { try AlphynSDK.register() } catch { print("AlphynSDK.register() failed: \(error.localizedDescription)") }
GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }}Important:
AlphynSDK.register()must be called synchronously indidFinishLaunchingWithOptionsbeforeGeneratedPluginRegistrant.register(). Background task registration cannot be deferred to Dart code because iOS requires it during app launch.
Initialization
Section titled “Initialization”You should initialize the SDK in your Dart code, preferably in your main() function before running the app.
import 'package:alphyn_sdk/alphyn_sdk.dart';import 'package:flutter/foundation.dart'; // kDebugModeimport 'package:flutter/material.dart';
void main() async { WidgetsFlutterBinding.ensureInitialized();
// Initialize the SDK. The debug hashes are development-only and each // platform has its own, because a Flutter project registers as two // separate Alphyn apps. await AlphynSdk.initialize( interval: 45.0, androidDebugHash: kDebugMode ? 'YOUR_ANDROID_DEBUG_HASH' : null, iosDebugHash: kDebugMode ? 'YOUR_IOS_DEBUG_HASH' : null, );
runApp(const MyApp());}Parameters:
interval: Interval in seconds between security scans (e.g.,45.0for 45 seconds). Defaults to 45.0.androidDebugHash: optional development-only hash from the Alphyn Portal, applied only when running on AndroidiosDebugHash: the same, applied only when running on iOS. Each platform is a separate Alphyn app with its own hashes. Do not ship either in production.
Register every build
Section titled “Register every build”Alphyn is fail-closed: a build whose hash was never registered terminates at launch, with no build-time error. On the CLI path the hooks below are installed for you; on the manual path you set them up yourself.
- Android. The app hash is the SHA-256 of your signing certificate, so it is stable across builds and you register it once per signing key. Run the SDK-provided
post-action-android.sh <apk-path> <YOUR_ANDROID_API_KEY>after each signed build. For Play App Signing, also enroll Google’s re-signing certificate once; see Play App Signing. - iOS. A build registers at archive time through an Xcode archive post-action; set it up once: Register via Xcode post-action. Debug and simulator builds never register, which is why development needs the pinned
iosDebugHashabove.