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.
- package/README.md +175 -0
- package/android/app/build.gradle +119 -0
- package/android/app/debug.keystore +0 -0
- package/android/app/proguard-rules.pro +10 -0
- package/android/app/src/debug/AndroidManifest.xml +9 -0
- package/android/app/src/main/AndroidManifest.xml +26 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoModule.kt +167 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoPackage.kt +22 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoTurboModule.kt +169 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/DeviceSecureInfoTurboPackage.kt +46 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/MainActivity.kt +22 -0
- package/android/app/src/main/java/com/reactnativedevicesecureinfo/MainApplication.kt +49 -0
- package/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/android/app/src/main/res/values/strings.xml +3 -0
- package/android/app/src/main/res/values/styles.xml +9 -0
- package/android/build.gradle +21 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/gradle.properties +39 -0
- package/android/gradlew +251 -0
- package/android/gradlew.bat +94 -0
- package/android/settings.gradle +6 -0
- package/ios/.xcode.env +11 -0
- package/ios/.xcode.env.local +1 -0
- package/ios/DeviceSecureInfoModule.h +7 -0
- package/ios/DeviceSecureInfoModule.m +217 -0
- package/ios/DeviceSecureInfoTurboModule.h +19 -0
- package/ios/DeviceSecureInfoTurboModule.mm +230 -0
- package/ios/Podfile +35 -0
- package/ios/ReactNativeDeviceSecureInfo/AppDelegate.swift +30 -0
- package/ios/ReactNativeDeviceSecureInfo/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/ios/ReactNativeDeviceSecureInfo/Images.xcassets/Contents.json +6 -0
- package/ios/ReactNativeDeviceSecureInfo/Info.plist +52 -0
- package/ios/ReactNativeDeviceSecureInfo/LaunchScreen.storyboard +47 -0
- package/ios/ReactNativeDeviceSecureInfo/PrivacyInfo.xcprivacy +37 -0
- package/ios/ReactNativeDeviceSecureInfo-Bridging-Header.h +4 -0
- package/ios/ReactNativeDeviceSecureInfo.xcodeproj/project.pbxproj +504 -0
- package/ios/ReactNativeDeviceSecureInfo.xcodeproj/xcshareddata/xcschemes/ReactNativeDeviceSecureInfo.xcscheme +88 -0
- package/ios/ReactNativeDeviceSecureInfo.xcworkspace/contents.xcworkspacedata +10 -0
- package/ios/ReactNativeDeviceSecureInfo.xcworkspace/xcuserdata/dengbin.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/package.json +77 -0
- package/react-native-device-secure-info.podspec +20 -0
- package/react-native.config.js +13 -0
- package/src/NativeDeviceSecureInfo.ts +67 -0
- package/src/assets/image.png +0 -0
- 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
|
+
}
|