react-native-device-secure-info 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +175 -0
  2. package/android/app/build.gradle +119 -0
  3. package/android/app/debug.keystore +0 -0
  4. package/android/app/proguard-rules.pro +10 -0
  5. package/android/app/src/debug/AndroidManifest.xml +9 -0
  6. package/android/app/src/main/AndroidManifest.xml +26 -0
  7. package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoModule.kt +167 -0
  8. package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoPackage.kt +22 -0
  9. package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoTurboModule.kt +169 -0
  10. package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoTurboPackage.kt +46 -0
  11. package/android/app/src/main/java/com/reactnativedevicesecureinfo/MainActivity.kt +22 -0
  12. package/android/app/src/main/java/com/reactnativedevicesecureinfo/MainApplication.kt +49 -0
  13. package/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  14. package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  15. package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  16. package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  17. package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  18. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  19. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  20. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  21. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  22. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  23. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  24. package/android/app/src/main/res/values/strings.xml +3 -0
  25. package/android/app/src/main/res/values/styles.xml +9 -0
  26. package/android/build.gradle +21 -0
  27. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  28. package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  29. package/android/gradle.properties +39 -0
  30. package/android/gradlew +251 -0
  31. package/android/gradlew.bat +94 -0
  32. package/android/settings.gradle +6 -0
  33. package/ios/.xcode.env +11 -0
  34. package/ios/.xcode.env.local +1 -0
  35. package/ios/DeviceSecureInfoModule.h +7 -0
  36. package/ios/DeviceSecureInfoModule.m +217 -0
  37. package/ios/DeviceSecureInfoTurboModule.h +19 -0
  38. package/ios/DeviceSecureInfoTurboModule.mm +230 -0
  39. package/ios/Podfile +35 -0
  40. package/ios/ReactNativeDeviceSecureInfo/AppDelegate.swift +30 -0
  41. package/ios/ReactNativeDeviceSecureInfo/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  42. package/ios/ReactNativeDeviceSecureInfo/Images.xcassets/Contents.json +6 -0
  43. package/ios/ReactNativeDeviceSecureInfo/Info.plist +52 -0
  44. package/ios/ReactNativeDeviceSecureInfo/LaunchScreen.storyboard +47 -0
  45. package/ios/ReactNativeDeviceSecureInfo/PrivacyInfo.xcprivacy +37 -0
  46. package/ios/ReactNativeDeviceSecureInfo-Bridging-Header.h +4 -0
  47. package/ios/ReactNativeDeviceSecureInfo.xcodeproj/project.pbxproj +504 -0
  48. package/ios/ReactNativeDeviceSecureInfo.xcodeproj/xcshareddata/xcschemes/ReactNativeDeviceSecureInfo.xcscheme +88 -0
  49. package/ios/ReactNativeDeviceSecureInfo.xcworkspace/contents.xcworkspacedata +10 -0
  50. package/ios/ReactNativeDeviceSecureInfo.xcworkspace/xcuserdata/dengbin.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  51. package/package.json +77 -0
  52. package/react-native-device-secure-info.podspec +20 -0
  53. package/react-native.config.js +13 -0
  54. package/src/NativeDeviceSecureInfo.ts +67 -0
  55. package/src/assets/image.png +0 -0
  56. package/src/index.ts +90 -0
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # react-native-device-secure-info
2
+
3
+ 一个 React Native 原生模块,用于获取设备安全信息,包括设备基础信息、内存、CPU 和电池状态。同时支持**新架构(TurboModule)**和**旧架构(Bridge)**。
4
+
5
+ ## 截图
6
+
7
+ <p align="center">
8
+ <img src="src/assets/image.png" alt="Demo Screenshot" width="300" />
9
+ </p>
10
+
11
+ ## 功能特性
12
+
13
+ - 📱 **基础设备信息** — 设备名称、系统版本、品牌、制造商、设备型号、设备 ID、运营商、SDK 版本
14
+ - 💾 **内存信息** — 总内存、可用内存、已用内存、内存使用率
15
+ - ⚙️ **CPU 信息** — CPU 架构、核心数、使用率
16
+ - 🔋 **电池信息** — 电量百分比、充电状态、是否正在充电
17
+ - 🚀 **双架构支持** — 自动适配新架构(TurboModule)和旧架构(Bridge)
18
+ - 📦 **TypeScript 支持** — 完整的类型定义
19
+
20
+ ## 平台支持
21
+
22
+ | 平台 | 支持 |
23
+ | --- | --- |
24
+ | iOS | ✅ |
25
+ | Android | ✅ |
26
+
27
+ ## 环境要求
28
+
29
+ - React Native >= 0.71.0
30
+ - React >= 18.0.0
31
+ - iOS >= 13.4
32
+ - Android minSdkVersion >= 21
33
+
34
+ ## 安装
35
+
36
+ ```bash
37
+ npm install react-native-device-secure-info
38
+ # 或
39
+ yarn add react-native-device-secure-info
40
+ ```
41
+
42
+ ### iOS
43
+
44
+ ```bash
45
+ cd ios && pod install
46
+ ```
47
+
48
+ ### Android
49
+
50
+ 无需额外配置,React Native CLI 的 autolinking 会自动完成链接。
51
+
52
+ ## 使用方式
53
+
54
+ ```typescript
55
+ import { getDeviceInfo } from 'react-native-device-secure-info';
56
+
57
+ async function fetchInfo() {
58
+ const info = await getDeviceInfo();
59
+
60
+ // 基础设备信息
61
+ console.log('设备名称:', info.deviceName);
62
+ console.log('系统:', info.systemName, info.systemVersion);
63
+ console.log('品牌:', info.brand);
64
+ console.log('制造商:', info.manufacturer);
65
+ console.log('设备型号:', info.deviceModel);
66
+ console.log('设备ID:', info.deviceId);
67
+ console.log('运营商:', info.carrierName);
68
+
69
+ // 内存信息
70
+ console.log('总内存:', info.totalMemory);
71
+ console.log('可用内存:', info.availableMemory);
72
+ console.log('内存使用率:', info.memoryUsagePercent + '%');
73
+
74
+ // CPU 信息
75
+ console.log('CPU架构:', info.cpuArchitecture);
76
+ console.log('CPU核心数:', info.cpuCores);
77
+ console.log('CPU使用率:', info.cpuUsagePercent + '%');
78
+
79
+ // 电池信息
80
+ console.log('电量:', info.batteryLevel + '%');
81
+ console.log('充电状态:', info.batteryState);
82
+ console.log('正在充电:', info.isCharging);
83
+ }
84
+ ```
85
+
86
+ ## API
87
+
88
+ ### `getDeviceInfo(): Promise<DeviceSecureInfo>`
89
+
90
+ 获取设备安全信息,返回一个 Promise,resolve 后得到 `DeviceSecureInfo` 对象。
91
+
92
+ ### DeviceSecureInfo 类型定义
93
+
94
+ ```typescript
95
+ interface DeviceSecureInfo {
96
+ // ---- 基础设备信息 ----
97
+ deviceName: string; // 设备名称(如 "iPhone 17 Pro")
98
+ systemVersion: string; // 系统版本号(如 "26.2" / "14")
99
+ brand: string; // 设备品牌(如 "Apple" / "Samsung")
100
+ manufacturer: string; // 制造商(如 "Apple" / "Xiaomi")
101
+ deviceId: string; // 设备唯一标识
102
+ carrierName: string; // 运营商名称(如 "中国移动")
103
+ sdkVersion: number; // SDK 版本号
104
+ deviceModel: string; // 设备型号(如 "iPhone14,2" / "arm64")
105
+ systemName: string; // 系统名称(如 "iOS" / "Android")
106
+
107
+ // ---- 内存信息 ----
108
+ totalMemory: number; // 总内存(字节)
109
+ availableMemory: number; // 可用内存(字节)
110
+ usedMemory: number; // 已使用内存(字节)
111
+ memoryUsagePercent: number; // 内存使用百分比
112
+
113
+ // ---- CPU 信息 ----
114
+ cpuArchitecture: string; // CPU 架构(如 "arm64")
115
+ cpuCores: number; // CPU 核心数
116
+ cpuUsagePercent: number; // CPU 使用率百分比
117
+
118
+ // ---- 电池信息 ----
119
+ batteryLevel: number; // 电池电量百分比(0-100,-1 表示未知)
120
+ batteryState: string; // 电池状态("charging" / "discharging" / "full" / "unknown")
121
+ isCharging: boolean; // 是否正在充电
122
+ }
123
+ ```
124
+
125
+ ## 架构说明
126
+
127
+ 本模块同时支持 React Native 新架构和旧架构:
128
+
129
+ | 架构 | 实现方式 | 说明 |
130
+ | --- | --- | --- |
131
+ | 新架构 | TurboModule + Codegen | 通过 `TurboModuleRegistry` 自动注册,性能更优 |
132
+ | 旧架构 | NativeModules (Bridge) | 通过 `NativeModules.DeviceSecureInfoModule` 获取 |
133
+
134
+ 模块入口(`src/index.ts`)会自动检测当前架构并选择对应的实现,使用者无需关心底层差异。
135
+
136
+ ## 项目结构
137
+
138
+ ```
139
+ react-native-device-secure-info/
140
+ ├── src/
141
+ │ ├── index.ts # JS 入口,自动适配新旧架构
142
+ │ └── NativeDeviceSecureInfo.ts # TurboModule Spec 定义(Codegen)
143
+ ├── ios/
144
+ │ ├── DeviceSecureInfoModule.h # iOS 旧架构头文件
145
+ │ ├── DeviceSecureInfoModule.m # iOS 旧架构实现(Bridge)
146
+ │ ├── DeviceSecureInfoTurboModule.h # iOS 新架构头文件
147
+ │ └── DeviceSecureInfoTurboModule.mm # iOS 新架构实现(TurboModule)
148
+ ├── android/
149
+ │ └── app/src/main/java/...
150
+ │ ├── DeviceSecureInfoModule.kt # Android 原生模块实现
151
+ │ └── DeviceSecureInfoPackage.kt # Android Package 注册
152
+ ├── react-native-device-secure-info.podspec # iOS CocoaPods 配置
153
+ ├── react-native.config.js # React Native autolinking 配置
154
+ └── package.json
155
+ ```
156
+
157
+ ## 本地开发
158
+
159
+ ### 运行 Demo App
160
+
161
+ ```bash
162
+ # 安装依赖
163
+ npm install
164
+
165
+ # iOS
166
+ cd ios && pod install && cd ..
167
+ npm run ios
168
+
169
+ # Android
170
+ npm run android
171
+ ```
172
+
173
+ ## License
174
+
175
+ MIT
@@ -0,0 +1,119 @@
1
+ apply plugin: "com.android.application"
2
+ apply plugin: "org.jetbrains.kotlin.android"
3
+ apply plugin: "com.facebook.react"
4
+
5
+ /**
6
+ * This is the configuration block to customize your React Native Android app.
7
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
8
+ */
9
+ react {
10
+ /* Folders */
11
+ // The root of your project, i.e. where "package.json" lives. Default is '../..'
12
+ // root = file("../../")
13
+ // The folder where the react-native NPM package is. Default is ../../node_modules/react-native
14
+ // reactNativeDir = file("../../node_modules/react-native")
15
+ // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
16
+ // codegenDir = file("../../node_modules/@react-native/codegen")
17
+ // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
18
+ // cliFile = file("../../node_modules/react-native/cli.js")
19
+
20
+ /* Variants */
21
+ // The list of variants to that are debuggable. For those we're going to
22
+ // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
23
+ // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
24
+ // debuggableVariants = ["liteDebug", "prodDebug"]
25
+
26
+ /* Bundling */
27
+ // A list containing the node command and its flags. Default is just 'node'.
28
+ // nodeExecutableAndArgs = ["node"]
29
+ //
30
+ // The command to run when bundling. By default is 'bundle'
31
+ // bundleCommand = "ram-bundle"
32
+ //
33
+ // The path to the CLI configuration file. Default is empty.
34
+ // bundleConfig = file(../rn-cli.config.js)
35
+ //
36
+ // The name of the generated asset file containing your JS bundle
37
+ // bundleAssetName = "MyApplication.android.bundle"
38
+ //
39
+ // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
40
+ // entryFile = file("../js/MyApplication.android.js")
41
+ //
42
+ // A list of extra flags to pass to the 'bundle' commands.
43
+ // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
44
+ // extraPackagerArgs = []
45
+
46
+ /* Hermes Commands */
47
+ // The hermes compiler command to run. By default it is 'hermesc'
48
+ // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
49
+ //
50
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
51
+ // hermesFlags = ["-O", "-output-source-map"]
52
+
53
+ /* Autolinking */
54
+ autolinkLibrariesWithApp()
55
+ }
56
+
57
+ /**
58
+ * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
59
+ */
60
+ def enableProguardInReleaseBuilds = false
61
+
62
+ /**
63
+ * The preferred build flavor of JavaScriptCore (JSC)
64
+ *
65
+ * For example, to use the international variant, you can use:
66
+ * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+`
67
+ *
68
+ * The international variant includes ICU i18n library and necessary data
69
+ * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
70
+ * give correct results when using with locales other than en-US. Note that
71
+ * this variant is about 6MiB larger per architecture than default.
72
+ */
73
+ def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
74
+
75
+ android {
76
+ ndkVersion rootProject.ext.ndkVersion
77
+ buildToolsVersion rootProject.ext.buildToolsVersion
78
+ compileSdk rootProject.ext.compileSdkVersion
79
+
80
+ namespace "com.reactnativedevicesecureinfo"
81
+ defaultConfig {
82
+ applicationId "com.reactnativedevicesecureinfo"
83
+ minSdkVersion rootProject.ext.minSdkVersion
84
+ targetSdkVersion rootProject.ext.targetSdkVersion
85
+ versionCode 1
86
+ versionName "1.0"
87
+ }
88
+ signingConfigs {
89
+ debug {
90
+ storeFile file('debug.keystore')
91
+ storePassword 'android'
92
+ keyAlias 'androiddebugkey'
93
+ keyPassword 'android'
94
+ }
95
+ }
96
+ buildTypes {
97
+ debug {
98
+ signingConfig signingConfigs.debug
99
+ }
100
+ release {
101
+ // Caution! In production, you need to generate your own keystore file.
102
+ // see https://reactnative.dev/docs/signed-apk-android.
103
+ signingConfig signingConfigs.debug
104
+ minifyEnabled enableProguardInReleaseBuilds
105
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
106
+ }
107
+ }
108
+ }
109
+
110
+ dependencies {
111
+ // The version of react-native is set by the React Native Gradle Plugin
112
+ implementation("com.facebook.react:react-android")
113
+
114
+ if (hermesEnabled.toBoolean()) {
115
+ implementation("com.facebook.react:hermes-android")
116
+ } else {
117
+ implementation jscFlavor
118
+ }
119
+ }
Binary file
@@ -0,0 +1,10 @@
1
+ # Add project specific ProGuard rules here.
2
+ # By default, the flags in this file are appended to flags specified
3
+ # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4
+ # You can edit the include path and order by changing the proguardFiles
5
+ # directive in build.gradle.
6
+ #
7
+ # For more details, see
8
+ # http://developer.android.com/guide/developing/tools/proguard.html
9
+
10
+ # Add any project specific keep options here:
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ xmlns:tools="http://schemas.android.com/tools">
4
+
5
+ <application
6
+ android:usesCleartextTraffic="true"
7
+ tools:targetApi="28"
8
+ tools:ignore="GoogleAppIndexingWarning"/>
9
+ </manifest>
@@ -0,0 +1,26 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+
3
+ <uses-permission android:name="android.permission.INTERNET" />
4
+
5
+ <application
6
+ android:name=".MainApplication"
7
+ android:label="@string/app_name"
8
+ android:icon="@mipmap/ic_launcher"
9
+ android:roundIcon="@mipmap/ic_launcher_round"
10
+ android:allowBackup="false"
11
+ android:theme="@style/AppTheme"
12
+ android:supportsRtl="true">
13
+ <activity
14
+ android:name=".MainActivity"
15
+ android:label="@string/app_name"
16
+ android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
17
+ android:launchMode="singleTask"
18
+ android:windowSoftInputMode="adjustResize"
19
+ android:exported="true">
20
+ <intent-filter>
21
+ <action android:name="android.intent.action.MAIN" />
22
+ <category android:name="android.intent.category.LAUNCHER" />
23
+ </intent-filter>
24
+ </activity>
25
+ </application>
26
+ </manifest>
@@ -0,0 +1,167 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ // Android 旧架构(Bridge)设备安全信息模块
4
+
5
+ import android.app.ActivityManager
6
+ import android.content.Context
7
+ import android.content.Intent
8
+ import android.content.IntentFilter
9
+ import android.os.BatteryManager
10
+ import android.os.Build
11
+ import android.provider.Settings
12
+ import android.telephony.TelephonyManager
13
+ import com.facebook.react.bridge.ReactApplicationContext
14
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
15
+ import com.facebook.react.bridge.ReactMethod
16
+ import com.facebook.react.bridge.WritableMap
17
+ import com.facebook.react.bridge.WritableNativeMap
18
+ import com.facebook.react.bridge.Promise
19
+ import java.io.RandomAccessFile
20
+
21
+ /**
22
+ * 设备安全信息原生模块(旧架构 Bridge 版本)
23
+ *
24
+ * 提供设备基础信息、内存、CPU、电池等信息
25
+ * 通过 ReactPackage 注册到 RN Bridge 中
26
+ */
27
+ class DeviceSecureInfoModule(reactContext: ReactApplicationContext) :
28
+ ReactContextBaseJavaModule(reactContext) {
29
+
30
+ override fun getName(): String = NAME
31
+
32
+ companion object {
33
+ const val NAME = "DeviceSecureInfoModule"
34
+ }
35
+
36
+ /**
37
+ * 获取完整的设备安全信息
38
+ * 通过 Promise 返回给 JS 层
39
+ */
40
+ @ReactMethod
41
+ fun getDeviceInfo(promise: Promise) {
42
+ try {
43
+ val context = reactApplicationContext
44
+ val telephonyManager =
45
+ context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
46
+
47
+ val deviceInfo: WritableMap = WritableNativeMap()
48
+
49
+ // ---- 基础设备信息 ----
50
+ deviceInfo.putString("deviceName", Build.MODEL)
51
+ deviceInfo.putString("systemVersion", Build.VERSION.RELEASE)
52
+ deviceInfo.putString("brand", Build.BRAND)
53
+ deviceInfo.putString("manufacturer", Build.MANUFACTURER)
54
+ deviceInfo.putString(
55
+ "deviceId",
56
+ Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
57
+ )
58
+ deviceInfo.putString("carrierName", telephonyManager.networkOperatorName)
59
+ deviceInfo.putInt("sdkVersion", Build.VERSION.SDK_INT)
60
+ deviceInfo.putString("deviceModel", Build.DEVICE)
61
+ deviceInfo.putString("systemName", "Android")
62
+
63
+ // ---- 内存信息 ----
64
+ val activityManager =
65
+ context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
66
+ val memoryInfo = ActivityManager.MemoryInfo()
67
+ activityManager.getMemoryInfo(memoryInfo)
68
+
69
+ val totalMemory = memoryInfo.totalMem
70
+ val availableMemory = memoryInfo.availMem
71
+ val usedMemory = totalMemory - availableMemory
72
+ val memoryUsagePercent = if (totalMemory > 0) {
73
+ (usedMemory.toDouble() / totalMemory.toDouble() * 100).toInt()
74
+ } else 0
75
+
76
+ deviceInfo.putDouble("totalMemory", totalMemory.toDouble())
77
+ deviceInfo.putDouble("availableMemory", availableMemory.toDouble())
78
+ deviceInfo.putDouble("usedMemory", usedMemory.toDouble())
79
+ deviceInfo.putInt("memoryUsagePercent", memoryUsagePercent)
80
+
81
+ // ---- CPU 信息 ----
82
+ deviceInfo.putString(
83
+ "cpuArchitecture",
84
+ Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown"
85
+ )
86
+ deviceInfo.putInt("cpuCores", Runtime.getRuntime().availableProcessors())
87
+ deviceInfo.putDouble("cpuUsagePercent", getCpuUsagePercent())
88
+
89
+ // ---- 电池信息 ----
90
+ val batteryIntent =
91
+ context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
92
+ if (batteryIntent != null) {
93
+ val level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
94
+ val scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
95
+ val batteryLevel = if (level >= 0 && scale > 0) {
96
+ (level.toDouble() / scale.toDouble() * 100).toInt()
97
+ } else -1
98
+
99
+ val status = batteryIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
100
+ val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
101
+ status == BatteryManager.BATTERY_STATUS_FULL
102
+ val batteryState = when (status) {
103
+ BatteryManager.BATTERY_STATUS_CHARGING -> "charging"
104
+ BatteryManager.BATTERY_STATUS_DISCHARGING -> "discharging"
105
+ BatteryManager.BATTERY_STATUS_FULL -> "full"
106
+ BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "discharging"
107
+ else -> "unknown"
108
+ }
109
+
110
+ deviceInfo.putInt("batteryLevel", batteryLevel)
111
+ deviceInfo.putString("batteryState", batteryState)
112
+ deviceInfo.putBoolean("isCharging", isCharging)
113
+ } else {
114
+ deviceInfo.putInt("batteryLevel", -1)
115
+ deviceInfo.putString("batteryState", "unknown")
116
+ deviceInfo.putBoolean("isCharging", false)
117
+ }
118
+
119
+ promise.resolve(deviceInfo)
120
+ } catch (e: Exception) {
121
+ promise.reject("DEVICE_INFO_ERROR", "获取设备信息失败: ${e.message}", e)
122
+ }
123
+ }
124
+
125
+ /**
126
+ * 读取 /proc/stat 获取 CPU 使用率
127
+ * 通过两次采样间隔 100ms 计算实时 CPU 使用百分比
128
+ */
129
+ private fun getCpuUsagePercent(): Double {
130
+ try {
131
+ val reader1 = RandomAccessFile("/proc/stat", "r")
132
+ val line1 = reader1.readLine()
133
+ reader1.close()
134
+
135
+ Thread.sleep(100)
136
+
137
+ val reader2 = RandomAccessFile("/proc/stat", "r")
138
+ val line2 = reader2.readLine()
139
+ reader2.close()
140
+
141
+ val cpu1 = parseCpuLine(line1)
142
+ val cpu2 = parseCpuLine(line2)
143
+
144
+ if (cpu1 != null && cpu2 != null) {
145
+ val totalDiff = cpu2.total - cpu1.total
146
+ val idleDiff = cpu2.idle - cpu1.idle
147
+ if (totalDiff > 0) {
148
+ return ((totalDiff - idleDiff).toDouble() / totalDiff.toDouble() * 100)
149
+ }
150
+ }
151
+ } catch (e: Exception) {
152
+ // /proc/stat 可能在某些设备上无法读取
153
+ }
154
+ return -1.0
155
+ }
156
+
157
+ private data class CpuStat(val total: Long, val idle: Long)
158
+
159
+ private fun parseCpuLine(line: String): CpuStat? {
160
+ val parts = line.trim().split("\\s+".toRegex())
161
+ if (parts.size < 5 || parts[0] != "cpu") return null
162
+ val values = parts.drop(1).map { it.toLongOrNull() ?: 0L }
163
+ val total = values.sum()
164
+ val idle = values.getOrElse(3) { 0L }
165
+ return CpuStat(total, idle)
166
+ }
167
+ }
@@ -0,0 +1,22 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ // 旧架构 ReactPackage —— 用于注册 DeviceSecureInfoModule 到 Bridge
4
+
5
+ import com.facebook.react.ReactPackage
6
+ import com.facebook.react.bridge.NativeModule
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.uimanager.ViewManager
9
+
10
+ /**
11
+ * 旧架构下的 ReactPackage
12
+ * 在 MainApplication 的 getPackages() 中注册
13
+ */
14
+ class DeviceSecureInfoPackage : ReactPackage {
15
+ override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
16
+ return mutableListOf(DeviceSecureInfoModule(reactContext))
17
+ }
18
+
19
+ override fun createViewManagers(reactContext: ReactApplicationContext): MutableList<ViewManager<*, *>> {
20
+ return mutableListOf()
21
+ }
22
+ }