개요
도움말 페이지, 약관, 개인정보 처리방침은 사용자를 브라우저로 내보내지 않고 앱 안에서 열려야 합니다. 네트워크 상태는 모바일 데이터로 스트리밍하기 전에 경고할지 결정합니다. 지문 또는 Face ID 확인은 공용 기기에서 비밀번호 입력을 대신합니다. KlugSystem은 시스템 자체 구성 요소로 이 세 가지를 모두 다룹니다.
인앱 브라우저는 Android에서는 Chrome Custom Tab(추가 라이브러리 불필요), iOS에서는 SFSafariViewController이며 툴바 색상을 지정할 수 있고, 사용자가 돌아오면 앱에 알려 줍니다. 네트워크 상태는 연결 가능 여부와 Wi-Fi/모바일 데이터 구분을 보고하고 변경 시 이벤트를 보냅니다. 생체 인증은 Android 9 이상에서는 BiometricPrompt, iOS에서는 LocalAuthentication을 사용하며, 실패 시 두 플랫폼에서 동일한 오류 코드를 제공하므로 하나의 핸들러로 어디서나 처리할 수 있습니다.
KlugSystem은 도움말 페이지, 모바일 데이터 경고, 기기 로그아웃 확인에 사용되며, 개념 증명인 저희 앱의 다음 릴리스에서 실행됩니다.
기능
- 독립형: ANE 하나로 충분하며, 코어 라이브러리나 의존성 ANE를 추가할 필요가 없음
- 인앱 브라우저: Chrome Custom Tab(Android) / SFSafariViewController(iOS), 툴바 색상, 닫힘 이벤트
- 네트워크: 연결 가능 여부, Wi-Fi 또는 모바일 데이터, 변경 이벤트(ConnectivityManager / NWPathMonitor)
- 생체 인증: 지문 및 Face ID / Touch ID, 사유 텍스트와 취소 레이블 지정 가능
- 두 플랫폼에서 동일한 오류 코드(cancel, fallback, locked out, not enrolled)
- 서드파티 라이브러리 없음. Android의 스토어 평점은 Google 자체 Play 리뷰 라이브러리를 사용
- isSupported 검사로 모든 플랫폼에서 같은 코드가 실행됨
지원 플랫폼
생체 인식 센서가 없는 기기는 canAuthenticate = false를 반환하므로, 앱이 비밀번호로 대체할 수 있습니다.
시작하기
애플리케이션 디스크립터에 확장을 추가합니다:
<extensions>
<extensionID>com.klug.system</extensionID>
</extensions>
Android: 매니페스트 추가 항목에 USE_BIOMETRIC, USE_FINGERPRINT, ACCESS_NETWORK_STATE를 추가하세요. iOS: InfoAdditions에 NSFaceIDUsageDescription을 추가하세요.
코드 예제
다섯 가지 완전한 흐름입니다. 모든 호출은 즉시 반환되며, 브라우저, 네트워크, 생체 인증 결과는 KlugSystem.* 타입의 이벤트로 전달됩니다. 전체 문서 →
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 개요
| KlugSystem.getInstance() | 단일 인스턴스를 반환합니다. |
| isSupported | 네이티브 부분이 있는 곳(iOS와 Android)에서 true입니다. |
| openBrowser(url, toolbarColor) | 인앱 브라우저를 엽니다. 툴바 색상은 0xRRGGBB(기본값 흰색)입니다. 열지 못하면 false를 반환하며, 사용자가 돌아오면 BROWSER_CLOSED가 발생합니다. |
| isReachable() / isWWAN() | 온라인 여부 / 모바일 데이터 여부. |
| startNetworkWatch() / stopNetworkWatch() | 변경될 때마다 NETWORK_CHANGE가 발생합니다. 핸들러에서 isReachable()과 isWWAN()을 읽으세요. |
| canAuthenticate(type) | 생체 인식을 사용할 수 있고 등록되어 있으면 true입니다. iOS: BIOMETRY_FINGERPRINT = Touch ID, BIOMETRY_FACE = Face ID. Android 9 이상: BIOMETRY_FINGERPRINT = 모든 생체 인식, BIOMETRY_FACE는 항상 false. |
| authenticate(reason, cancelLabel) | 시스템 프롬프트를 표시하며, AUTH_SUCCESS 또는 AUTH_FAILED가 발생합니다. 프롬프트를 표시할 수 없으면(Android 9 미만) false를 반환합니다. |
| lastAuthError | 마지막 AUTH_FAILED의 오류이며 두 플랫폼 모두 iOS 번호를 사용합니다: -1 실패, -2 취소, -3 대체, -4 시스템 취소, -6 사용 불가, -7 미등록, -8 잠김. |
| cancelAuthenticate() | 실행 중인 프롬프트를 닫습니다. |
| requestReview() | App Store 또는 Google Play에 인앱 평점 대화상자를 요청하며, 표시 여부는 스토어가 결정합니다. |
| BIOMETRY_FINGERPRINT, BIOMETRY_FACE | canAuthenticate()의 타입: 1과 2. |
이벤트
| BROWSER_CLOSED | 인앱 브라우저가 닫혔습니다: iOS에서는 완료, Android에서는 앱으로 돌아옴. |
| NETWORK_CHANGE | 네트워크가 변경되었습니다(startNetworkWatch() 이후). |
| AUTH_SUCCESS | 사용자가 확인되었습니다. |
| AUTH_FAILED | 확인되지 않았습니다. 이유는 lastAuthError에 있습니다. |
KlugSystem 구매
AIR 애플리케이션 1개에 대한 연간 라이선스이며 12개월간 모든 업데이트를 제공합니다. 결제 후 확장, ActionScript 라이브러리, 문서를 이메일로 보내 드리며, 보통 영업일 기준 1일 이내입니다. 라이선스 및 약관
요구 사항
| AIR SDK | 51.x (HARMAN) |
| iOS | iOS 13 이상 |
| Android | Android 6 이상, 생체 인증은 Android 9 이상 |
| 권한 | Android: USE_BIOMETRIC, USE_FINGERPRINT, ACCESS_NETWORK_STATE · iOS: NSFaceIDUsageDescription |