zoukankan      html  css  js  c++  java
  • (OK) android源码环境内置已编译好的模块apk_so_jar_bin


    http://blog.csdn.net/sgmenghuo/article/details/52238933


    0、前言

        作为android开发人员,经常面对这样的问题:网上下载的apk预制到系统,第三方oem提供编译好的库或者jar包等,你要将这些编制到你的系统中该如何做,那么这就不得不要去熟悉android编译环境,即一系列以LOCAL_XXX这样的变量。其实我们实际上碰到的编译MODULE就那么几样,下面我一一列出,可能不全面但是够用了。

    1、第三方jar静态编译

        源码环境使用第三方jar,需要关注三个LOCAL_XXX:
    LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES值格式为  别名:库相对路径
    LOCAL_STATIC_JAVA_LIBRARIES
    BUILD_MULTI_PREBUILT第三方包,编译类型为BUILD_MULTI_PREBUILT
    其中zxing-1.6-core.jar放在apk源码目录的libs目录下
    Android.mk如下:
    1. LOCAL_PATH :=$(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4. LOCAL_MODULE_TAGS := optional  
    5. #LOCAL_JAVA_LIBRARIES := ScannerAPI  telephony-common telephony-msim   
    6. LOCAL_STATIC_JAVA_LIBRARIES :=zxing android-support-v4 android-support-v13  
    7. LOCAL_SRC_FILES :=$(call all-java-files-under, src)  
    8. LOCAL_PACKAGE_NAME := SetInput2  
    9. LOCAL_CERTIFICATE := platform   #签名为platform  
    10.   
    11.   
    12. include $(BUILD_PACKAGE)  
    13.   
    14.   
    15. include $(CLEAR_VARS)  
    16. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=zxing:libs/zxing-1.6-core.jar  
    17. include $(BUILD_MULTI_PREBUILT)  

    2、可执行程序bin

        比如我们想内置某些已编译好的busybox工具
    Android.mk如下:
    1. LOCAL_PATH:= $(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4. LOCAL_MODULE        :busybox  
    5. LOCAL_MODULE_TAGS   :optional  
    6. LOCAL_MODULE_CLASS  :EXECUTABLES  
    7. LOCAL_SRC_FILES     :busybox  
    8. LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/system/xbin  
    9. include $(BUILD_PREBUILT)  

    3、不带so的apk

        我在源码环境内置apk时发现有的可以运行,有的不能运行(说缺少lib64下的库),所以我分开说明如何内置这2中apk。
    RAR工具解压apk没有lib文件夹的就是不带so的apk,最简单。
    Android.mk如下:
    1. LOCAL_PATH := $(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4. LOCAL_MODULE_TAGS :optional  
    5. LOCAL_MODULE :rsota  
    6. LOCAL_SRC_FILES := $(LOCAL_MODULE).apk  
    7. LOCAL_MODULE_CLASS  :APPS  
    8. LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/app  
    9. LOCAL_CERTIFICATE :platform     
    10. LOCAL_MODULE_SUFFIX := .apk  
    11.   
    12. include $(BUILD_PREBUILT)  


    4、带so的apk

        解压apk,发现lib文件夹含有xxx.so就是带so的apk,一般这些so默认是32位的,当前我们使用的大量的设备都是64位cpu,apk一运行就曝出找不到lib64类型的库,我们只需要让他调用apk解压的那些32位的so库就行了。

    4.1、so库架构类型

        这里穿插下关于lib下so的一些故事。如下是youku.apk中lib目录下的:
        
    从这个图可以看出,这个youku.apk支持3种类型的cpu架构:arm,mips,x86,如果这里只有armeabi,那么是绝对不能正常安装到x86的android设备上的(比如使用x86架构的联想K900,好像还是科比代言,卖的好惨,反正我没看到有人用)。如果要提高多架构兼容,就得放入多架构的库,坏处就是apk好大啊吃手机内存啊,所以X86架构的手机好不好卖不是google决定的啊,是apk广大开发者决定的啊,没软件用,谁屌你,所以X86架构一般只能在几百块的水平打酱油,Windows Phone也是没软件用的例子。话说到这跑题了,我们继续库的类型。lib目录下一般包含着几种类型:armeabi,armeabi-v7a,arm64-v8a,mips,x86。不过我们只关注arm的。
    armeabi是普通老的32位arm,armeabi-v7a是带浮点运算及一些高级指令的32位arm,arm64-v8a是近几年A53 A57架构的64位arm,具体渊源见如下文章
    armeabi-v7a armeabi arm64-v8a》         http://blog.csdn.net/mao520741111/article/details/50328669
    现在市面上的基本都是32位apk,所以你基本看不到arm64-v8a库,但是从android L版本后确实是64位虚拟机了,当然是兼容32位的啦,在64位虚拟机运行当然会默认去运行lib64类型的库,而我们内置带so(内置一般都是32位的so)的apk就是要强制让apk去用现有的32位so,方法如下:

    4.2、带so库apk例子

    1)解包拿出lib下的armeabi或者armeabi-v7a下的xxx.so(最终内置到系统相对于apk目录的lib/arm下)
    2)Android.mk既要内置apk还要copy库
    注意预置模块,用到BUILD_PREBUILT

    例子一

    (apk,so和Android.mk在一个目录下):

    1. LOCAL_PATH := $(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4. LOCAL_MODULE_TAGS :optional eng  
    5. LOCAL_MODULE :LiangdusIME  
    6. LOCAL_SRC_FILES := $(LOCAL_MODULE).apk  
    7. LOCAL_MODULE_CLASS  :APPS  
    8. LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app  
    9. LOCAL_CERTIFICATE :platform  
    10. LOCAL_MODULE_SUFFIX := .apk  
    11. include $(BUILD_PREBUILT)  
    12.   
    13. include $(CLEAR_VARS)  
    14. LOCAL_MODULE        :libLDWWIme  
    15. LOCAL_MODULE_CLASS  :SHARED_LIBRARIES  
    16. LOCAL_MODULE_SUFFIX := .so  
    17. LOCAL_MULTILIB      :32  
    18. LOCAL_MODULE_TAGS   :optional  
    19. LOCAL_SRC_FILES     :libLDWWIme.so  
    20. LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/system/priv-app/LiangdusIME/lib/arm  
    21. include $(BUILD_PREBUILT)  


    例子一有点缺点,要在$(product).mk中进行如下添加PRODUCT_PACKAGES += LiangdusIME libLDWWIme,在库比较少的时候没问题,多的时候,就比较麻烦了。比如一个apk有10个库,那么Android.mk都要要写10个module,$(product).mk也要写上这10个module名,麻烦死了,按道理就是一个apk,就写一个LOCAL_MODULE,其他的库应该有某种简单办法依赖一起内置,是的确实有那就是BUILD_MULTI_PREBUILT.

    例子二

    目录结构为
    ---Android.mk
    ---SeuicService.apk
    ---armeabi-v7a
           |---libctp_jni.so
           |---libkeypad_jni.so
    ---arm64-v8a
           |---libctp_jni.so
           |---libkeypad_jni.so

    1. <span style="font-size:14px;">LOCAL_PATH := $(call my-dir)  
    2.   
    3. #====== so lab =====  
    4. include $(CLEAR_VARS)  
    5. LOCAL_PREBUILT_LIBS :armeabi-v7a/libctp_jni.so  
    6. LOCAL_MULTILIB :32  
    7. LOCAL_MODULE_TAGS :optional  
    8. include $(BUILD_MULTI_PREBUILT)  
    9.   
    10. include $(CLEAR_VARS)  
    11. LOCAL_PREBUILT_LIBS :armeabi-v7a/libkeypad_jni.so  
    12. LOCAL_MULTILIB :32  
    13. LOCAL_MODULE_TAGS :optional  
    14. include $(BUILD_MULTI_PREBUILT)  
    15.   
    16. include $(CLEAR_VARS)  
    17. LOCAL_PREBUILT_LIBS :arm64-v8a/libctp_jni.so  
    18. LOCAL_MULTILIB :64  
    19. LOCAL_MODULE_TAGS :optional  
    20. include $(BUILD_MULTI_PREBUILT)  
    21.   
    22. include $(CLEAR_VARS)  
    23. LOCAL_PREBUILT_LIBS :arm64-v8a/libkeypad_jni.so  
    24. LOCAL_MULTILIB :64  
    25. LOCAL_MODULE_TAGS :optional  
    26. include $(BUILD_MULTI_PREBUILT)  
    27.   
    28. # ====  app ========================  
    29. include $(CLEAR_VARS)  
    30.   
    31. LOCAL_MODULE_TAGS :optional  
    32. LOCAL_MODULE :SeuicService  
    33. LOCAL_MODULE_CLASS :APPS  
    34. LOCAL_CERTIFICATE :PRESIGNED     #预签名过了,不需在签名了  
    35. LOCAL_MODULE_PATH := $(TARGET_OUT)/app  
    36. LOCAL_REQUIRED_MODULES :=         #本模块加入系统,我需要的依赖模块也必须加入  
    37.         libkeypad_jni   
    38.             libctp_jni  
    39. LOCAL_SRC_FILES :SeuicService.apk  
    40.   
    41. include $(BUILD_PREBUILT)</span>  

    其中LOCAL_REQUIRED_MODULES表示预置SeuicService这个模块时,会先去执行依赖的模块,就是内置so库。这样执行的结果是SeuicService.apk放到了android系统的system/app下,armeabi-v7a的2个so库内置到了android系统的system/lib/下,arm64-v8a的2个so放到了system/lib64/下,apk不管运行在32还是64位虚拟机都能正常。
    例子二的区别是so库谁都能用,例子一的so库只有自己能用。

    例子三

    目录结构为
    ---Android.mk
    ---Chrome.apk
    ---lib
         |---armeabi-v7a
                |---crazy.libchrome.so
                |---libchrome.1847.114.so
    |---crazy.libchrome.align
    |---libchrome.1916.122.so
    |---libchrome.1916.138.so
    |---libchrome.1916.141.so
    |---libchrome.1985.122.so
    |---libchrome.1985.128.so
    |---libchrome.1985.131.so
    |---libchrome.1985.135.so
    |---libchrome.2062.117.so
    |---libchrome.2125.102.so
    |---libchrome.2125.114.so
    |---libchrome.2171.37.so
    |---libchrome.2171.59.so
    |---libchromium_android_linker.so
    |---libchromeview.so

    1. LOCAL_PATH := $(call my-dir)  
    2.   
    3. # ====  app ========================  
    4. include $(CLEAR_VARS)  
    5.   
    6. LOCAL_MODULE_TAGS :optional  
    7. LOCAL_MODULE :Chrome  
    8. LOCAL_MODULE_CLASS :APPS  
    9. LOCAL_CERTIFICATE :PRESIGNED  
    10. LOCAL_MODULE_PATH := $(TARGET_OUT)/app  
    11. LOCAL_POST_PROCESS_COMMAND := $(shell mkdir -p $(LOCAL_MODULE_PATH)/Chrome/lib/arm)   
    12. LOCAL_POST_PROCESS_COMMAND := $(shell cp -r $(LOCAL_PATH)/lib/armeabi-v7a/* $(LOCAL_MODULE_PATH)/Chrome/lib/arm)   
    13. LOCAL_SRC_FILES :Chrome.apk  
    14.   
    15. include $(BUILD_PREBUILT)  

    这是自由度最大的的方法,这个LOCAL_POST_PROCESS_COMMAND太厉害了简直为所欲为,因为它所引起的shell命令在make初期搜索Android.mk就执行了(我试过了可以多次加入执行)那个时候连system目录等都还没建立呢,这就是为什么我先mkdir再去cp,不然cp在目录没生成的情况下是失败的,而且注意了不报错。所以这种使用方式,需要你预先知道你要干什么,你得能预料结果,一般我就用mmm编译然后到out目录去验证。

    5、源码集成带第三方so,jar的apk

    这个是网上找到了
    1. LOCAL_PATH:= $(call my-dir)    
    2.   
    3. include $(CLEAR_VARS)  
    4. LOCAL_MODULE_TAGS :optional    
    5. LOCAL_STATIC_JAVA_LIBRARIES :libbaidumapapi    
    6. LOCAL_SRC_FILES := $(call all-subdir-java-files)    
    7. LOCAL_PACKAGE_NAME :MyMaps    
    8. include $(BUILD_PACKAGE)    
    9.   
    10. ##################################################    
    11.   
    12. include $(CLEAR_VARS)    
    13.   
    14. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libbaidumapapi:libs/baidumapapi.jar    
    15. LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so    
    16. LOCAL_MODULE_TAGS :optional    
    17.   
    18. include $(BUILD_MULTI_PREBUILT)    

    6、其他预编译

    其他如各种配置文件的拷贝基本都是通过include $(BUILD_PREBUILT)或者include $(BUILD_MULTI_PREBUILT)来完成,比如

    include $(CLEAR_VARS)
    LOCAL_MODULE := com.seuic.misc.xml
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE_CLASS := ETC
    LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    include $(BUILD_PREBUILT)

    基本就是修改LOCAL_MODULE名字,或者修改LOCAL_MODULE_CLASS(类型检查,临时文件存放等),以及修改LOCAL_MODULE_PATH放到哪。
    其中LOCAL_MODULE_CLASS值有:APP,ETC,STATIC_LIBRARIES,EXECUTABLES,JAVA_LIBRARIES,SHARED_LIBRARIES等



    另外,Android.mk它也是makefile,不要以为它就是特殊的文件,什么都强制照搬,思维会定在如何去用LOCAL_XXX上面,如果你足够熟悉,你可以更灵活点,当然可能不好看。


    顺便提下
    1)上面看到LOCAL_MODULE_TAGS := optional都是要在$(PRODUCT).mk中将模块名加入到PRODUCT_PACKAGES中的,否则make不编译别找我。
    2)将so提升为系统库,就是对应so放到android系统的system/lib或者system/lib64下,这样系统中任何java文件就有机会通过System.loadLibrary("yyy"); 加载libyyy.so,但是,但但是,这个so不是普通c用的so,是jni格式的so。
    3)将jar提升为系统包,就是将jar放到android系统的system/framework下,且添加权限,添加权限有2中方法(假设jar文件名为scanner.jar其java包名为com.seuic.scanner,模块名为scan)。
    方法一:在$(PRODUCT).mk中添加PRODUCT_BOOT_JARS+=scan
    方法二:在对应的*.rc中追加scanner.jar,用冒号分割,export BOOTCLASSPATH /system/framework/core.jar:scanner.jar,这个基本被方法一替代,不要再使用了,编译会自动展开PRODUCT_BOOT_JARS,在系统的root目录下生成init.environ.rc(内容全是export导出的环境变量)
    方法三:这个方法独立性比较好,建议用这个方法。
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <permissions>  
    3.     <library  
    4.         name="com.seuic.scanner"  
    5.         file="/system/framework/scanner.jar"  
    6.      />  
    7. </permissions>  
    4)Android如何调用第三方SO库
    http://zwz94.blog.163.com/blog/static/3206039520131111101412959/
    这篇文章问的还是有点意义的,看看能加深理解

  • 相关阅读:
    Tomcat 8.5 添加https认证
    常用服务的搭建、配置及优化
    Linux基础知识整理
    在CentOS-6系统中二进制安装MySQL-5.6
    搭建本地yum源仓库
    Redis-请慎用String类型
    Redis AOF日志备份原理
    MySQL 输入查询
    MySQL 命令行连接选项
    感思-最好的优化就是减少数据量!
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645086.html
Copyright © 2011-2022 走看看