android预编译apk的深入思考

    xiaoxiao2021-03-30  40

    有时候我们会去和别的客户合作开发一些项目,但是出于安全性的考虑,独立的模块我们不会发布源码,只会以apk或者so的形式release给客户。

    合作的时候我们这边的apk release给用户,但是客户编译的OTA包运行起来后此apk开机会挂掉,提示找不到jni,但去单板的对应目录去查看发现此jni的so是存在的,比较奇怪。

    Line 60: E/AndroidRuntime( 4751): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/system/app/xxxxGuide/xxxxGuide.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]] couldn't find "libxxxxjni.so" Line 95: E/AndroidRuntime( 4782): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/system/app/xxxxxService/xxxxxService.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]] couldn't find "libxxxxjni.so"

    询问高手后,给出的结论是: 从log看,这些apk加载so出错了。这些apk是不是没有按照系统标准编译来编啊? 如果是源码,一定要通过Android.mk来编译,如果是release的apk文件,也需要通过Android.mk来预编译。不能把eclipse或者AndroidStudio中的apk直接拖过来用。

    但是自己还是不太理解,回顾此apk的编译方式,发现此apk是编译时直接cp apk到out目录的。此apk运行的时候会间接的通过java接口依赖到此jni so上去,而cp apk到out目录打包到OTA包的时候会破坏apk的运行查找规则,需要手动建立依赖关系才行。手动建立依赖关系需要通过预编译来实现。

    具体分析: 开机的时候 xxxxxService的apk会跑到lib64下去找libxxxjni的so找不到报错,而我们的apk是32位的,只允许去32库下去查找。 —因为从Android5.0之后,Android从32位升级到64位系统 ps查看zygote进程是32和64共存,

    ps |grep zygote root 1564 1 2066844 89296 ffffffff a6675f44 S zygote64 root 1565 1 1478752 76004 ffffffff f72066e8 S zygote

    如果一个apk的部分方法有依赖jni so的话,在编译的时候需要指定此apk是32位的还是64位,如果不指定就会默认去64位lib下去找; 1、用源码编译的时候在Android.mk中指定

    LOCAL_JNI_SHARED_LIBRARIES := libxxxxjni LOCAL_MULTILIB := 32

    编译出来的out目录下apk文件夹中会创建arm/lib目录,去此目录下ll查看可看的有软链接 libxxxxjni.so -> /system/lib/libxxxxjni.so,但去Samba去查看的时候此文件夹为空; 2、如果不用源码编译,在代码编译的时候只放apk,在编译的时候只做拷贝到out目录的动作 –这样会导致我们最初遇到的错误,寻找so报错,因为我们手动破坏了apk和so的链接关系,所以要做apk的预编译来重新建立软链接; –方法是在apk的目录下创建Android.mk文件, 例如:

    include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_MODULE := xxxxxService LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) LOCAL_CERTIFICATE := platform LOCAL_SRC_FILES := xxxxxService.apk LOCAL_JNI_SHARED_LIBRARIES := libxxxxjni LOCAL_MULTILIB := 32 LOCAL_MODULE_PATH := $(TARGET_OUT_APPS) include $(BUILD_PREBUILT)

    这样编译生成的out目录下apk文件夹中就会有arm/lib的文件夹,apk和so的软链接关系存在正常。 或者加入LOCAL_32_BIT_ONLY := true这句话,指定此apk只用32位,这样编译的apk默认为32位,编译生成的out目录下的此apk文件夹不会创建arm/lib目录。

    通过第二种方式重新预编译后,apk运行正常。

    转载请注明原文地址: https://ju.6miu.com/read-665237.html

    最新回复(0)