← 所有扩展

原生扩展

KlugSystem

com.klug.system

无需 APM。下载即用,再简单不过。

每个应用都需要的系统服务,集于一个小巧的扩展:在应用内浏览器中打开网页、了解设备是否在线以及使用 Wi-Fi 还是移动数据、通过指纹或 Face ID 确认用户身份,并请求商店评分。

iOSAndroid 已投入生产 €19 / 年起 · 购买

概览

帮助页面、条款和隐私政策应在应用内打开,而不是把用户抛到浏览器。网络状态决定是否在使用移动数据推流前发出警告。指纹或 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,可自定义提示文字和取消标签
  • 两个平台使用相同的错误代码(取消、回退、已锁定、未录入)
  • 无第三方库;在 Android 上,商店评分使用 Google 自己的 Play 评价库
  • isSupported 检查,因此同一份代码可在所有平台上运行

支持的平台

iOS 浏览器 · 网络 · Face ID / Touch ID · arm64
Android 浏览器 · 网络 · 指纹 (Android 9+)

没有生物识别传感器的设备会报告 canAuthenticate = false,因此您的应用可以回退到密码。

入门

将扩展添加到您的应用描述文件中:

app.xml
<extensions>
    <extensionID>com.klug.system</extensionID>
</extensions>

Android:将 USE_BIOMETRIC、USE_FINGERPRINT 和 ACCESS_NETWORK_STATE 添加到清单附加内容中。iOS:将 NSFaceIDUsageDescription 添加到 InfoAdditions。

代码示例

五个完整流程。每次调用都会立即返回;浏览器、网络和生物识别的结果以 KlugSystem.* 类型的事件到达。完整文档 →

1 · 在应用内浏览器中打开帮助页面
Help.as
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
}
2 · 使用移动数据推流前发出警告
Network.as
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();
}
3 · 通过指纹或 Face ID 确认用户身份
Confirm.as
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
}
4 · 请求商店评分
Rating.as
// 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
5 · 干净地关闭
Shutdown.as
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在存在原生部分的平台上为 True(iOS 和 Android)。
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_FACEcanAuthenticate() 的类型:1 和 2。

事件

BROWSER_CLOSED应用内浏览器已关闭:iOS 上点击“完成”,Android 上返回到您的应用。
NETWORK_CHANGE网络已变化(在 startNetworkWatch() 之后)。
AUTH_SUCCESS用户已通过确认。
AUTH_FAILED未通过确认;原因见 lastAuthError。

购买 KlugSystem

一个 AIR 应用的年度许可,含 12 个月内的所有更新。付款后,您将通过电子邮件收到扩展、ActionScript 库和文档,通常在一个工作日内。许可与条款

基础版
€19 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 不含支持
购买基础版
标准版
€149 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 7 天内通过电子邮件答复
购买标准版
优先版
€299 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 48 小时内通过电子邮件答复
购买优先版
税费在结账时由 Link (Stripe) 计算。您需要在结账时输入 AIR 应用的应用 ID。

要求

AIR SDK51.x (HARMAN)
iOSiOS 13 或更高版本
AndroidAndroid 6 或更高版本;生物识别需 Android 9 或更高版本
权限Android:USE_BIOMETRIC、USE_FINGERPRINT、ACCESS_NETWORK_STATE · iOS:NSFaceIDUsageDescription