Overview
Help pages, terms and privacy policies should open inside the app, not throw the user out to a browser. Network status decides whether to warn before streaming over mobile data. A fingerprint or Face ID check replaces typing a password on a shared device. KlugSystem covers all three with the system's own components.
The in-app browser is a Chrome Custom Tab on Android (no extra library needed) and SFSafariViewController on iOS, with your toolbar colour; your app is told when the user is back. Network status reports reachability and Wi-Fi versus mobile data and sends an event when it changes. Biometrics use BiometricPrompt on Android 9+ and LocalAuthentication on iOS; failures come with the same error codes on both platforms, so one handler works everywhere.
KlugSystem runs in the next release of our apps, our proof of concept, for help pages, the mobile-data warning and confirming a device logout.
Features
- Self-contained: one ANE, no core library or dependency ANEs to add
- In-app browser: Chrome Custom Tab (Android) / SFSafariViewController (iOS), toolbar colour, closed event
- Network: reachable, Wi-Fi or mobile data, change events (ConnectivityManager / NWPathMonitor)
- Biometrics: fingerprint and Face ID / Touch ID with your reason text and cancel label
- Same error codes on both platforms (cancel, fallback, locked out, not enrolled)
- No third-party libraries; on Android the store rating uses Google's own Play review library
- isSupported check, so the same code runs on every platform
Supported platforms
Devices without a biometric sensor report canAuthenticate = false, so your app can fall back to the password.
Getting started
Add the extension to your application descriptor:
<extensions>
<extensionID>com.klug.system</extensionID>
</extensions>
Android: add USE_BIOMETRIC, USE_FINGERPRINT and ACCESS_NETWORK_STATE to the manifest additions. iOS: add NSFaceIDUsageDescription to the InfoAdditions.
Code examples
Five complete flows. Every call returns at once; the browser, network and biometric results arrive as events of type KlugSystem.*. Full documentation →
import com.klug.system.KlugSystem; import flash.events.Event; import flash.net.URLRequest; import flash.net.navigateToURL; var sys:KlugSystem = KlugSystem.getInstance(); sys.addEventListener( KlugSystem.BROWSER_CLOSED, onBrowserClosed ); function openHelp():void { var url:String = "https://example.com/help"; // false: not supported here, or no browser could open the page if ( !sys.isSupported || !sys.openBrowser( url, 0x2B2B2B ) ) // toolbar 0xRRGGBB navigateToURL( new URLRequest( url ) ); } function onBrowserClosed( e:Event ):void { // iOS: the user tapped Done. Android: your app is in the foreground again. refreshAccount(); // your app }
sys.addEventListener( KlugSystem.NETWORK_CHANGE, onNetworkChange ); sys.startNetworkWatch(); // the first event usually arrives right away function onNetworkChange( e:Event ):void { // the event carries no detail: ask for the current state if ( !sys.isReachable() ) showOfflineBanner(); // your app else if ( sys.isWWAN() ) showMobileDataWarning(); // on mobile data else hideBanners(); }
sys.addEventListener( KlugSystem.AUTH_SUCCESS, onAuthOk ); sys.addEventListener( KlugSystem.AUTH_FAILED, onAuthFailed ); function confirmLogout():void { // iOS: 1 = Touch ID, 2 = Face ID. // Android 9+: 1 = any enrolled biometric; 2 is always false there. var bio:Boolean = sys.canAuthenticate( KlugSystem.BIOMETRY_FINGERPRINT ) || sys.canAuthenticate( KlugSystem.BIOMETRY_FACE ); if ( !bio || !sys.authenticate( "Confirm to log out", "Cancel" ) ) askForPassword(); // no sensor, nothing enrolled, or Android below 9 } function onAuthOk( e:Event ):void { logOut(); // your app } function onAuthFailed( e:Event ):void { // iOS error numbers on both platforms if ( sys.lastAuthError == -2 ) return; // the user tapped Cancel askForPassword(); // -3 fallback (iOS), -8 locked out, -4 system cancel, -1 failed }
// after a good moment, for example the tenth successful session if ( sessionCount == 10 ) // your app's counter sys.requestReview(); // the store decides whether the dialog really appears: // iOS at most 3 times in 365 days and never in TestFlight; // Google Play has its own quota and never shows it for sideloaded installs
function leaveScreen():void { sys.stopNetworkWatch(); sys.cancelAuthenticate(); // closes a running prompt; AUTH_FAILED may follow sys.removeEventListener( KlugSystem.NETWORK_CHANGE, onNetworkChange ); sys.removeEventListener( KlugSystem.AUTH_SUCCESS, onAuthOk ); sys.removeEventListener( KlugSystem.AUTH_FAILED, onAuthFailed ); }
API overview
| KlugSystem.getInstance() | Returns the single instance. |
| isSupported | True where the native part is present (iOS and Android). |
| openBrowser(url, toolbarColor) | Opens the in-app browser, toolbar colour 0xRRGGBB (default white). Returns false if it could not open; BROWSER_CLOSED when the user is back. |
| isReachable() / isWWAN() | Online at all / on mobile data. |
| startNetworkWatch() / stopNetworkWatch() | NETWORK_CHANGE on every change; read isReachable() and isWWAN() in the handler. |
| canAuthenticate(type) | True if the biometric is available and enrolled. iOS: BIOMETRY_FINGERPRINT = Touch ID, BIOMETRY_FACE = Face ID. Android 9+: BIOMETRY_FINGERPRINT = any biometric, BIOMETRY_FACE always false. |
| authenticate(reason, cancelLabel) | Shows the system prompt; AUTH_SUCCESS or AUTH_FAILED. Returns false if no prompt can be shown (Android below 9). |
| lastAuthError | Error of the last AUTH_FAILED, iOS numbers on both platforms: -1 failed, -2 cancel, -3 fallback, -4 system cancel, -6 not available, -7 not enrolled, -8 locked out. |
| cancelAuthenticate() | Closes a running prompt. |
| requestReview() | Asks the App Store or Google Play for the in-app rating dialog; the store decides whether it shows. |
| BIOMETRY_FINGERPRINT, BIOMETRY_FACE | Types for canAuthenticate(): 1 and 2. |
Events
| BROWSER_CLOSED | The in-app browser is closed: Done on iOS, back in your app on Android. |
| NETWORK_CHANGE | The network changed (after startNetworkWatch()). |
| AUTH_SUCCESS | The user was confirmed. |
| AUTH_FAILED | No confirmation; the reason is in lastAuthError. |
Buy KlugSystem
A yearly licence for one AIR application, with all updates for 12 months. After payment you receive the extension, the ActionScript library and the documentation by e-mail, usually within one business day. Licence and terms
- Licence for one AIR application
- All updates for 12 months
- Answer by e-mail within 7 days
- Licence for one AIR application
- All updates for 12 months
- Answer by e-mail within 48 hours
Requirements
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 or later |
| Android | Android 6 or later; biometrics Android 9 or later |
| Permissions | Android: USE_BIOMETRIC, USE_FINGERPRINT, ACCESS_NETWORK_STATE · iOS: NSFaceIDUsageDescription |