Android 系统源码项目加载预编好的so库

打印 上一主题 下一主题

主题 666|帖子 666|积分 1998

Android 系统源码项目加载预编好的so库


  
一、媒介

Android 系统开辟中会源代码有加载so库的情况,本文举行简单介绍。
Android Studio 项目加载so库,已经有介绍过:
https://blog.csdn.net/wenzhi20102321/article/details/137080360
Android Studio加载so和使用so还是比力方便的,环境OK的情况,几分钟就可以完成验证测试了。
但是如果要在系统源代码Java内里加载和使用so就比力麻烦了,
主要通过Android.mk大概Android.bp编译加载so,反正网上的代码写的mk/bp基本都是不行的。
原来以为只是介绍一下编译使用的Android.mk大概Android.bp就可以了,
但是究竟有点出乎意料,总结下来发现劳绩了一些知识点;
所以这个很有必要举行总结一下。有兴趣的可以看看。
平凡应用开辟不愿定用到这个知识,但是系统编译开辟会用到这个知识,而且有的相关文件还不好解决。
本文末了还有一些源码编译apk相关知识的总结,还是比力有效的。可以点赞收藏。
二、源码中加载so

源码中加载so,首选是Android.mk,由于Android.bp 未美满,会有bug。
1、预备源码
这里预备的源码和Android Studio 加载so的源码是一模一样的,
只是在app同级目录下加一个Android.mk 大概Android.bp。
1、Android.mk加载so

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_PACKAGE_NAME := JniLoadso
  4. LOCAL_MODULE_TAGS := optional
  5. LOCAL_CERTIFICATE := platform
  6. LOCAL_PRIVATE_PLATFORM_APIS := true
  7. #生成到system/priv-app目录
  8. LOCAL_PRIVILEGED_MODULE := true
  9. LOCAL_DEX_PREOPT := false
  10. LOCAL_MANIFEST_FILE := \
  11.    app/src/main/AndroidManifest.xml
  12.         
  13. LOCAL_SRC_FILES := \
  14.             $(call all-java-files-under,app/src/main/java/) \
  15. LOCAL_RESOURCE_DIR := \
  16.     $(LOCAL_PATH)/app/src/main/res
  17. LOCAL_PREBUILT_JNI_LIBS:= \
  18.     app/jni/arm64-v8a/libnative-lib.so
  19. #这样加没用!!不知为啥
  20. #LOCAL_SHARED_LIBRARIES := libnative-lib
  21. LOCAL_STATIC_ANDROID_LIBRARIES := \
  22.     androidx.recyclerview_recyclerview \
  23.     com.google.android.material_material
  24. LOCAL_STATIC_JAVA_LIBRARIES := \
  25.     androidx.appcompat_appcompat \
  26.     androidx-constraintlayout_constraintlayout
  27. include $(BUILD_PACKAGE)
  28. include $(CLEAR_VARS)
  29. LOCAL_MODULE := libnative-lib
  30. LOCAL_SRC_FILES := app/jni/arm64-v8a/libnative-lib.so
  31. include $(PREBUILT_SHARED_LIBRARY)
复制代码
上面加了Androidx的包,必要在AndroidManifest.xml举行适配修改一下否则会编译报错。具体如何适配末了有说明;Android13大概Android14 源码编译会有这个问题。
这里的Android.mk 直接放在app同级目录下面就行,
我不喜欢放两个Android.mk的处理,现实上许多源码应用是如许处理的:
app同级目录下放一个声明链接的Android.mk,app/src/main/ 下面也放一个现实起作用的Android.mk;
加载so的主要相关代码:

  1. LOCAL_PREBUILT_JNI_LIBS:= \
  2.     app/jni/arm64-v8a/libnative-lib.so
  3. #这样加没用!!不知为啥
  4. #LOCAL_SHARED_LIBRARIES := libnative-lib
  5. include $(CLEAR_VARS)
  6. LOCAL_MODULE := libnative-lib
  7. LOCAL_SRC_FILES := app/jni/arm64-v8a/libnative-lib.so
  8. include $(PREBUILT_SHARED_LIBRARY)
复制代码
上面和so相关就就LOCAL_PREBUILT_JNI_LIBS这一行代码,其他的编译命令和编译平凡Java代码项目是一样的。
参加这个后,系统会在apk的同级目录下天生so文件。
后续有尝试去除 PREBUILT_SHARED_LIBRARY ,其实也是可以天生so在lib目录的。
所以主要作用的文件就是:
  1. LOCAL_PREBUILT_JNI_LIBS:= \
  2.     app/jni/arm64-v8a/libnative-lib.so
复制代码
out目录天生后的so文件,如下图所示:

整编整个大包,烧录到系统,这个so就会在运行的Android设备apk的lib目录下。具体情况:
  1. rk3588_t:/system/priv-app/JniLoadso #
  2. rk3588_t:/system/priv-app/JniLoadso # ls
  3. JniLoadso.apk  lib  oat
  4. rk3588_t:/system/priv-app/JniLoadso # ls lib/arm64/
  5. libnative-lib.so
  6. rk3588_t:/system/priv-app/JniLoadso #
复制代码
app应用运行后是可以正常读取到so库的。
2、Android.bp加载so

Android.bp 如何编写?
其实系统源码中有个android.go 文件是写了Android.mk和Android.bp所有对于属性的转换关系的。
但是并不是所有的标签都能转换。估计是实现了比力常用的大部分功能。
(1)Android.mk使用源码命令编译成Android.bp

源码中如何实现转换的,末了有链接,有兴趣的可以看看。
通过转换后获取到Android.bp:
  1. android_app {
  2.     name: "JniLoadso",
  3.     certificate: "platform",
  4.     platform_apis: true,
  5.     //生成到system/priv-app目录
  6.     privileged: true,
  7.     dex_preopt: {
  8.         enabled: false,
  9.     },
  10.     manifest: "app/src/main/AndroidManifest.xml",
  11.     srcs: ["app/src/main/java//**/*.java"],
  12.     resource_dirs: ["app/src/main/res"],
  13.     // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_PREBUILT_JNI_LIBS
  14.     // LOCAL_PREBUILT_JNI_LIBS := app/jni/arm64-v8a/libnative-lib.so
  15.     //这样加没用!!不知为啥
  16.     //LOCAL_SHARED_LIBRARIES := libnative-lib
  17.     static_libs: [
  18.         "androidx.recyclerview_recyclerview",
  19.         "com.google.android.material_material",
  20.         "androidx.appcompat_appcompat",
  21.         "androidx-constraintlayout_constraintlayout",
  22.     ],
  23. }
  24. // ANDROIDMK TRANSLATION ERROR: unsupported include
  25. // include $(PREBUILT_SHARED_LIBRARY)
复制代码
固然天生了Android.bp但是末了提示有ERROR,而且LOCAL_PREBUILT_JNI_LIBS指令是无法转换的。
所以Android使用源码命令转换Android.mk,在一些特殊的模块处理上是有问题的,好比so加载就有问题。
而且在mk和bp转换的关系源码android.go中也是未找到 LOCAL_PREBUILT_JNI_LIBS 的转换关系;
所以这个是目前Android14 也无法解决的问题;使用Android.bp就是无法编译加载so。
但是上面的Android.bp 是可以正常编译出apk的,只是编译出的out目录apk中未天生lib目录。
所以Android.bp 没法编译加载so项目吗,其实不是。
由于在源码中如许编译so项目是没问题的。但是要多做一些操纵。往后看看吧。
(2)Android.bp

有效部分的源码:
  1. android_app {
  2.     name: "JniLoadso",
  3.     platform_apis: true,
  4.     certificate: "platform",
  5.     optimize: {
  6.         proguard_flags_files: ["app/src/main/proguard.flags"],
  7.     },
  8.     privileged: true,
  9.     static_libs: [
  10.         "androidx.appcompat_appcompat",
  11.         "androidx-constraintlayout_constraintlayout",
  12.         "androidx.annotation_annotation",
  13.         "com.google.android.material_material",
  14.         "androidx-constraintlayout_constraintlayout",
  15.         "androidx.recyclerview_recyclerview",
  16.     ],
  17.     manifest: "app/src/main/AndroidManifest.xml",
  18.     srcs: ["app/src/main/java/**/*.java",
  19.      ],
  20.     resource_dirs: ["app/src/main/res"],
  21. }
复制代码
如许编译后运行的设备中未包含 JniLoadso 应用必要的so,那么点击运行应用肯定会报错的,怎么解决?
Android.bp 不消编译so并举行读取so解决方法:

  1. 1、Android 系统编译源码应用可以读取系统so;
  2. 如果apk应用是64位的(目前99%应用都是64位的),那么系统可以读取到system/lib64下面的so;
  3. 2、如果是限制单个应用使用,可以通过脚本把so放到运行环境的apk的lib/arm64/目录下;
  4. 3、apk优先是读取自己目录下的lib,如果没有就读取系统下的 system/lib64的so
  5. 这是亲自测试验证过的,两个地方只有一个地方有就可以正常读取到。
复制代码
其实如何读取不消我们管,系统会实现;
具体要管的就是系统运行环境有没有放入so文件,有就可以读取到,没有就会报错。
系统编译的app应用代码中只要定义了加载so
  1.     static {
  2.         System.loadLibrary("native-lib");
  3.     }
复制代码
那如果运行环境中如果存在so就没有问题。
缘故原由和思路找到了,源码内里怎么写这个脚本呢?
  1. 1、复制文件到system/lib64
  2. PRODUCT_COPY_FILES += device/copyfile/libnative-lib.so:$(TARGET_COPY_OUT_SYSTEM)/lib64/libnative-lib.so
  3. //PRODUCT_COPY_FILES 目录是以release目录为基准的;
  4. //copyfile 这个文件夹是自己添加的,自定义的,可以根据自己情况设置。
  5. 2、复制文件到某个apk的目录下:
  6. PRODUCT_COPY_FILES += device/copyfile/libnative-lib.so:$(TARGET_COPY_OUT_SYSTEM)/priv-app/JniLoadso/lib/arm64/libnative-lib.so
复制代码
PRODUCT_COPY_FILES 指令,相信许多搞过系统源码都是知道的,这个就是复制文件的;
在device下的某个mk文件都有这个指令,在device目录此中一个起作用的写入上面的指令就可以。
正常情况下,写了上面指令,系统源码编译后就会在out目录下天生so文件,
好比写了第一条指令,就会在out/target/XXX…/system/lib64 看到 libnative-lib.so 文件。
三、其他

1、系统源码加载编译so小结

  1. (1) Android.mk 中可以使用 LOCAL_PREBUILT_JNI_LIBS指令复制so到编译的XXXapk/lib/arm64/目录下;
  2. (2) Android.bp 没有指令复制so到编译的apk目录下;
  3. (3) Android 系统编译源码应用可以读取系统so和apk目录下的lib/arm64/的so文件
  4. (4) 如果是使用Android.bp编译so项目,
  5. 必须要写脚本命令复制so到system/lib64 或者复制到apk的ib/arm64/
  6. (5) 如果是使用Android.mk编译so项目,
  7. 即可使用LOCAL_PREBUILT_JNI_LIBS指令复制so,也可以在另外的mk文件使用脚本复制so文件到system/lib64 或者复制到apk的ib/arm64/
  8. (6) 如果是单个应用使用的so,使用复制脚本命令把so文件复制到到apk的ib/arm64/就可以;
  9.          如果是多个应用使用到的so,使用复制脚本命令把so文件复制到到system/lib64/比较好。
复制代码
其实那些编译apk的指令都是差不多的,许多网上搜索到不可用的指令,参考系统源码其他apk编译的就可以;
最重要的是学习到了系统中编译源码apk 会读取 apk的ib/arm64/大概system/lib64 下面的so;
加载so肯定是以so文件名称作为唯一标识的,如果so文件名称不对是读取不到的;
Java代码中读取so:
  1.     static {
  2.         System.loadLibrary("native-lib");
  3.     }
复制代码
那么so的名称肯定要设置成 libnative-lib.so(native-lib.so是不行的),也就是说前面加lib,后面加.so,就是so文件的命名。
2、Android.mk中可以实行 PRODUCT_COPY_FILES 吗?

许多人大概没试过,不确定有没有作用。
我之前也么试过,本日特意试了一下,确实不行。
Android.mk中可以实行 PRODUCT_COPY_FILES 会报错:
  1. FAILED:
  2. In file included from build/make/core/prebuilt.mk:53:
  3. packages/SkgApps/JniLoadso/Android.mk:36: error: cannot assign to readonly variable: PRODUCT_COPY_FILES
复制代码
其实想一下就知道了,Android.mk内里应该是实行有限的指令和标签的;
在android.go内里确实是没有这个 PRODUCT_COPY_FILES 指令的。
3、mk 添加编译androidx相关包报错解决

AndroidManifest.xml.fixed 的分析处理:
https://blog.csdn.net/wenzhi20102321/article/details/138334484
4、Android.mk 在源码中实行实行转换成Android.bp

Android.mk和Android.bp的区别和转换详解:
https://blog.csdn.net/wenzhi20102321/article/details/135704801

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

民工心事

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表