# bluememe-utils Cordova plugin for OutSystems 11 mobile apps. 功能: - 保存或连接指定 WiFi 热点 - Firebase Cloud Messaging 推送通知 - Touch ID / Face ID / Android biometric 解锁,并把解锁结果通知给应用 插件 ID:`bluememe-utils` JS 全局对象: - `BluememeUtils` - `cordova.plugins.bluememeUtils` ## Install 在 OutSystems 11 的 extensibility configuration 中添加插件仓库或本地包后,可使用下面的参数覆盖 Firebase 配置。 ```json { "plugin": { "url": "bluememe-utils", "variables": { "ANDROID_FIREBASE_APP_ID": "1:000000000000:android:xxxxxxxxxxxxxxxx", "ANDROID_FIREBASE_API_KEY": "AIza...", "ANDROID_FIREBASE_PROJECT_ID": "your-firebase-project", "ANDROID_FIREBASE_SENDER_ID": "000000000000", "ANDROID_FIREBASE_STORAGE_BUCKET": "your-firebase-project.appspot.com", "IOS_FIREBASE_GOOGLE_APP_ID": "1:000000000000:ios:xxxxxxxxxxxxxxxx", "IOS_FIREBASE_API_KEY": "AIza...", "IOS_FIREBASE_PROJECT_ID": "your-firebase-project", "IOS_FIREBASE_GCM_SENDER_ID": "000000000000", "IOS_FIREBASE_STORAGE_BUCKET": "your-firebase-project.appspot.com", "IOS_FACE_ID_USAGE_DESCRIPTION": "Use Face ID to unlock this application." } } } ``` 也可以让宿主 App 提供并处理标准 Firebase 配置文件: - Android:`google-services.json` - iOS:`GoogleService-Info.plist` 如果宿主工程已经由 OutSystems、MABS 配置或其他插件初始化 Firebase,本插件会复用已有的 default Firebase app。否则建议使用上面的 plugin variables,让本插件在运行时手动初始化 Firebase。 ## JavaScript API 所有方法都使用 Cordova callback 风格,适合在 OutSystems client action 中封装。 ```js BluememeUtils.getDeviceInfo(function (info) { console.log(info.deviceKey); }, error); ``` `getDeviceInfo` 返回: ```json { "deviceKey": "generated-and-persisted-uuid", "platform": "Android", "appIdentifier": "com.company.app", "appVersion": "1.0.0", "buildNumber": "1", "osVersion": "15", "sdkVersion": 35, "deviceModel": "Google Pixel 8", "manufacturer": "Google", "brand": "google", "model": "Pixel 8", "locale": "ja-JP", "timeZone": "Asia/Tokyo" } ``` `deviceKey` 首次调用时生成并保存在本地,用于标识当前 App 安装实例。App 卸载或清除数据后会重新生成。iOS 不返回 `sdkVersion`、`manufacturer`、`brand`,但会返回 `systemName`。 ```js BluememeUtils.requestWifiPermission(success, error); BluememeUtils.saveWifi({ ssid: "MyHotspot", password: "password123", security: "wpa2" }, success, error); BluememeUtils.connectWifi({ ssid: "MyHotspot", password: "password123", security: "wpa2" }, success, error); BluememeUtils.removeWifi({ ssid: "MyHotspot", password: "password123", security: "wpa2" }, success, error); BluememeUtils.disconnectWifi(success, error); ``` WiFi options: - `ssid`:必填 - `password`:开放网络可省略 - `security`:`open`、`wep`、`wpa2`、`wpa3`,默认按是否存在 password 推断为 `open` 或 `wpa2` - `hiddenSsid`:可选;Android 支持隐藏 SSID;iOS 13+ 会设置 `NEHotspotConfiguration.hidden` - `bssid`:可选,仅 Android 10+ 临时连接使用 - `joinOnce`:可选,仅 iOS;`connectWifi` 默认 `true`,`saveWifi` 默认 `false` ## Push Notifications ```js BluememeUtils.requestPushPermission(success, error); BluememeUtils.getPushPermissionStatus(success, error); BluememeUtils.getFirebaseToken(function (result) { console.log(result.token); }, error); BluememeUtils.subscribeToTopic("news", success, error); BluememeUtils.unsubscribeFromTopic("news", success, error); BluememeUtils.startNotificationListener(function (event) { if (event.type === "token") { console.log(event.token); } if (event.type === "notification") { console.log(event.notification); } if (event.type === "notificationOpened") { console.log(event.notification); } }, error); BluememeUtils.getInitialNotification(success, error); BluememeUtils.stopNotificationListener(success, error); ``` `getPushPermissionStatus` 只读取当前系统通知状态,不弹授权框。可用于填充后端 `NotificationsEnabled`。 返回示例: ```json { "type": "notification", "platform": "Android", "enabled": true, "granted": true, "runtimePermissionGranted": true, "appNotificationsEnabled": true, "authorizationStatus": "authorized", "missing": [] } ``` 推荐注册 token 前调用: ```js BluememeUtils.getPushPermissionStatus(function (status) { var notificationsEnabled = status.enabled === true; }, error); ``` 事件也会派发到 `window`: - `bluememeutils.token` - `bluememeutils.notification` - `bluememeutils.notificationOpened` - `bluememeutils.unlock` 也可以用插件内置监听器: ```js BluememeUtils.on("unlock", function (event) { console.log(event.unlocked); }); ``` ## Biometric Unlock ```js BluememeUtils.isBiometricAvailable(success, error); BluememeUtils.unlockWithBiometrics({ reason: "Unlock application", title: "Unlock", subtitle: "", description: "", cancelText: "Cancel", fallbackTitle: "Use Passcode", allowDeviceCredential: true }, function (result) { console.log(result.unlocked, result.biometryType); }, error); ``` `biometryType` 可能值: - iOS:`face`、`touch`、`none`、`biometric` - Android:`face`、`fingerprint`、`iris`、`biometric` ## Platform Notes Android WiFi: - Android 10+ 不允许第三方应用静默保存并强制切换系统 WiFi。 - `saveWifi` 在 Android 10+ 使用 `WifiNetworkSuggestion`,系统可能要求用户批准。 - `connectWifi` 在 Android 10+ 使用 `WifiNetworkSpecifier`,这是临时连接,通常只绑定当前应用进程网络。 - Android 9 及以下使用旧 `WifiConfiguration` API,可保存并启用网络。 - 调用 WiFi API 前先调用 `requestWifiPermission`,并确保系统位置服务开启。 iOS WiFi: - 使用 `NEHotspotConfiguration`。 - 插件会向 Cordova iOS entitlements 写入 `com.apple.developer.networking.HotspotConfiguration`,但仍必须在 Apple Developer App ID 中开启 `Hotspot Configuration` capability,并使用包含该 capability 的 provisioning profile 重新构建。 - 如果 iOS 返回 `NEHotspotConfigurationErrorDomain` code `8` / `internal error`,优先检查 App ID、entitlements、provisioning profile 是否都包含 `Hotspot Configuration`,并确认是在真机前台运行,不是在模拟器中测试。 - iOS 的 `NEHotspotConfiguration` password initializer 公开支持 WEP/WPA/WPA2 Personal。WPA2/WPA3 mixed 通常应先按 `security: "wpa2"` 测试;如果 WPA2-only 可用但 mixed 不可用,需要调整热点兼容性配置或改用配置描述文件/MDM 流程。 - iOS 不提供第三方 App 断开当前 WiFi 的公开 API,因此 `disconnectWifi` 在 iOS 返回错误。 Firebase: - Android 13+ 需要通知权限,调用 `requestPushPermission`。 - iOS 需要 Push Notifications capability、Background Modes 中的 Remote notifications,以及 APNs key/certificate 已配置到 Firebase。 - 如果项目中还有其他推送插件,也可能同时修改 `UNUserNotificationCenterDelegate` 或 Firebase service,需要在真机上确认通知打开事件。 Biometric: - iOS Face ID 需要 `NSFaceIDUsageDescription`,可通过 `IOS_FACE_ID_USAGE_DESCRIPTION` 设置。 - Android 本插件使用平台 `BiometricPrompt`,`unlockWithBiometrics` 支持 Android 9+。 ## Error Shape 错误 callback 返回对象: ```json { "code": "ERROR_CODE", "message": "Human readable message" } ``` 常见错误: - `PERMISSION_REQUIRED` - `INVALID_WIFI_OPTIONS` - `WIFI_CONNECT_FAILED` - `FIREBASE_NOT_CONFIGURED` - `FCM_TOKEN_FAILED` - `BIOMETRIC_UNAVAILABLE` - `AUTHENTICATION_ERROR`