美文网首页android源码Android开发
放弃用Android.mk的方式编译APK

放弃用Android.mk的方式编译APK

作者: andforce | 来源:发表于2019-02-15 19:19 被阅读0次

    不知道Android从哪个版本开始,在AOSP中使用mm编译,变得无比缓慢,严重拖慢了开发节奏。
    想要加快mm编译除了提高电脑的硬件配置之外,还可以使用Android Studio搭配Gradle的方式编译Apk。

    从0开始

    我最初学习开发Android的时候,都是用的Eclipse+ADT插件编译调试的,目前这种方式已经被摒弃,不推荐了。
    因此接下来只讲Android Studio + Gradle的方式。
    先不要管目前手头的代码是什么方式,或者什么目录结构的,我们的目的要把老的目录结构转换成标准的Android Studio的结构,并且要支持 Android.mk 编译

    使用AndroidStudio创建一个Project,然后放到AOSP中进行mm编译能生成apk,并顺利运行

    AndroidStudio生成的Project的目录结构:

    ├── app
    │   ├── app.iml
    │   ├── build
    │   │   ├── generated
    │   │   ├── intermediates
    │   │   ├── outputs
    │   │   ├── reports
    │   │   └── tmp
    │   ├── build.gradle
    │   ├── proguard-rules.pro
    │   └── src
    │       ├── androidTest
    │       ├── main
    │       └── test
    ├── build
    │   └── intermediates
    │       └── lint-cache
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── GradleAndroidmkDemo.iml
    ├── gradle.properties
    ├── gradlew
    ├── gradlew.bat
    ├── local.properties
    └── settings.gradle
    
    build.gradle转换成Android.mk

    先看以下app目录下的build.gradle:

    apply plugin: 'com.android.application'
    
    android {
        // compileSdkVersion 27, 要跟你AOSP的版本匹配,不能高与AOSP的版本,否则容易出问题
        // 下面的 minSdkVersion 21 和 targetSdkVersion 27 也需要注意
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.andforce.gradleandroidmkdemo"
            minSdkVersion 21
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.1.1'
    
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    }
    

    我们可以看到,其实主要依赖了:

        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    
    寻找依赖库

    1:从ASOP源码中查找
    在AOSP代码中的framework/support存放了很多库:

    .
    ├── Android.mk
    ├── annotations
    │   ├── AndroidManifest.xml
    │   ├── Android.mk
    │   ├── api
    │   ├── build.gradle
    │   ├── external-annotations
    │   └── src
    .
    .
    .
    
    ├── v13
    │   ├── AndroidManifest.xml
    │   ├── Android.mk
    │   ├── api
    │   ├── build.gradle
    │   ├── java
    │   ├── lint-baseline.xml
    │   └── tests
    ├── v14
    │   ├── Android.mk
    │   └── preference
    ├── v17
    │   ├── Android.mk
    │   ├── leanback
    │   └── preference-leanback
    ├── v4
    │   ├── AndroidManifest.xml
    │   ├── Android.mk
    │   ├── build.gradle
    │   └── lint-baseline.xml
    ├── v7
    │   ├── Android.mk
    │   ├── appcompat              #这里就是我们需要的
    │   ├── cardview
    │   ├── gridlayout
    │   ├── mediarouter
    │   ├── palette
    │   ├── preference
    │   └── recyclerview
    └── wear
        ├── AndroidManifest.xml
        ├── Android.mk
        ├── api
        ├── build.gradle
        ├── lint-baseline.xml
        ├── proguard-rules.pro
        ├── README.txt
        ├── res
        ├── res-public
        ├── src
        └── tests
    

    可以看到正好有我们此次用到的appcompat-v7,其他什么v4 之类也有。
    但是没有看到constraint-layout,这时候就要祭出神器了:
    https://mvnrepository.com/
    想要依赖什么,直接把包名或者库名放到红色框内搜一下就出来了

    image.png
    这次我们需要的是com.android.support.constraint:constraint-layout:1.1.3,所以我们搜com.android.support.constraint看看:
    image.png
    点击进去之后可以看到:
    image.png
    然后我们就得到了constraint-layout-1.1.3.aar
    image.png
    根据经验,仅仅有了constraint-layout还是不行,还需要一个constraint-layout-solver的jar

    同理,我们在上面的网站也能得到:constraint-layout-solver-1.1.3.jar

    开始编写 Android.mk

    在工程的根目录下(与app目录同级别),创建Android.mk

    LOCAL_PATH:= $(call my-dir)
    
    # 清除除了LOCAL_PATH外的所有变量
    include $(CLEAR_VARS)
    
    # support包的根目录,因为编译时我们只能引用来自于framework的support包
    support_library_root_dir := frameworks/support
    
    # 设置src 和 res
    LOCAL_SRC_FILES := $(call all-java-files-under, app/src/main/java)
    LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, app/src/main/res) \
        $(support_library_root_dir)/v7/appcompat/res
    
    # 指定Manifest文件
    LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
    
    # 重复资源自动覆盖
    LOCAL_AAPT_FLAGS += \
        --auto-add-overlay \
        --extra-packages android.support.v7.appcompat \
        --extra-packages android.support.constraint
    
    # frameworks/support/ 下有v7 和 v4的源码
    LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-appcompat android-support-v4
    # constraint-layout需要的jar
    LOCAL_STATIC_JAVA_LIBRARIES += constraint-layout-solver
    
    # 依赖库,aar
    LOCAL_STATIC_JAVA_AAR_LIBRARIES := constraint-layout
    
    # Apk名称
    LOCAL_PACKAGE_NAME := GradleAndroidmkDemo
    
    # BUILD_PACKAGE 是一个预定义的宏,里面包含编译一个APK的脚本。
    include $(BUILD_PACKAGE)
    
    include $(CLEAR_VARS)
    
    # 构建依赖的jar
    LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layout-solver:app/mk/libs/constraint-layout-solver-1.1.3.jar
    # 构建依赖的aar
    LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layout:app/mk/aars/constraint-layout-1.1.3.aar
    
    include $(BUILD_MULTI_PREBUILT)
    
    include $(call all-makefiles-under,$(LOCAL_PATH))
    

    如果没有什么特殊情况,我们把这个Project放到packages/apps下,进行mm编译就能生成apk了,至此我们的第一步就走完了。

    Project依赖多个Moudle怎么办?

    我们创建一个module叫mylibrary,然后让app依赖它:

    ├── Android.mk
    ├── app
    │   ├── app.iml
    │   ├── build
    │   ├── build.gradle
    │   ├── mk
    │   ├── proguard-rules.pro
    │   └── src
    ├── build
    │   └── intermediates
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    ├── GradleAndroidmkDemo.iml
    ├── gradle.properties
    ├── gradlew
    ├── gradlew.bat
    ├── LICENSE
    ├── local.properties
    ├── mylibrary
    │   ├── build
    │   ├── build.gradle
    │   ├── libs
    │   ├── mylibrary.iml
    │   ├── proguard-rules.pro
    │   └── src
    ├── README.md
    └── settings.gradle
    

    此时,我需要求改Android.mk,让其能把mylibrary编译进去。

    # 添加mylibrary的src和res
    LOCAL_SRC_FILES += $(call all-java-files-under, mylibrary/src/main/java)
    # 这里需要注意,由于library的拥有自己的package name,因此会生成自己的R文件,不能直接把res路径直接加上,需要向下面这样写
    LOCAL_AAPT_FLAGS += --auto-add-overlay -S $(addprefix $(LOCAL_PATH)/, \
        mylibrary/src/main/res) --extra-packages com.andforce.mylibrary
    

    到现在,我们已经完成了依赖Module的编译过程。

    相关文章

      网友评论

        本文标题:放弃用Android.mk的方式编译APK

        本文链接:https://www.haomeiwen.com/subject/rivmeqtx.html