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
@@ -0,0 +1,169 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ // Android 新架构(TurboModule)设备安全信息模块
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.WritableMap
15
+ import com.facebook.react.bridge.WritableNativeMap
16
+ import com.facebook.react.bridge.Promise
17
+ import com.facebook.react.module.annotations.ReactModule
18
+ import com.facebook.react.turbomodule.core.interfaces.TurboModule
19
+ import com.facebook.react.bridge.ReactMethod
20
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
21
+ import java.io.RandomAccessFile
22
+
23
+ /**
24
+ * 设备安全信息原生模块(新架构 TurboModule 版本)
25
+ *
26
+ * 使用 @ReactModule 注解声明模块名
27
+ * 继承 ReactContextBaseJavaModule 并实现 TurboModule 接口
28
+ * 新架构下通过 TurboReactPackage 的懒加载机制按需创建
29
+ */
30
+ @ReactModule(name = DeviceSecureInfoTurboModule.NAME)
31
+ class DeviceSecureInfoTurboModule(reactContext: ReactApplicationContext) :
32
+ ReactContextBaseJavaModule(reactContext), TurboModule {
33
+
34
+ companion object {
35
+ const val NAME = "DeviceSecureInfoModule"
36
+ }
37
+
38
+ override fun getName(): String = NAME
39
+
40
+ /**
41
+ * 获取完整的设备安全信息
42
+ */
43
+ @ReactMethod
44
+ fun getDeviceInfo(promise: Promise) {
45
+ try {
46
+ val context = reactApplicationContext
47
+ val telephonyManager =
48
+ context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
49
+
50
+ val deviceInfo: WritableMap = WritableNativeMap()
51
+
52
+ // ---- 基础设备信息 ----
53
+ deviceInfo.putString("deviceName", Build.MODEL)
54
+ deviceInfo.putString("systemVersion", Build.VERSION.RELEASE)
55
+ deviceInfo.putString("brand", Build.BRAND)
56
+ deviceInfo.putString("manufacturer", Build.MANUFACTURER)
57
+ deviceInfo.putString(
58
+ "deviceId",
59
+ Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
60
+ )
61
+ deviceInfo.putString("carrierName", telephonyManager.networkOperatorName)
62
+ deviceInfo.putInt("sdkVersion", Build.VERSION.SDK_INT)
63
+ deviceInfo.putString("deviceModel", Build.DEVICE)
64
+ deviceInfo.putString("systemName", "Android")
65
+
66
+ // ---- 内存信息 ----
67
+ val activityManager =
68
+ context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
69
+ val memoryInfo = ActivityManager.MemoryInfo()
70
+ activityManager.getMemoryInfo(memoryInfo)
71
+
72
+ val totalMemory = memoryInfo.totalMem
73
+ val availableMemory = memoryInfo.availMem
74
+ val usedMemory = totalMemory - availableMemory
75
+ val memoryUsagePercent = if (totalMemory > 0) {
76
+ (usedMemory.toDouble() / totalMemory.toDouble() * 100).toInt()
77
+ } else 0
78
+
79
+ deviceInfo.putDouble("totalMemory", totalMemory.toDouble())
80
+ deviceInfo.putDouble("availableMemory", availableMemory.toDouble())
81
+ deviceInfo.putDouble("usedMemory", usedMemory.toDouble())
82
+ deviceInfo.putInt("memoryUsagePercent", memoryUsagePercent)
83
+
84
+ // ---- CPU 信息 ----
85
+ deviceInfo.putString(
86
+ "cpuArchitecture",
87
+ Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown"
88
+ )
89
+ deviceInfo.putInt("cpuCores", Runtime.getRuntime().availableProcessors())
90
+ deviceInfo.putDouble("cpuUsagePercent", getCpuUsagePercent())
91
+
92
+ // ---- 电池信息 ----
93
+ val batteryIntent =
94
+ context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
95
+ if (batteryIntent != null) {
96
+ val level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
97
+ val scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
98
+ val batteryLevel = if (level >= 0 && scale > 0) {
99
+ (level.toDouble() / scale.toDouble() * 100).toInt()
100
+ } else -1
101
+
102
+ val status = batteryIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
103
+ val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
104
+ status == BatteryManager.BATTERY_STATUS_FULL
105
+ val batteryState = when (status) {
106
+ BatteryManager.BATTERY_STATUS_CHARGING -> "charging"
107
+ BatteryManager.BATTERY_STATUS_DISCHARGING -> "discharging"
108
+ BatteryManager.BATTERY_STATUS_FULL -> "full"
109
+ BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "discharging"
110
+ else -> "unknown"
111
+ }
112
+
113
+ deviceInfo.putInt("batteryLevel", batteryLevel)
114
+ deviceInfo.putString("batteryState", batteryState)
115
+ deviceInfo.putBoolean("isCharging", isCharging)
116
+ } else {
117
+ deviceInfo.putInt("batteryLevel", -1)
118
+ deviceInfo.putString("batteryState", "unknown")
119
+ deviceInfo.putBoolean("isCharging", false)
120
+ }
121
+
122
+ promise.resolve(deviceInfo)
123
+ } catch (e: Exception) {
124
+ promise.reject("DEVICE_INFO_ERROR", "获取设备信息失败: ${e.message}", e)
125
+ }
126
+ }
127
+
128
+ /**
129
+ * 读取 /proc/stat 获取 CPU 使用率
130
+ */
131
+ private fun getCpuUsagePercent(): Double {
132
+ try {
133
+ val reader1 = RandomAccessFile("/proc/stat", "r")
134
+ val line1 = reader1.readLine()
135
+ reader1.close()
136
+
137
+ Thread.sleep(100)
138
+
139
+ val reader2 = RandomAccessFile("/proc/stat", "r")
140
+ val line2 = reader2.readLine()
141
+ reader2.close()
142
+
143
+ val cpu1 = parseCpuLine(line1)
144
+ val cpu2 = parseCpuLine(line2)
145
+
146
+ if (cpu1 != null && cpu2 != null) {
147
+ val totalDiff = cpu2.total - cpu1.total
148
+ val idleDiff = cpu2.idle - cpu1.idle
149
+ if (totalDiff > 0) {
150
+ return ((totalDiff - idleDiff).toDouble() / totalDiff.toDouble() * 100)
151
+ }
152
+ }
153
+ } catch (e: Exception) {
154
+ // /proc/stat 可能在某些设备上无法读取
155
+ }
156
+ return -1.0
157
+ }
158
+
159
+ private data class CpuStat(val total: Long, val idle: Long)
160
+
161
+ private fun parseCpuLine(line: String): CpuStat? {
162
+ val parts = line.trim().split("\\s+".toRegex())
163
+ if (parts.size < 5 || parts[0] != "cpu") return null
164
+ val values = parts.drop(1).map { it.toLongOrNull() ?: 0L }
165
+ val total = values.sum()
166
+ val idle = values.getOrElse(3) { 0L }
167
+ return CpuStat(total, idle)
168
+ }
169
+ }
@@ -0,0 +1,46 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ // Android 新架构 TurboModule Package
4
+ // 使用 TurboReactPackage 替代传统 ReactPackage,支持懒加载
5
+
6
+ import com.facebook.react.TurboReactPackage
7
+ import com.facebook.react.bridge.NativeModule
8
+ import com.facebook.react.bridge.ReactApplicationContext
9
+ import com.facebook.react.module.model.ReactModuleInfo
10
+ import com.facebook.react.module.model.ReactModuleInfoProvider
11
+
12
+ /**
13
+ * 新架构下的 TurboReactPackage
14
+ * 提供模块懒加载(按需创建),性能优于旧架构的 ReactPackage
15
+ */
16
+ class DeviceSecureInfoTurboPackage : TurboReactPackage() {
17
+
18
+ /**
19
+ * 按需创建模块实例(懒加载)
20
+ * 旧架构 ReactPackage 的 createNativeModules 会一次性创建所有模块
21
+ */
22
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
23
+ return when (name) {
24
+ DeviceSecureInfoTurboModule.NAME -> DeviceSecureInfoTurboModule(reactContext)
25
+ else -> null
26
+ }
27
+ }
28
+
29
+ /**
30
+ * 提供模块元信息,框架据此决定何时实例化模块
31
+ */
32
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
33
+ return ReactModuleInfoProvider {
34
+ mapOf(
35
+ DeviceSecureInfoTurboModule.NAME to ReactModuleInfo(
36
+ DeviceSecureInfoTurboModule.NAME, // 模块名
37
+ DeviceSecureInfoTurboModule.NAME, // 类名
38
+ false, // canOverrideExistingModule
39
+ false, // needsEagerInit(false = 懒加载)
40
+ false, // isCxxModule
41
+ true // isTurboModule(标记为 TurboModule)
42
+ )
43
+ )
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,22 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ import com.facebook.react.ReactActivity
4
+ import com.facebook.react.ReactActivityDelegate
5
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6
+ import com.facebook.react.defaults.DefaultReactActivityDelegate
7
+
8
+ class MainActivity : ReactActivity() {
9
+
10
+ /**
11
+ * Returns the name of the main component registered from JavaScript. This is used to schedule
12
+ * rendering of the component.
13
+ */
14
+ override fun getMainComponentName(): String = "ReactNativeDeviceSecureInfo"
15
+
16
+ /**
17
+ * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
18
+ * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
19
+ */
20
+ override fun createReactActivityDelegate(): ReactActivityDelegate =
21
+ DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
22
+ }
@@ -0,0 +1,49 @@
1
+ package com.reactnativedevicesecureinfo
2
+
3
+ import android.app.Application
4
+ import com.facebook.react.PackageList
5
+ import com.facebook.react.ReactApplication
6
+ import com.facebook.react.ReactHost
7
+ import com.facebook.react.ReactNativeHost
8
+ import com.facebook.react.ReactPackage
9
+ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
10
+ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11
+ import com.facebook.react.defaults.DefaultReactNativeHost
12
+ import com.facebook.react.soloader.OpenSourceMergedSoMapping
13
+ import com.facebook.soloader.SoLoader
14
+
15
+ class MainApplication : Application(), ReactApplication {
16
+
17
+ override val reactNativeHost: ReactNativeHost =
18
+ object : DefaultReactNativeHost(this) {
19
+ override fun getPackages(): List<ReactPackage> =
20
+ PackageList(this).packages.apply {
21
+ // 注册设备安全信息模块
22
+ // 根据架构类型选择对应的 Package
23
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
24
+ add(DeviceSecureInfoTurboPackage())
25
+ } else {
26
+ add(DeviceSecureInfoPackage())
27
+ }
28
+ }
29
+
30
+ override fun getJSMainModuleName(): String = "index"
31
+
32
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
33
+
34
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
35
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
36
+ }
37
+
38
+ override val reactHost: ReactHost
39
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
40
+
41
+ override fun onCreate() {
42
+ super.onCreate()
43
+ SoLoader.init(this, OpenSourceMergedSoMapping)
44
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
45
+ // If you opted-in for the New Architecture, we load the native entry point for this app.
46
+ load()
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Copyright (C) 2014 The Android Open Source Project
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ -->
16
+ <inset xmlns:android="http://schemas.android.com/apk/res/android"
17
+ android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
18
+ android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
19
+ android:insetTop="@dimen/abc_edit_text_inset_top_material"
20
+ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
21
+ >
22
+
23
+ <selector>
24
+ <!--
25
+ This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
26
+ The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
27
+ NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
28
+
29
+ <item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
30
+
31
+ For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
32
+ -->
33
+ <item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
34
+ <item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
35
+ </selector>
36
+
37
+ </inset>
@@ -0,0 +1,3 @@
1
+ <resources>
2
+ <string name="app_name">ReactNativeDeviceSecureInfo</string>
3
+ </resources>
@@ -0,0 +1,9 @@
1
+ <resources>
2
+
3
+ <!-- Base application theme. -->
4
+ <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
5
+ <!-- Customize your theme here. -->
6
+ <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
7
+ </style>
8
+
9
+ </resources>
@@ -0,0 +1,21 @@
1
+ buildscript {
2
+ ext {
3
+ buildToolsVersion = "35.0.0"
4
+ minSdkVersion = 24
5
+ compileSdkVersion = 35
6
+ targetSdkVersion = 35
7
+ ndkVersion = "27.1.12297006"
8
+ kotlinVersion = "2.0.21"
9
+ }
10
+ repositories {
11
+ google()
12
+ mavenCentral()
13
+ }
14
+ dependencies {
15
+ classpath("com.android.tools.build:gradle")
16
+ classpath("com.facebook.react:react-native-gradle-plugin")
17
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
18
+ }
19
+ }
20
+
21
+ apply plugin: "com.facebook.react.rootproject"
@@ -0,0 +1,7 @@
1
+ distributionBase=GRADLE_USER_HOME
2
+ distributionPath=wrapper/dists
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
4
+ networkTimeout=10000
5
+ validateDistributionUrl=true
6
+ zipStoreBase=GRADLE_USER_HOME
7
+ zipStorePath=wrapper/dists
@@ -0,0 +1,39 @@
1
+ # Project-wide Gradle settings.
2
+
3
+ # IDE (e.g. Android Studio) users:
4
+ # Gradle settings configured through the IDE *will override*
5
+ # any settings specified in this file.
6
+
7
+ # For more details on how to configure your build environment visit
8
+ # http://www.gradle.org/docs/current/userguide/build_environment.html
9
+
10
+ # Specifies the JVM arguments used for the daemon process.
11
+ # The setting is particularly useful for tweaking memory settings.
12
+ # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13
+ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14
+
15
+ # When configured, Gradle will run in incubating parallel mode.
16
+ # This option should only be used with decoupled projects. More details, visit
17
+ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18
+ # org.gradle.parallel=true
19
+
20
+ # AndroidX package structure to make it clearer which packages are bundled with the
21
+ # Android operating system, and which are packaged with your app's APK
22
+ # https://developer.android.com/topic/libraries/support-library/androidx-rn
23
+ android.useAndroidX=true
24
+
25
+ # Use this property to specify which architecture you want to build.
26
+ # You can also override it from the CLI using
27
+ # ./gradlew <task> -PreactNativeArchitectures=x86_64
28
+ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
29
+
30
+ # Use this property to enable support to the new architecture.
31
+ # This will allow you to use TurboModules and the Fabric render in
32
+ # your application. You should enable this flag either if you want
33
+ # to write custom TurboModules/Fabric components OR use libraries that
34
+ # are providing them.
35
+ newArchEnabled=true
36
+
37
+ # Use this property to enable or disable the Hermes JS engine.
38
+ # If set to false, you will be using JSC instead.
39
+ hermesEnabled=true