ha-frp-rn 1.0.16 → 1.0.18

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 (53) hide show
  1. package/android/build/.transforms/66c11c57a73a38f4bbb04b9b88dc5137/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/io/github/acedroidx/frp/ShellService$Companion.dex +0 -0
  2. package/android/build/.transforms/66c11c57a73a38f4bbb04b9b88dc5137/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/io/github/acedroidx/frp/ShellService.dex +0 -0
  3. package/android/build/.transforms/8976eb8239f11fc86931495268aa2e67/transformed/classes/classes_dex/classes.dex +0 -0
  4. package/android/build/intermediates/aar_main_jar/release/syncReleaseLibJars/classes.jar +0 -0
  5. package/android/build/intermediates/compile_library_classes_jar/release/bundleLibCompileToJarRelease/classes.jar +0 -0
  6. package/android/build/intermediates/full_jar/release/createFullJarRelease/full.jar +0 -0
  7. package/android/build/intermediates/incremental/release/mergeReleaseResources/compile-file-map.properties +1 -1
  8. package/android/build/intermediates/incremental/release/packageReleaseResources/compile-file-map.properties +1 -1
  9. package/android/build/intermediates/local_aar_for_lint/release/out.aar +0 -0
  10. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/io/github/acedroidx/frp/ShellService$Companion.class +0 -0
  11. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/io/github/acedroidx/frp/ShellService.class +0 -0
  12. package/android/build/intermediates/runtime_library_classes_jar/release/bundleLibRuntimeToJarRelease/classes.jar +0 -0
  13. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  14. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  15. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  16. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  17. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  18. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  19. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  20. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  21. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  22. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  23. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  24. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  25. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  26. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  27. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  28. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  29. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  30. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  31. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  32. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  33. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  34. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  35. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  36. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  37. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  38. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  39. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  40. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  41. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  42. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  43. package/android/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  44. package/android/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin +0 -0
  45. package/android/build/kotlin/compileReleaseKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  46. package/android/build/kotlin/compileReleaseKotlin/local-state/build-history.bin +0 -0
  47. package/android/build/outputs/aar/ha-frp-rn-release.aar +0 -0
  48. package/android/build/outputs/logs/manifest-merger-release-report.txt +9 -9
  49. package/android/build/tmp/compileReleaseJavaWithJavac/previous-compilation-data.bin +0 -0
  50. package/android/build/tmp/kotlin-classes/release/io/github/acedroidx/frp/ShellService$Companion.class +0 -0
  51. package/android/build/tmp/kotlin-classes/release/io/github/acedroidx/frp/ShellService.class +0 -0
  52. package/android/src/main/java/io/github/acedroidx/frp/ShellService.kt +253 -226
  53. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- #Wed Dec 24 14:56:04 CST 2025
1
+ #Tue Dec 30 14:08:53 CST 2025
2
2
  io.github.acedroidx.frp.ha-frp-rn-appcompat-1.7.0-10\:/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl.png=D\:\\Project\\Page_Manager\\ha-mobile-rn\\node_modules\\ha-frp-rn\\android\\build\\intermediates\\merged_res\\release\\mergeReleaseResources\\drawable-xxxhdpi-v4\\abc_text_select_handle_right_mtrl.png
3
3
  io.github.acedroidx.frp.ha-frp-rn-appcompat-1.7.0-10\:/layout/abc_action_mode_bar.xml=D\:\\Project\\Page_Manager\\ha-mobile-rn\\node_modules\\ha-frp-rn\\android\\build\\intermediates\\merged_res\\release\\mergeReleaseResources\\layout\\abc_action_mode_bar.xml
4
4
  io.github.acedroidx.frp.ha-frp-rn-core-1.13.1-17\:/drawable-hdpi-v4/notification_bg_low_pressed.9.png=D\:\\Project\\Page_Manager\\ha-mobile-rn\\node_modules\\ha-frp-rn\\android\\build\\intermediates\\merged_res\\release\\mergeReleaseResources\\drawable-hdpi-v4\\notification_bg_low_pressed.9.png
@@ -1 +1 @@
1
- #Wed Dec 24 14:44:33 CST 2025
1
+ #Tue Dec 30 14:08:45 CST 2025
@@ -1,16 +1,16 @@
1
1
  -- Merging decision tree log ---
2
2
  manifest
3
- ADDED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml:2:13-83
4
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml:2:13-83
3
+ ADDED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml:2:13-83
4
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml:2:13-83
5
5
  package
6
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml
6
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml
7
7
  xmlns:android
8
- ADDED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml:2:23-81
8
+ ADDED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml:2:23-81
9
9
  uses-sdk
10
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml reason: use-sdk injection requested
11
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml
12
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml
10
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml reason: use-sdk injection requested
11
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml
12
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml
13
13
  android:targetSdkVersion
14
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml
14
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml
15
15
  android:minSdkVersion
16
- INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest2194563455099757824.xml
16
+ INJECTED from D:\Project\Page_Manager\ha-mobile-rn\node_modules\ha-frp-rn\android\build\intermediates\tmp\ProcessLibraryManifest\release\tempAndroidManifest14099836558573805620.xml
@@ -1,226 +1,253 @@
1
- package io.github.acedroidx.frp
2
-
3
- import android.content.Context
4
- import android.util.Log
5
- import java.io.*
6
- import java.util.concurrent.Executors
7
- import java.util.concurrent.TimeUnit
8
-
9
- class ShellService(private val context: Context) {
10
-
11
- enum class Status {
12
- STOPPED,
13
- STARTING,
14
- RUNNING,
15
- STOPPING,
16
- ERROR
17
- }
18
-
19
- private var process: Process? = null
20
- private var status = Status.STOPPED
21
- private var lastMessage = ""
22
- private var executorService = Executors.newSingleThreadExecutor()
23
- private var onStatusChangeListener: ((Status, String) -> Unit)? = null
24
- private val TAG = "ShellService"
25
-
26
- fun setOnStatusChangeListener(listener: (Status, String) -> Unit) {
27
- this.onStatusChangeListener = listener
28
- }
29
-
30
- /**
31
- * 使用配置路径启动FRP访问者模式
32
- *
33
- * @param configPath - 配置文件路径
34
- */
35
- fun startVisitor(configPath: String) {
36
- startFrp("frpc", configPath)
37
- }
38
-
39
- /**
40
- * 使用配置路径启动FRP服务器模式
41
- *
42
- * @param configPath - 配置文件路径
43
- */
44
- fun startServer(configPath: String) {
45
- startFrp("frps", configPath)
46
- }
47
-
48
- /**
49
- * 使用FrpConfig对象启动FRP
50
- *
51
- * @param frpConfig - FRP配置对象
52
- */
53
- fun start(frpConfig: FrpConfig) {
54
- val binaryName = when (frpConfig.type) {
55
- FrpType.FRPC -> "frpc"
56
- FrpType.FRPS -> "frps"
57
- }
58
- val configPath = frpConfig.getFile(context).absolutePath
59
- startFrp(binaryName, configPath)
60
- }
61
-
62
- private fun startFrp(binaryName: String, configPath: String) {
63
- if (status == Status.RUNNING) {
64
- Log.w(TAG, "FRP is already running")
65
- return
66
- }
67
-
68
- setStatus(Status.STARTING, "Starting $binaryName...")
69
-
70
- executorService.submit {
71
- try {
72
- // 使用正确的工作目录
73
- val frpDir = File(context.cacheDir, "frp")
74
- if (!frpDir.exists()) {
75
- frpDir.mkdirs()
76
- }
77
-
78
- // 获取应用的nativeLibraryDir,找到真正的FRP二进制文件
79
- val packageManager = context.packageManager
80
- val applicationInfo = packageManager.getApplicationInfo(
81
- context.packageName,
82
- android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES
83
- )
84
-
85
- // 构建完整的FRP二进制文件路径
86
- val nativeLibraryDir = applicationInfo.nativeLibraryDir
87
- val libName = when (binaryName) {
88
- "frpc" -> "libfrpc.so"
89
- "frps" -> "libfrps.so"
90
- else -> {
91
- Log.e(TAG, "Unknown binary name: $binaryName")
92
- setStatus(Status.ERROR, "Unknown binary name: $binaryName")
93
- return@submit
94
- }
95
- }
96
-
97
- val binaryPath = File(nativeLibraryDir, libName)
98
- if (!binaryPath.exists()) {
99
- Log.e(TAG, "FRP binary not found: $binaryPath")
100
- setStatus(Status.ERROR, "FRP binary not found: $binaryPath")
101
- return@submit
102
- }
103
-
104
- // 确保二进制文件可执行
105
- binaryPath.setExecutable(true)
106
-
107
- // 构建命令
108
- val command = arrayOf(
109
- binaryPath.absolutePath, // 使用完整的二进制文件路径
110
- "-c",
111
- configPath
112
- )
113
-
114
- Log.i(TAG, "Executing: ${command.joinToString(" ")}")
115
- Log.i(TAG, "Working directory: ${frpDir.absolutePath}")
116
-
117
- // 执行命令
118
- val pb = ProcessBuilder(*command)
119
- .redirectErrorStream(true)
120
- .directory(frpDir)
121
-
122
- process = pb.start()
123
- setStatus(Status.RUNNING, "$binaryName started successfully")
124
- lastMessage = "$binaryName is running normally"
125
- onStatusChangeListener?.invoke(status, lastMessage)
126
-
127
- // 读取输出
128
- BufferedReader(InputStreamReader(process?.inputStream)).use { reader ->
129
- var line: String?
130
- while (reader.readLine().also { line = it } != null) {
131
- Log.d(TAG, "FRP output: $line")
132
- lastMessage = line ?: ""
133
- onStatusChangeListener?.invoke(status, lastMessage)
134
- }
135
- }
136
-
137
- // 监控进程
138
- monitorProcess()
139
-
140
- } catch (e: Exception) {
141
- Log.e(TAG, "Error running FRP: ${e.message}", e)
142
- setStatus(Status.ERROR, "Failed to start FRP: ${e.message}")
143
- }
144
- }
145
- }
146
-
147
- private fun monitorProcess() {
148
- executorService.submit {
149
- try {
150
- process?.waitFor()
151
- val exitCode = process?.exitValue() ?: -1
152
- setStatus(Status.STOPPED, "FRP stopped with exit code $exitCode")
153
- } catch (e: Exception) {
154
- Log.e(TAG, "Error monitoring FRP process: ${e.message}", e)
155
- setStatus(Status.ERROR, "Error monitoring FRP: ${e.message}")
156
- }
157
- }
158
- }
159
-
160
- fun stop() {
161
- if (status != Status.RUNNING && status != Status.STARTING) {
162
- Log.w(TAG, "FRP is not running")
163
- return
164
- }
165
-
166
- setStatus(Status.STOPPING, "Stopping FRP...")
167
-
168
- try {
169
- process?.destroy()
170
- process?.waitFor(5, TimeUnit.SECONDS)
171
- if (process?.isAlive == true) {
172
- process?.destroyForcibly()
173
- process?.waitFor(2, TimeUnit.SECONDS)
174
- }
175
- setStatus(Status.STOPPED, "FRP stopped")
176
- } catch (e: Exception) {
177
- Log.e(TAG, "Error stopping FRP: ${e.message}", e)
178
- setStatus(Status.ERROR, "Failed to stop FRP: ${e.message}")
179
- } finally {
180
- process = null
181
- }
182
- }
183
-
184
- private fun extractBinary(binaryName: String): String? {
185
- // FRP二进制文件作为Native Library打包在APK的lib目录下
186
- // 直接返回正确的二进制文件名(Android会自动加载)
187
- Log.i(TAG, "Using native library for $binaryName")
188
- return when (binaryName) {
189
- "frpc" -> "libfrpc.so"
190
- "frps" -> "libfrps.so"
191
- else -> {
192
- Log.e(TAG, "Unknown binary name: $binaryName")
193
- null
194
- }
195
- }
196
- }
197
-
198
- private fun setStatus(newStatus: Status, message: String) {
199
- status = newStatus
200
- lastMessage = message
201
- Log.i(TAG, "Status: $status, Message: $message")
202
- onStatusChangeListener?.invoke(newStatus, message)
203
- }
204
-
205
- fun getStatus(): Status {
206
- return status
207
- }
208
-
209
- fun getLastMessage(): String {
210
- return lastMessage
211
- }
212
-
213
- companion object {
214
- // Properties for external access
215
- val Status.status: Status
216
- get() = this
217
- val Status.message: String
218
- get() = when (this) {
219
- Status.STOPPED -> "Stopped"
220
- Status.STARTING -> "Starting"
221
- Status.RUNNING -> "Running"
222
- Status.STOPPING -> "Stopping"
223
- Status.ERROR -> "Error"
224
- }
225
- }
226
- }
1
+ package io.github.acedroidx.frp
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import java.io.*
6
+ import java.util.concurrent.Executors
7
+ import java.util.concurrent.TimeUnit
8
+
9
+ class ShellService(private val context: Context) {
10
+
11
+ enum class Status {
12
+ STOPPED,
13
+ STARTING,
14
+ RUNNING,
15
+ STOPPING,
16
+ ERROR
17
+ }
18
+
19
+ private var process: Process? = null
20
+ private var status = Status.STOPPED
21
+ private var lastMessage = ""
22
+ private var executorService = Executors.newSingleThreadExecutor()
23
+ private var onStatusChangeListener: ((Status, String) -> Unit)? = null
24
+ private val TAG = "ShellService"
25
+
26
+ fun setOnStatusChangeListener(listener: (Status, String) -> Unit) {
27
+ this.onStatusChangeListener = listener
28
+ }
29
+
30
+ /**
31
+ * 使用配置路径启动FRP访问者模式
32
+ *
33
+ * @param configPath - 配置文件路径
34
+ */
35
+ fun startVisitor(configPath: String) {
36
+ startFrp("frpc", configPath)
37
+ }
38
+
39
+ /**
40
+ * 使用配置路径启动FRP服务器模式
41
+ *
42
+ * @param configPath - 配置文件路径
43
+ */
44
+ fun startServer(configPath: String) {
45
+ startFrp("frps", configPath)
46
+ }
47
+
48
+ /**
49
+ * 使用FrpConfig对象启动FRP
50
+ *
51
+ * @param frpConfig - FRP配置对象
52
+ */
53
+ fun start(frpConfig: FrpConfig) {
54
+ val binaryName = when (frpConfig.type) {
55
+ FrpType.FRPC -> "frpc"
56
+ FrpType.FRPS -> "frps"
57
+ }
58
+ val configPath = frpConfig.getFile(context).absolutePath
59
+ startFrp(binaryName, configPath)
60
+ }
61
+
62
+ private fun startFrp(binaryName: String, configPath: String) {
63
+ if (status == Status.RUNNING) {
64
+ Log.w(TAG, "FRP is already running")
65
+ return
66
+ }
67
+
68
+ setStatus(Status.STARTING, "Starting $binaryName...")
69
+
70
+ executorService.submit {
71
+ try {
72
+ // === 关键修复:区分 asset 和真实文件 ===
73
+ val rawConfigFile = File(configPath)
74
+ val isAssetPath = configPath.startsWith("assets/") || configPath.contains("asset")
75
+
76
+ val actualConfigFile: File = if (isAssetPath) {
77
+ // 复制 asset 到可写目录
78
+ val internalDir = context.filesDir // /data/data/.../files
79
+ val destFile = File(internalDir, "frpc-running.toml") // 可写位置
80
+ copyAssetToFile(context, configPath.substringAfterLast("/"), destFile)
81
+ destFile
82
+ } else {
83
+ // 已经是真实路径
84
+ if (!rawConfigFile.exists()) {
85
+ Log.e(TAG, "Config file does not exist: $configPath")
86
+ setStatus(Status.ERROR, "Config file not found: $configPath")
87
+ return@submit
88
+ }
89
+ rawConfigFile
90
+ }
91
+
92
+ // 此时 actualConfigFile 一定是可访问的真实文件
93
+ val workingDir = actualConfigFile.parentFile!!
94
+ val binaryPath = getBinaryPath(binaryName)
95
+
96
+ // 构建命令
97
+ val command = arrayOf(
98
+ binaryPath.absolutePath,
99
+ "-c",
100
+ actualConfigFile.name // 只传文件名,工作目录已设
101
+ )
102
+
103
+ Log.i(TAG, "Executing: ${command.joinToString(" ")}")
104
+ Log.i(TAG, "Working directory: ${workingDir.absolutePath}")
105
+ Log.i(TAG, "Config file: ${actualConfigFile.absolutePath}")
106
+
107
+ // 执行
108
+ val pb = ProcessBuilder(*command)
109
+ .redirectErrorStream(true)
110
+ .directory(workingDir)
111
+
112
+ process = pb.start()
113
+ setStatus(Status.RUNNING, "$binaryName started successfully")
114
+
115
+ // 输出监听
116
+ BufferedReader(InputStreamReader(process?.inputStream)).use { reader ->
117
+ var line: String?
118
+ while (reader.readLine().also { line = it } != null) {
119
+ Log.d(TAG, "FRP output: $line")
120
+ lastMessage = line ?: ""
121
+ onStatusChangeListener?.invoke(status, lastMessage)
122
+ }
123
+ }
124
+
125
+ monitorProcess()
126
+
127
+ } catch (e: Exception) {
128
+ Log.e(TAG, "Error running FRP: ${e.message}", e)
129
+ setStatus(Status.ERROR, "Failed to start FRP: ${e.message}")
130
+ }
131
+ }
132
+ }
133
+
134
+ /**
135
+ * 将 assets 中的文件复制到目标文件
136
+ */
137
+ private fun copyAssetToFile(context: Context, assetName: String, destFile: File) {
138
+ try {
139
+ context.assets.open(assetName).use { input ->
140
+ FileOutputStream(destFile).use { output ->
141
+ val buffer = ByteArray(1024)
142
+ var length: Int
143
+ while (input.read(buffer).also { length = it } > 0) {
144
+ output.write(buffer, 0, length)
145
+ }
146
+ }
147
+ }
148
+ Log.i(TAG, "Successfully copied asset $assetName to ${destFile.absolutePath}")
149
+ } catch (e: IOException) {
150
+ Log.e(TAG, "Failed to copy asset $assetName", e)
151
+ throw RuntimeException("Failed to copy asset: $assetName", e)
152
+ }
153
+ }
154
+
155
+ /**
156
+ * 获取 native 二进制路径
157
+ */
158
+ private fun getBinaryPath(binaryName: String): File {
159
+ val packageManager = context.packageManager
160
+ val applicationInfo = packageManager.getApplicationInfo(
161
+ context.packageName,
162
+ android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES
163
+ )
164
+ val nativeLibraryDir = File(applicationInfo.nativeLibraryDir)
165
+ val libName = when (binaryName) {
166
+ "frpc" -> "libfrpc.so"
167
+ "frps" -> "libfrps.so"
168
+ else -> throw IllegalArgumentException("Unknown binary: $binaryName")
169
+ }
170
+ return File(nativeLibraryDir, libName)
171
+ }
172
+
173
+
174
+ private fun monitorProcess() {
175
+ executorService.submit {
176
+ try {
177
+ process?.waitFor()
178
+ val exitCode = process?.exitValue() ?: -1
179
+ setStatus(Status.STOPPED, "FRP stopped with exit code $exitCode")
180
+ } catch (e: Exception) {
181
+ Log.e(TAG, "Error monitoring FRP process: ${e.message}", e)
182
+ setStatus(Status.ERROR, "Error monitoring FRP: ${e.message}")
183
+ }
184
+ }
185
+ }
186
+
187
+ fun stop() {
188
+ if (status != Status.RUNNING && status != Status.STARTING) {
189
+ Log.w(TAG, "FRP is not running")
190
+ return
191
+ }
192
+
193
+ setStatus(Status.STOPPING, "Stopping FRP...")
194
+
195
+ try {
196
+ process?.destroy()
197
+ process?.waitFor(5, TimeUnit.SECONDS)
198
+ if (process?.isAlive == true) {
199
+ process?.destroyForcibly()
200
+ process?.waitFor(2, TimeUnit.SECONDS)
201
+ }
202
+ setStatus(Status.STOPPED, "FRP stopped")
203
+ } catch (e: Exception) {
204
+ Log.e(TAG, "Error stopping FRP: ${e.message}", e)
205
+ setStatus(Status.ERROR, "Failed to stop FRP: ${e.message}")
206
+ } finally {
207
+ process = null
208
+ }
209
+ }
210
+
211
+ private fun extractBinary(binaryName: String): String? {
212
+ // FRP二进制文件作为Native Library打包在APK的lib目录下
213
+ // 直接返回正确的二进制文件名(Android会自动加载)
214
+ Log.i(TAG, "Using native library for $binaryName")
215
+ return when (binaryName) {
216
+ "frpc" -> "libfrpc.so"
217
+ "frps" -> "libfrps.so"
218
+ else -> {
219
+ Log.e(TAG, "Unknown binary name: $binaryName")
220
+ null
221
+ }
222
+ }
223
+ }
224
+
225
+ private fun setStatus(newStatus: Status, message: String) {
226
+ status = newStatus
227
+ lastMessage = message
228
+ Log.i(TAG, "Status: $status, Message: $message")
229
+ onStatusChangeListener?.invoke(newStatus, message)
230
+ }
231
+
232
+ fun getStatus(): Status {
233
+ return status
234
+ }
235
+
236
+ fun getLastMessage(): String {
237
+ return lastMessage
238
+ }
239
+
240
+ companion object {
241
+ // Properties for external access
242
+ val Status.status: Status
243
+ get() = this
244
+ val Status.message: String
245
+ get() = when (this) {
246
+ Status.STOPPED -> "Stopped"
247
+ Status.STARTING -> "Starting"
248
+ Status.RUNNING -> "Running"
249
+ Status.STOPPING -> "Stopping"
250
+ Status.ERROR -> "Error"
251
+ }
252
+ }
253
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ha-frp-rn",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "React Native FRP module for network penetration",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",