@@ -13,37 +13,41 @@ import (
1313// findNativeLibraryDir 查找应用的 native library 目录
1414// 这个目录是系统自动管理的,包含从 APK 中提取的 .so 文件
1515func findNativeLibraryDir () (string , error ) {
16- // 方法 1: 通过可执行文件路径推断
16+ // 方法 1: 通过环境变量获取(Fyne 可能会设置)
17+ if libDir := os .Getenv ("ANDROID_LIB_DIR" ); libDir != "" {
18+ if info , err := os .Stat (libDir ); err == nil && info .IsDir () {
19+ return libDir , nil
20+ }
21+ }
22+
23+ // 方法 2: 通过可执行文件路径推断
1724 execPath , err := os .Executable ()
1825 if err == nil {
1926 // 可执行文件通常在 /data/app/<package>-<hash>/base.apk 或 /data/app/<package>-<hash>/oat/arm64/base.odex
2027 // native library 通常在 /data/app/<package>-<hash>/lib/arm64/
2128
2229 // 尝试找到应用根目录
2330 dir := execPath
24- for i := 0 ; i < 5 ; i ++ { // 最多向上查找5层
31+ for i := 0 ; i < 10 ; i ++ { // 最多向上查找10层
2532 dir = filepath .Dir (dir )
33+ if dir == "/" || dir == "." {
34+ break
35+ }
36+
2637 libDir := filepath .Join (dir , "lib" )
2738
2839 // 检查 lib 目录
2940 if info , err := os .Stat (libDir ); err == nil && info .IsDir () {
30- // 检查是否包含架构子目录
41+ // 检查是否包含架构子目录或 .so 文件
3142 entries , err := os .ReadDir (libDir )
3243 if err == nil && len (entries ) > 0 {
33- // 如果 lib 目录有子目录(架构名),返回 lib 目录
34- for _ , entry := range entries {
35- if entry .IsDir () {
36- return libDir , nil
37- }
38- }
39- // 如果 lib 目录直接包含 .so 文件,也返回
4044 return libDir , nil
4145 }
4246 }
4347 }
4448 }
4549
46- // 方法 2 : 尝试标准的 Android native library 路径
50+ // 方法 3 : 尝试标准的 Android native library 路径
4751 possibleBasePaths := []string {
4852 "/data/data/com.oneclickvirt.goecs/lib" ,
4953 "/data/app/com.oneclickvirt.goecs/lib" ,
@@ -69,7 +73,7 @@ func findNativeLibraryDir() (string, error) {
6973 }
7074 }
7175
72- // 方法 3 : 搜索 /data/app 目录
76+ // 方法 4 : 搜索 /data/app 目录
7377 dataAppDir := "/data/app"
7478 if entries , err := os .ReadDir (dataAppDir ); err == nil {
7579 for _ , entry := range entries {
@@ -82,39 +86,60 @@ func findNativeLibraryDir() (string, error) {
8286 }
8387 }
8488
85- return "" , fmt .Errorf ("无法找到 native library 目录" )
86- }
87-
88- // getLibraryName 获取当前架构对应的库名称
89- func getLibraryName () string {
90- switch runtime .GOARCH {
91- case "arm64" :
92- return "libgoecs_arm64.so"
93- case "amd64" :
94- return "libgoecs_amd64.so"
95- case "arm" :
96- return "libgoecs_arm.so"
97- case "386" :
98- return "libgoecs_386.so"
99- default :
100- return "libgoecs.so"
89+ // 方法 5: 尝试通过 /proc/self/maps 查找已加载的共享库路径
90+ if mapsData , err := os .ReadFile ("/proc/self/maps" ); err == nil {
91+ lines := strings .Split (string (mapsData ), "\n " )
92+ for _ , line := range lines {
93+ // 查找包含 .so 的行
94+ if strings .Contains (line , ".so" ) && strings .Contains (line , "/data/" ) {
95+ // 提取路径部分
96+ parts := strings .Fields (line )
97+ if len (parts ) >= 6 {
98+ soPath := parts [5 ]
99+ // 获取库目录
100+ libDir := filepath .Dir (soPath )
101+ // 向上查找到 lib 目录
102+ for i := 0 ; i < 3 ; i ++ {
103+ if filepath .Base (libDir ) == "lib" {
104+ return libDir , nil
105+ }
106+ libDir = filepath .Dir (libDir )
107+ }
108+ }
109+ }
110+ }
101111 }
112+
113+ return "" , fmt .Errorf ("无法找到 native library 目录" )
102114}
103115
104116// ExtractECSBinary 获取 ECS 二进制文件路径
105117// 在 Android 上,我们不需要"提取",而是直接使用系统已安装的 native library
106118func ExtractECSBinary () (string , error ) {
107119 // 获取 native library 目录
108120 libDir , err := findNativeLibraryDir ()
121+ debugInfo := fmt .Sprintf ("架构: %s/%s\n " , runtime .GOOS , runtime .GOARCH )
122+
109123 if err != nil {
110- return "" , fmt .Errorf ("获取 native library 目录失败: %v" , err )
124+ debugInfo += fmt .Sprintf ("查找 lib 目录失败: %v\n " , err )
125+ } else {
126+ debugInfo += fmt .Sprintf ("找到 lib 目录: %s\n " , libDir )
127+
128+ // 列出 lib 目录内容
129+ if entries , err := os .ReadDir (libDir ); err == nil {
130+ debugInfo += fmt .Sprintf ("lib 目录内容 (%d 项):\n " , len (entries ))
131+ for _ , entry := range entries {
132+ entryType := "文件"
133+ if entry .IsDir () {
134+ entryType = "目录"
135+ }
136+ debugInfo += fmt .Sprintf (" - %s (%s)\n " , entry .Name (), entryType )
137+ }
138+ }
111139 }
112140
113- // 尝试的文件名列表(按优先级)
114- possibleNames := []string {
115- "libgoecs.so" , // 通用名称
116- getLibraryName (), // 带架构后缀的名称
117- }
141+ // 库名称固定为 libgoecs.so
142+ libraryName := "libgoecs.so"
118143
119144 // 尝试的子目录(Android ABI 名称)
120145 abiDirs := []string {
@@ -135,14 +160,15 @@ func ExtractECSBinary() (string, error) {
135160
136161 // 尝试所有可能的路径组合
137162 var checkedPaths []string
138- for _ , abiDir := range abiDirs {
139- baseDir := libDir
140- if abiDir != "" {
141- baseDir = filepath .Join (libDir , abiDir )
142- }
143163
144- for _ , name := range possibleNames {
145- ecsPath := filepath .Join (baseDir , name )
164+ if err == nil {
165+ for _ , abiDir := range abiDirs {
166+ baseDir := libDir
167+ if abiDir != "" {
168+ baseDir = filepath .Join (libDir , abiDir )
169+ }
170+
171+ ecsPath := filepath .Join (baseDir , libraryName )
146172 checkedPaths = append (checkedPaths , ecsPath )
147173
148174 if info , err := os .Stat (ecsPath ); err == nil && ! info .IsDir () {
@@ -155,10 +181,31 @@ func ExtractECSBinary() (string, error) {
155181 }
156182 }
157183
184+ // 如果上述方法都失败,尝试在常见位置查找
185+ // 注意:不再查找 /system/lib,因为那是系统库位置
186+ fallbackPaths := []string {
187+ "/data/local/tmp/libgoecs.so" , // 临时目录(需要 root)
188+ }
189+
190+ for _ , path := range fallbackPaths {
191+ checkedPaths = append (checkedPaths , path )
192+ if info , err := os .Stat (path ); err == nil && ! info .IsDir () {
193+ return path , nil
194+ }
195+ }
196+
158197 // 未找到文件,返回详细错误信息
159- return "" , fmt .Errorf ("找不到 ECS 二进制文件\n 已检查的路径:\n %s\n \n 请确保:\n 1. ECS 二进制文件已编译为 Android 版本\n 2. 文件已放置在 jniLibs/%s/libgoecs.so\n 3. APK 已重新打包" ,
198+ recommendedABI := "arm64-v8a"
199+ if runtime .GOARCH == "amd64" || runtime .GOARCH == "386" {
200+ recommendedABI = "x86_64"
201+ }
202+
203+ return "" , fmt .Errorf ("找不到 ECS 二进制文件\n \n 调试信息:\n %s\n 已检查的路径:\n %s\n \n 请确保:\n 1. ECS 二进制文件已编译为 Android 版本(Linux/%s)\n 2. 文件已放置在 jniLibs/%s/libgoecs.so\n 3. APK 已重新打包\n 4. 当前架构: %s" ,
204+ debugInfo ,
160205 strings .Join (checkedPaths , "\n " ),
161- abiDirs [1 ]) // 显示推荐的 ABI 目录
206+ runtime .GOARCH ,
207+ recommendedABI ,
208+ runtime .GOARCH )
162209}
163210
164211// CleanupECSBinary 清理函数
0 commit comments