• 安卓gradle使用


    在这里插入图片描述

    https://www.cnblogs.com/lsgxeva/p/13382844.html


    是android 的主流编译工具
    以前gradle因为编译过程的原因有点慢
    与android studio关系紧密
    对简单程序基本不需要配置代码,值使用android studio就可以完成编译和运行
    对于复杂的多人合作项目会使用一些个性化配置提高开发效率
    比如自定义一下编译包名字,对同一产品编译出免费版和付费版apk等
    android studio 2.0发布之后,gradle升级为instant run,编译速度逆天

    gradle编译周期

    gradle里的项目和task,每个项目至少一个project,一个build.gradle就代表一个poject,每个project包含多少个task,task里包含很多action,action代码块里包含一些需要被执行的代码
    编译过程关爱到了根据build相关文件聚合所有的project和task,执行task里的action,因为build.gradle里的task很多,所以用依赖逻辑保证执行顺序,几乎所有的task都需要依赖其他的task执行,没有依赖的task首先执行
    编译分为三个阶段

    初始化阶段:创建project对象,有多个gradle就创建多个project
    配置阶段:这个阶段执行所有的编译脚本,同时创建项目的所有task,为执行阶段做准备
    执行阶段:在这个阶段gradle根据传入的参数决定如何执行这些task,action的执行代码都在这里
    
    
    • 1
    • 2
    • 3
    • 4

    gradle文件

    实际上是一个app下面对应一个build.gradle,settings.gradle,然后下面是子app,子app有自己的build.gradle
    setting.gradle定义哪些模块加入编译过程,单个模块的app是一般不需要这个文件,此文件在初始化的时候被执行
    顶层的build.gradle里的配置用到所有的项目,典型配置里在buildscript里定义android编译工具的类路径仓库里的JCenter是一个maven库
    allprojects里定义的属性会被应用到所有module里
    apply插件里用了安卓的gradle插件,插件里提供编译打包等task
    buildType里定义了编译类型,对调试和发布可以有不同配置

    gradle wrapper

    为了兼容旧版本产生
    包括一些脚本文件和针对不同系统的运行文件,会自动下载对呀版本的运行文件
    https://www.cnblogs.com/lsgxeva/p/13382844.html
    可以使用gradlew列出所有的task和task的依赖
    wrapper是我们使用命令行编译的开始
    在as点击build,rebuild,clean的时候都触发了对应的gradle task
    四个基本task
    assemble可以把所有的buildtype(调试,发布)生成apk包
    clean可以移除所有的编译输出文件,比如apk
    check可以执行lint监测编译
    build同时执行assemble和check命令

    buildconfig

    可以通过buildconfig.debug判断当前版本是否是debug版本,gradle编写语言是groovy,一种jvm语言,groovy可以生成java字节码类

    repositories

    可以加入项目链接
    如果仓库有密码可以传入用户名和密码
    还可以用相对路径配置一下本地仓库,通过配置项目里存在的静态文件夹作为本地仓库

    Dependencies

    库名称由组名,库名称和版本号组成
    为了保证依赖库是最新状态可以使用通配符+,但是会导致每次都要用网络请求查看是否有最新版本导致编译过慢
    也可以使用file()添加文件依赖,如果有多个jar包依赖可以放到文件夹里使用filetree引用
    配置本地的so库可以
    不方便直接引用项目需要使用文件形式引入就把项目打包成aar文件
    这样我们在项目下新建aars文件夹之后配置一下仓库,引用的时候

    区别构建

    在debug和release的时候可能需要配置不同的服务器地址,打包市场渠道包的时候可能要打免费版收费版或内部版外部版程序
    这是有buildtype区分
    可以创建新的编译类型
    gradle默认创建一个新的资源集,可以建立不同的文件夹,里面放上需要的不同资源和代码

    针对同一份源码编译不同的程序编译收费和免费版可以使用product flavors
    想build type一样也是可以有不同文件夹和配置
    复杂情况可能需要多个product的未读进行组合,比如想要颜色和价格两个维度组合,先创建维度,之后是维度细分
    buildtype里的优先级最大

    可以开启并行编译加快编译
    可以开启守护进程,二次编译的时候重用进程
    可以使用shrinkresources渠道编译的时候不需要的资源
    用shrinkReleaseResources命令可以看懂减少了哪些资源
    一些需要动态加载的资源需要向Progard的一样对资源进行keep操作
    可以再res/raw/下建立一个keep.xml文件keep资源
    对一些特殊文件或文件夹,如国际化的资源文件,屏幕适配资源,如果已经确定了某种型号不需要重新适配可以去掉不适配的资源

    自定义task

    groovy

    在groovy里没有固定类型,变量直接使用def引用
    使用单引号只是字符串,双引号里面还可以放变量$变量名
    方法也使用def声明,不指定返回值就返回最后一行代码的值
    默认所有类和方法都是公共的,所有类的字段是private
    通过new得到实例来引用
    类里生命的字段都会默认生成对应的settinggetter方法,groovy方法调用时可以没有括号的,也不需要分号结尾,也可以直接调用
    可以通过instance.greeting方式拿到字段值,也是通过get方法的

    在map,collections
    定义一个列表遍历列表使用each
    定义一个map,获取map使用get或[]
    闭包,匿名内部类,支持类似lamda形式的语法调用
    task执行的时候action依次执行
    可以在里面写dolast和dofirst方法
    关于Task 的依赖有两种,must RunAfter和dependsOn
    must必须按顺序加入之后顺序之后,后者是同时执行的

    impletation里的依赖是怎样引入的

    建立自己的android库

    新建的时候选择新建模块–android library–之后在minimum sdk里是api16
    之后吧代码传到library里上传github
    然后发布代码就可以发布了

    volley使用概览

    https://developer.android.com/training/volley?hl=zh-cn
    是一个可以让应用更轻松更快联网的http库
    可以自动网络请求调度,可以有多个并发网络链接
    有透明磁盘和具有标准http缓存一致性的内存响应缓存
    支持请求的优先级,可以取消单个请求并且设置要取消的请求的时间段或范围
    可以自定义重试和退避的时间
    强大的排序功能,可以轻松从网络异步提取的数据正确填充界面
    可以用结构化数据形式获取搜索结果页面,可以轻松集成各种协议,开箱后就支持原始字符串图片和json
    不适合下载大量内容的操作和流式传输操作,在解析过程里会把所有的响应存储在内存里,大量下载内容的操作需要使用downloadManager等替代方法

        dependencies {
            ...
            implementation 'com.android.volley:volley:1.1.1'
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5

    implementation和api的区别

    https://blog.csdn.net/geyuecang/article/details/105270669
    implementation引入,gradle会把依赖项添加到编译类路径,并且吧依赖项打包到构建输出,其他模块只有在运行的时候才可以使用这个依赖项
    使用这个依赖项配置代替api或已经弃用的compile可以缩短构建时间减少构建系统需要重新编译的模块数,比如implementation依赖项更改了其api,gradle只重新编译改依赖项以及直接依赖于它的模块
    api引入
    gradle不仅吧依赖项添加到编译类路径还添加到构建输出里,一个模块包涵api依赖项的时候,会让gradle了解该模块需要以传递方式导出到其他模块,让其他模块运行和编译的时候都可以使用这个依赖项
    类似于compile,但是只能对需要以传递方式导出到其他上游消费者的依赖项使用它,如果api依赖项更改了其外部api,gradle会在编译的时候重新编译所有访问该依赖项的模块,会显著增加构建时间
    https://blog.csdn.net/ezconn/article/details/112851615

    com.android和com.mcxiaoke

    com.android是android内置的

    确定应用是否支持64位库

    检查apk文件结构
    对于 ARM 架构,32 位库位于 armeabi-v7a 中。 对应的 64 位库则位于 arm64-v8a 中。
    对于 x86 架构,32 位库位于 x86 中,64 位库则位于 x86_64 中。
    https://developer.android.com/games/optimize/64-bit?hl=zh-cn

    编译报错多个第三方库没有64位架构包

    https://www.csdn.net/tags/NtzaQg1sNjc5ODAtYmxvZwO0O0OO0O0O.html
    有一个项目需要把coocos引擎升级到支持64位的

    apk包里的dex文件

    是android系统里的一种文件,和apk以及jar格式类似
    就是所优化后的安卓版exe文件
    在java程序编译成class之后还需要使用dx工具吧所有class文件整合为一个dex文件让各个类共享数据,是jar文件大小的一半
    实际上就是在pc使用的java虚拟机可以运行class文件,android系统的davlik虚拟机运行dex文件
    使用反编译工具可以获取java源码,修改dex文件可以更好的防破解
    java,C和C++都可以生成dex文件
    生成
    IDE可以帮助build生成dex文件,也可以在class文件下使用dx --dex --output指令生成dex文件

    dx --dex --output TestMain.dex TestMain.class
    
    • 1

    dex文件在手机上可以使用adb运行
    先使用adb push吧生成的dex文件push到手机的一个目录里,之后使用adb shell链接手机之后执行dalvikvm -cp命令执行该文件,不需要写dex后缀
    https://blog.csdn.net/tabactivity/article/details/78950379

    node_modules 目录结构

    https://segmentfault.com/a/1190000022579808?utm_source=tag-newest
    npm install 执行完毕后,我们可以在 nodemodules 中看到所有依赖的包

    第三方库是否支持64位架构的问题

    怎么判断第三方库/sdk是否支持64位架构

    build的时候把一些包变成dex文件

    插件化开发的时候想让app快速启动,需要让主dex只包含首页和基础模块,其他放到从dex里
    所以先让项目支持multidex
    https://blog.csdn.net/hujin2017/article/details/102719506

    android {
    
        defaultConfig {
            // 设置支持multidex
            multiDexEnabled true
        }   
    }
    dependencies {
        //引入对multidex支持的库	
        compile 'com.android.support:multidex:1.0.1'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在自定义的application中的attachBaseContext方法中添加如下代码:

       @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
            MultiDex.install(this);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    明确主dex文件中要包含哪些class文件,明确后,在module的build.gradle所在的目录下,新建一个maindexlist.txt文件,并将这些class文件所在的路径都写入到这个文件中。

    引入第三方库的三个方式

    https://segmentfault.com/a/1190000040411873?utm_source=sf-similar-article
    在build.gradle里添加依赖是使用的gradle抓取方式
    默认是谷歌和jcenter两个库,还可以自己添加maven库
    下载jar包到模块的libs下
    然后右键Add as library…
    或者在dependencies里
    导入本地库

    implementation files('libs/cglib-for-android.jar')
    
    • 1

    导入这个模块下所有的jar包

    implementation fileTree(dir: 'libs',includes: ['*.jar','*.aar'])
    
    • 1

    引入第三方库

    https://blog.csdn.net/qq_32534441/article/details/107069737
    一次性引入libs目录下所有jar文件

    compile fileTree(include: ['*.jar'], dir: 'libs')
    
    • 1

    远程依赖原理

    https://blog.csdn.net/Deemons/article/details/77588327
    as是从文件定义的仓库服务器下载library的
    库的字符串形式包涵三个部分,groupid+library名称+版本号
    as下载之后和我们的项目一起编译

    as下载的远程依赖包

    一般在as本地缓存库里
    在这里插入图片描述

    pom,aar,jar

    远程依赖到本地as缓存之后有这几个文件
    在aar的源码里不管使用 implementation 或者 api,打成 aar 包之后,当我们通过 gradle 脚本上传到服务器时,我们可以通过 pom.project 来将 aar 源码中的依赖生成 pom.xml 文件。这些依赖配置项会通过脚本,被转义成 maven 中的依赖配置项

    settings.gradle

    是子模块配置文件,单项目构建可以不用,多项目必须用
    根目录下的可以配置所有的module
    rootProject.name = 'project-root’指定父模块的名称
    include用于加载子系统以及模块
    gradle工作流程
    初始化的时候先解析settings.gradle
    配置阶段,解析每个build.gradle,只解析不执行各个build.gradle里的task
    解析完形成一个task有向图方便后续执行task
    在所有project配置完之后有一个回调.afterEvaluate,表示所有的模块都已经配置完了。
    之后开始执行task

    build.gradle

    plugins里是需要引入的插件

        // Spring boot
        id 'org.springframework.boot' version '2.1.6.RELEASE'
        // Maven
        id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    
    • 1
    • 2
    • 3
    • 4

    仓库配置里
    仓库用于存储下载的依赖或远程或缓存

    Android studio插件,检查依赖的so是否支持64位(或者其他的abi)

    https://blog.csdn.net/qq_15345551/article/details/121518218?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-4-121518218.pc_agg_new_rank&utm_term=Android+%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E6%94%AF%E6%8C%8164%E4%BD%8D%E6%9E%B6%E6%9E%84&spm=1000.2123.3001.4430
    pk构建的过程中,会执行{merge[BuildVariants]NativeLibs}这个task去合并所有的依赖,包括远程和本地
    通过dependencyInsight,我们可以查找到这个so文件最顶层的依赖

    64位打包的apk里的so文件特别少

    https://blog.csdn.net/Duker_tec/article/details/122078281
    在这里插入图片描述

    .so文件

    就是动态链接库,是linux系统里的,是linux系统的可执行文件,共享库文件
    可以让多个程序共享一个动态链接库
    app的二进制接口定义了二进制文件(包括so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐,到可用的系统函数库,每个系统架构对应一个abi
    项目只要使用ndk就生成so文件
    ndk是吧C变成so文件,sdk是吧java变成so文件
    Native Libs Monitor可以帮助看到apk用了哪些so文件,以及so文件来源于哪些函数库或框架

    Native Libs Monitor在as里的使用

    apk打包原理

    apk包打包之后使用PackageManager安装,在小于Android 5.0的系统中,.so文件位于app的nativeLibraryPath目录中;在大于等于Android 5.0的系统中,.so文件位于app的nativeLibraryRootDir/CPU_ARCH目录中。

    直接/间接

    联系github作者

    1.在仓库提issue
    2.看作者简介
    https://blog.csdn.net/weixin_44424296/article/details/114460923

    gradle升级instant run

    强制让所有模块都用相同的支持库版本

    https://blog.csdn.net/yang123465/article/details/80677753
    引用的第三方库的支持库版本低于(或者不一致)app build.gradle中的支持库版本

    android{
    
    
        configurations.all {  
            resolutionStrategy.eachDependency { DependencyResolveDetails details ->  
                def requested = details.requested  
                if (requested.group == 'com.android.support') {  
                    if (!requested.name.startsWith("multidex")) {  
                        details.useVersion '27.7.1'  
                    }  
                }  
            } 
    
        } 
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    gradle常用操作

    https://www.csdn.net/tags/MtTaEg0sNjM5NDk5LWJsb2cO0O0O.html
    可以获取所有gradle版本,可以再项目的build.gradle里配置统一的版本号
    在模块的default配置里可以引用project的build.gradle里的项目别名和里面的关键字指定统一的版本名等
    注解处理器是javac的一个工具,可以再编译的时候扫描和处理注解,获取到注解和被注解对象的相关信息之后根据注解自动生成java代码
    https://blog.csdn.net/wusj3/article/details/88415798
    gradle里的多渠道管理可以再里面设置测试用的appid,或者不同url的根地址
    然后一些第三方sdk申请到的appkey在manifest文件里使用meta-data标签设置value和name,可以先写一个占位符,之后在gradle的defaultconfig里配置
    gradle是纯java写的
    可以使用BuildConfig.DEBUG决定是否打印log,buildConfigField(“boolean”, “isBeta”, “true”)

    打包64位

    https://blog.csdn.net/lyabc123456/article/details/81557220

    apk打包原理

    https://blog.csdn.net/lazyer_dog/article/details/54581148
    先打包资源变成R.java
    之后处理AIDL文件生成相应的java文件,没有用的aidl文件就跳过
    编译项目里所有的Java文件为class文件
    吧class文件变成dex文件
    打包成apk
    对apk进行签名,keysrore,签名完才可以安装到设备上
    对签名完的文件进行对齐处理

    检查第三方lib合规性

    https://developer.android.com/distribute/best-practices/develop/64-bit
    https://blog.csdn.net/ouyang_peng/article/details/51168072

    混淆打包

    https://www.cnblogs.com/xqxacm/p/5897435.html

  • 相关阅读:
    解决DCNv2不能使用高版本pytorch编译的问题
    Java面试题:请谈谈Java中的volatile关键字?
    Transformer学习路线
    分数限制下,选好专业还是选好学校?过来人跟你说
    java开发岗位面试
    10大python加速技巧
    Allegro DVT与SiMa.ai携手优化嵌入式边缘应用的能效
    安防监控系统/视频云存储/视频监控平台EasyCVR无法级联上级平台,该如何解决?
    输入网址到网页显示,期间发生了什么?(收藏篇)
    在C/C++中使用vcpkg
  • 原文地址:https://blog.csdn.net/weixin_46045444/article/details/124021563