Usage
Note: The SDK must be initialized before use. On iOS, call
AlphynSDK.register()in your AppDelegate (see Platform Setup). Then initialize the SDK from Dart in yourmain()function (see Initialization). All Dart APIs are available after initialization is complete.
Checking Initialization Status
Section titled “Checking Initialization Status”import 'package:alphyn_sdk/alphyn_sdk.dart';
// Returns: Future<bool?>// - true: SDK is successfully initialized and ready to use// - false: SDK initialization failed or was not called// - null: Initialization status cannot be determinedfinal isInitialized = await AlphynSdk.isInitialized();if (isInitialized == true) { print('✅ SDK initialized successfully'); // Output: ✅ SDK initialized successfully} else { print('❌ SDK not initialized');}Purpose: Verifies that the SDK was properly initialized on the native side. This should be the first call you make before using any other SDK functionality. Always check this status before attempting to retrieve device information or perform security scans.
Real Output Example:
[AlphynSdkManager] checkInitialization() called[AlphynSdkManager] SDK initialization status: true[ExampleApp] SDK initialized successfullyDevice Information
Section titled “Device Information”Get Device Identifier
Section titled “Get Device Identifier”// Returns: Future<String>// A unique identifier for the device, used for tracking and security verification// This identifier is persistent across app sessions and is generated by the SDKfinal deviceId = await AlphynSdk.getDeviceId();print('Device ID: $deviceId');// Output: Device ID: 817D56BE-0BC4-4CE4-8516-8F582EEBE0FCPurpose: Retrieves a unique, persistent identifier for the device. This ID is essential for:
- Device tracking across sessions
- Security event correlation
- Device fingerprinting
- User verification processes
Get Application Hash
Section titled “Get Application Hash”// Returns: Future<String>// A cryptographic hash of the application binary// Used to verify app integrity and detect tampering or modificationsfinal appHash = await AlphynSdk.getAppHash();print('App Hash: $appHash');// Output: App Hash: 64f3f5b47a856403dc48bfbaac0fcdb89f414f63dafb9c18e8b6d87f2a43caecPurpose: Generates and returns a cryptographic hash of your application. This hash is critical for:
- Detecting app tampering or unauthorized modifications
- Verifying application integrity
- Ensuring the app has not been repackaged or altered
- Compliance and security auditing
Security Scanning
Section titled “Security Scanning”Get Current Scan Results
Section titled “Get Current Scan Results”// Returns: Future<String?>// The most recent security scan result as a string// Contains detailed information about the current security state of the device/app// Returns null if no scan has been performed or SDK is not initializedfinal scanResult = await AlphynSdk.getScanResult();if (scanResult != null) { print('Scan Result: $scanResult');} else { print('No scan result available');}
// Example output: 'SIMULATOR_RUNTIME'// or 'FRIDA_DETECTED'// or null if no scan performedPurpose: Retrieves the most current security scan results. This provides real-time information about:
- Current security threats detected
- Device security posture
- Active security violations
- Overall security status
Use this to make immediate security decisions (e.g., blocking features, logging out users).
Get Security Rejection Reasons
Section titled “Get Security Rejection Reasons”// Returns: Future<List<String>>// A list of specific security issues that triggered rejection or warnings// Each string describes a distinct security concern detected// getRejectReasons() returns a newline-separated string; split it into a listfinal rejectReasonsRaw = await AlphynSdk.getRejectReasons();final rejectReasons = rejectReasonsRaw.split('\n').where((line) => line.trim().isNotEmpty).toList();print('Rejection Reasons: $rejectReasons');
// Example output:// [// 'DETECTION: COMMON_SUSPICIOUS_PATH Common suspicious file path accessible',// 'DETECTION: SIMULATOR_ENVIRONMENT Simulator environment detected',// 'DETECTION: SIMULATOR_RUNTIME Simulator runtime detected',// 'DETECTION: DEBUGGER_SYSTEM_CHECK Debugger detected (system check)',// 'DETECTION: FRIDA_DETECTED Frida traces detected',// 'DETECTION: VPN_IN_USE VPN in use'// ]
for (var reason in rejectReasons) { print('Security Issue: $reason');
// Parse detection type and description if (reason.startsWith('DETECTION:')) { final parts = reason.substring(11).split(' '); final detectionType = parts.first; print(' Type: $detectionType'); }}Purpose: Returns a detailed list of all security violations or concerns detected during scanning. Each reason represents:
- A specific security threat or risk factor
- The type of violation (e.g., jailbreak, debugger, emulator)
- Issues that may require app restrictions or user warnings
Use this to:
- Display specific security warnings to users
- Log detailed security events
- Implement granular security policies based on threat types
Get Last Scan Date
Section titled “Get Last Scan Date”// Returns: Future<DateTime?>// The timestamp when the last security scan was completed// Returns null if no scan has been performed yetfinal lastScanDate = await AlphynSdk.getLastScanDate();if (lastScanDate != null) { print('Last Scan: ${lastScanDate.toIso8601String()}'); // Output: Last Scan: 2025-11-20T11:21:28.000Z
print('Time since last scan: ${DateTime.now().difference(lastScanDate)}'); // Output: Time since last scan: 0:00:02.456789} else { print('No scan performed yet');}Purpose: Provides the exact timestamp of the last completed security scan. Useful for:
- Determining scan freshness
- Calculating time intervals between scans
- Triggering manual scans if too much time has passed
- Audit logging and compliance reporting
Verify High-Risk Actions
Section titled “Verify High-Risk Actions”signAction signs with a hardware-backed key that belongs to one enrolled user, so
enrollForMfa(userId) must have run once on this device first, and userId below is your own
identifier for the logged-in user. The PIN is optional. See
MFA Transaction Signing for the full flow.
// Returns: Future<ActionVerificationResult>// Verifies a high-risk action with the Alphyn backend// Used for sensitive operations like payments, data transfers, etc.
final result = await AlphynSdk.signAction( userId: userId, actionLabel: 'payment_transfer', context: { 'amount': '1000.00', 'currency': 'USD', 'timestamp': DateTime.now().toIso8601String(), },);
if (result.success) { print('✅ Action verified successfully'); print('Token: ${result.token}'); print('Expires at: ${result.expiresAtEpochMs != null ? DateTime.fromMillisecondsSinceEpoch(result.expiresAtEpochMs!) : 'N/A'}');
// Proceed with the high-risk action using the verification token proceedWithAction(result.token!);} else { print('❌ Action verification failed'); print('Error Code: ${result.errorCode}'); print('Error Message: ${result.errorMessage}');
// Block the action or show error to user showErrorToUser(result.errorMessage ?? 'Verification failed');}Purpose: Verifies high-risk actions with the Alphyn backend before execution. This provides an additional layer of security for sensitive operations by:
- Validating the action context with the backend
- Receiving a verification token for the action
- Detecting suspicious patterns or unauthorized attempts
- Enabling action-level security policies
Parameters:
actionLabel(required): A string identifier for the action type (e.g.,'payment_transfer','sensitive_data_access')context(required): A map containing contextual information about the action. This is forwarded to the backend for verification.
Returns: Future<ActionVerificationResult> with the following properties:
success(bool): Whether the verification was successfultoken(String?): Verification token if successful (use this to proceed with the action)expiresAtEpochMs(int?): Token expiration timestamp in milliseconds since epocherrorCode(String?): Error code if verification failederrorMessage(String?): Human-readable error message if verification failed
Use Cases:
- Payment transactions
- Sensitive data transfers
- Administrative operations
- Account modifications
- Any operation requiring additional verification
Example: Payment Verification
Future<void> processPayment({ required double amount, required String recipient,}) async { // Verify the payment action before processing final verification = await AlphynSdk.signAction( userId: userId, actionLabel: 'payment_transfer', context: { 'amount': amount.toString(), 'currency': 'USD', 'recipient': recipient, 'timestamp': DateTime.now().toIso8601String(), 'user_id': currentUserId, }, );
if (!verification.success) { throw PaymentException( 'Payment verification failed: ${verification.errorMessage}', ); }
// Use the verification token when processing the payment await paymentService.transfer( amount: amount, recipient: recipient, verificationToken: verification.token!, );}Advanced Features
Section titled “Advanced Features”Get All Risk Factors
Section titled “Get All Risk Factors”// Returns: Future<List<String>>// A comprehensive list of all risk factors detected across all scans// Includes cumulative security concerns, not just current threatsfinal riskFactors = await AlphynSdk.getAllRiskFactors();print('Total Risk Factors: ${riskFactors.length}');
// Example output:// [// 'COMMON_SUSPICIOUS_PATH',// 'SIMULATOR_ENVIRONMENT',// 'SIMULATOR_RUNTIME',// 'DEBUGGER_SYSTEM_CHECK',// 'DEBUGGER_PROCESS_CHECK',// 'DEBUGGER_EXCEPTION_CHECK',// 'VPN_IN_USE',// 'FRIDA_DETECTED',// 'FRIDA_SERVER_RUNNING'// ]
for (var factor in riskFactors) { print('Risk Factor: $factor');}Purpose: Returns a complete list of all security risk factors detected. This includes:
- Historical security issues
- Cumulative risk assessment data
- All threat categories identified
- Device security profile information
Use this for:
- Comprehensive security reporting
- Risk scoring and analysis
- Security dashboards
- Historical threat tracking
Get All Scan Results with Date Filtering
Section titled “Get All Scan Results with Date Filtering”// Returns: Future<List<String>>// A list of all scan results, optionally filtered by date range// Each string represents a complete scan report from a specific time
// Get all scan results (no filter)final allResults = await AlphynSdk.getAllScanResults();
// Get scan results from the last 7 daysfinal lastWeek = DateTime.now().subtract(Duration(days: 7));final recentResults = await AlphynSdk.getAllScanResults( startEpochMs: lastWeek.millisecondsSinceEpoch, endEpochMs: DateTime.now().millisecondsSinceEpoch,);
print('Total scans: ${allResults.length}');print('Recent scans (7 days): ${recentResults.length}');
// Example output:// [// 'ScanResult(date: 2025-11-20 11:21:29 +0000, detections: ["Detection: COMMON_SUSPICIOUS_PATH Severity: HIGH", "Detection: SIMULATOR_RUNTIME Severity: CRITICAL"])',// 'ScanResult(date: 2025-11-20 11:21:30 +0000, detections: ["Detection: FRIDA_DETECTED, FRIDA_SERVER_RUNNING Severity: CRITICAL"])'// ]
// Parse scan resultsfor (var scanResult in recentResults) { print('Scan: $scanResult');
// Extract date and detections from the string if (scanResult.contains('date:')) { // Parse the scan result string as needed }}Purpose: Retrieves historical scan data with optional date range filtering. This allows you to:
- Analyze security trends over time
- Generate historical security reports
- Track security improvements or degradation
- Export scan history for compliance
- Filter scans by specific time periods
Parameters:
startEpochMs(optional): Beginning of the date range in milliseconds since epoch (inclusive)endEpochMs(optional): End of the date range in milliseconds since epoch (inclusive)- If both omitted: Returns all available scan results
Update Scan Interval
Section titled “Update Scan Interval”// Returns: Future<void>// Updates the scan interval in seconds
await AlphynSdk.setInterval(60.0); // Set to 60 secondsprint('Scan interval updated to 60 seconds');Purpose: Updates the interval between automatic security scans. This allows you to:
- Adjust scan frequency based on app state
- Balance between security coverage and performance
- Reduce battery usage when appropriate
Parameters:
intervalSeconds(required): The new interval in seconds (must be greater than 8)
Note: The interval must be greater than 8 seconds. Attempting to set a lower value will result in an error.
Get Security Modules
Section titled “Get Security Modules”// Returns: Future<List<String>>// A list of security modules loaded by the SDK
final modules = await AlphynSdk.getModules();print('Loaded modules: ${modules.length}');
for (var module in modules) { print('Module: $module');}
// Example output: ['NetworkSecurity', 'DeviceIntegrity', 'AppVerification']Purpose: Retrieves the list of security modules currently loaded by the SDK. This provides:
- Visibility into which security checks are active
- Debugging information for troubleshooting
- Verification that expected modules are loaded
Use this for:
- Security auditing
- Diagnostics and troubleshooting
- Verifying SDK configuration
Security Event Listeners (Cross-Platform)
Section titled “Security Event Listeners (Cross-Platform)”The SDK provides a stream-based security event listener that works on both Android and iOS. This allows you to receive real-time security events from the native SDK in a reactive, Flutter-friendly way.
Using Security Events Stream
Section titled “Using Security Events Stream”The securityEvents() method returns a Stream<AlphynCallbackResult> that emits security events from the native SDK. This works on both Android and iOS.
import 'package:alphyn_sdk/alphyn_sdk.dart';import 'dart:async';
// Subscribe to security eventsfinal subscription = AlphynSdk.securityEvents().listen( (event) { print('Event Type: ${event.originalEventType}'); print('Operation: ${event.operationType}'); print('Result: ${event.operationResult}'); print('Message: ${event.message}'); print('Details: ${event.details}');
// Handle different event types switch (event.originalEventType) { case AlphynEventType.threatDetected: print('🚨 Threat detected!'); handleThreat(event); break; case AlphynEventType.scanSuccess: print('✅ Scan completed successfully'); break; case AlphynEventType.initComplete: print('✅ SDK initialized'); break; case AlphynEventType.networkError: print('⚠️ Network error occurred'); break; default: print('Event: ${event.originalEventType}'); } }, onError: (error) { print('Error in security events stream: $error'); },);
// Don't forget to cancel the subscription when done// subscription.cancel();Key Points:
- Works on both Android and iOS
- Automatically set up when you first access the stream
- Multiple subscribers can listen to the same stream
- Events are emitted on the main thread
- Always cancel subscriptions in
dispose()to prevent memory leaks
Complete Example
Section titled “Complete Example”import 'package:flutter/material.dart';import 'package:alphyn_sdk/alphyn_sdk.dart';import 'dart:async';
class SecurityMonitor extends StatefulWidget { @override _SecurityMonitorState createState() => _SecurityMonitorState();}
class _SecurityMonitorState extends State<SecurityMonitor> { StreamSubscription<AlphynCallbackResult>? _subscription; List<AlphynCallbackResult> _events = [];
@override void initState() { super.initState(); _setupListener(); }
void _setupListener() { // Subscribe to security events stream _subscription = AlphynSdk.securityEvents().listen( (event) { setState(() { _events.insert(0, event); // Add to beginning // Keep only last 50 events if (_events.length > 50) { _events = _events.take(50).toList(); } }); }, onError: (error) { print('Security events error: $error'); }, ); }
@override void dispose() { _subscription?.cancel(); super.dispose(); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Security Monitor')), body: ListView.builder( itemCount: _events.length, itemBuilder: (context, index) { final event = _events[index]; return ListTile( title: Text(event.originalEventType.name), subtitle: Text(event.message), trailing: Icon( event.operationResult == OperationResult.success ? Icons.check_circle : Icons.error, color: event.operationResult == OperationResult.success ? Colors.green : Colors.red, ), ); }, ), ); }}Event Types
Section titled “Event Types”Events are of type AlphynCallbackResult with the following properties:
operationType: The type of operation (OperationType.initialization,OperationType.securityScan, etc.)operationResult: The result (OperationResult.success,OperationResult.failure,OperationResult.threatDetected)originalEventType: The specific event type (AlphynEventType.initComplete,AlphynEventType.threatDetected, etc.)message: Human-readable messagedetails: Additional details
Available Event Types
Section titled “Available Event Types”The SDK emits various event types through the stream:
Initialization Events:
initComplete- SDK initialization completed successfullyinitFailed- SDK initialization failedfirstInit- First-time initializationinvalidAppKey- Invalid application key provided
Security Events:
threatDetected- Security threat identifiedsecureDevice- Device verified as securescanSuccess- Security scan completed successfullyscanResponse- Scan results are availablescanFailed- Security scan failedriskFactorDetected- Risk factor detected during scan
Network Events:
networkInit- Network initializationnetworkMtls- Mutual TLS connection establishedjwtAuthSuccess- JWT authentication successfulnetworkError- Network connectivity errorauthFailed- Authentication failedrequestFailed- API request failed
Storage Events:
keystoreSuccess- Keystore operation successfulkeystoreFailed- Keystore operation failedkeyExchangeSuccess- Key exchange completedkeysFoundStorage- Existing keys found in storagekeysCreatedNew- New keys created
Other Events:
invalidDateOrTime- Invalid date/time detectedcallbackSuccess- Callback operation successfulcallbackFailed- Callback operation failed
Best Practices
Section titled “Best Practices”- Always cancel subscriptions in
dispose()to prevent memory leaks - Handle errors in the stream’s
onErrorcallback - Filter events based on your needs (e.g., only listen to threat events)
- Update UI safely by checking
mountedbefore callingsetState() - Limit event history to prevent memory issues (keep only last N events)
API Reference
Section titled “API Reference”securityEvents()- Returns aStream<AlphynCallbackResult>that emits security events from the native SDK. Works on both Android and iOS.
Complete Example
Section titled “Complete Example”import 'package:flutter/material.dart';import 'package:alphyn_sdk/alphyn_sdk.dart';import 'dart:async';
class SecurityScreen extends StatefulWidget { @override _SecurityScreenState createState() => _SecurityScreenState();}
class _SecurityScreenState extends State<SecurityScreen> { bool _isInitialized = false; String _deviceId = ''; String _appHash = ''; List<String> _scanResults = []; List<AlphynCallbackResult> _securityEvents = []; StreamSubscription<AlphynCallbackResult>? _eventSubscription;
@override void initState() { super.initState(); _initializeSdk(); _setupSecurityListener(); }
@override void dispose() { _eventSubscription?.cancel(); super.dispose(); }
Future<void> _initializeSdk() async { try { // Check initialization status (SDK is initialized natively) final initialized = await AlphynSdk.isInitialized();
if (initialized == true) { setState(() { _isInitialized = true; });
// Load device information await _loadDeviceInfo();
// Perform security scan await _performScan(); } } catch (e) { print('SDK check failed: $e'); } }
void _setupSecurityListener() { // Subscribe to security events stream _eventSubscription = AlphynSdk.securityEvents().listen( (event) { setState(() { _securityEvents.insert(0, event); if (_securityEvents.length > 50) { _securityEvents = _securityEvents.take(50).toList(); } }); }, onError: (error) { print('Security events error: $error'); }, ); }
Future<void> _loadDeviceInfo() async { final deviceId = await AlphynSdk.getDeviceId(); final appHash = await AlphynSdk.getAppHash();
setState(() { _deviceId = deviceId; _appHash = appHash; }); }
Future<void> _performScan() async { final scanResult = await AlphynSdk.getScanResult(); // getRejectReasons() returns a newline-separated string; split it into a list final rejectReasonsRaw = await AlphynSdk.getRejectReasons(); final rejectReasons = rejectReasonsRaw.split('\n').where((line) => line.trim().isNotEmpty).toList();
setState(() { _scanResults = []; if (scanResult != null && scanResult.isNotEmpty) { _scanResults.add(scanResult); } if (rejectReasons.isNotEmpty) { _scanResults.addAll(rejectReasons); } }); }
Future<void> _verifyTestAction() async { try { final result = await AlphynSdk.signAction( userId: userId, actionLabel: 'test_action', context: { 'timestamp': DateTime.now().toIso8601String(), 'source': 'example_app', }, );
if (result.success) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Action verified! Token: ${result.token}')), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Verification failed: ${result.errorMessage}')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); } }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Security Dashboard')), body: _isInitialized ? SingleChildScrollView( padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Device ID: $_deviceId', style: TextStyle(fontWeight: FontWeight.bold)), SizedBox(height: 8), Text('App Hash: $_appHash', style: TextStyle(fontWeight: FontWeight.bold)), SizedBox(height: 16), Text('Scan Results:', style: TextStyle(fontWeight: FontWeight.bold)), ..._scanResults.map((result) => Padding( padding: EdgeInsets.only(left: 16, top: 4), child: Text(result), )), SizedBox(height: 16), ElevatedButton( onPressed: _verifyTestAction, child: Text('Verify Test Action'), ), SizedBox(height: 16), Text('Security Events (${_securityEvents.length}):', style: TextStyle(fontWeight: FontWeight.bold)), ..._securityEvents.take(10).map((event) => Padding( padding: EdgeInsets.only(left: 16, top: 4), child: Text('${event.originalEventType.name}: ${event.message}'), )), ], ), ) : Center(child: CircularProgressIndicator()), ); }}