这里的模块指的是Module,As新建立工程,自动生成一个app的Module

项目体量比较大的情况下,对代码划分不同的Module,再通过gradle组合编译.

在代码比较多的情况下

优势:

模块可以单独编译,比整体编译更快;

查找问题,可以快速定位;

方便文件分类管理

模块添加和删除

添加模块

点击file按钮

Android主模块 安卓 模块_android

选择模块类型

Android主模块 安卓 模块_根目录_02

module类型又很多,用的最多的应该是第一个Phone应用和Library类型

第一个是应用类型,可以像app一样编译运行

第二个是库类型,本身可以编译,通过依赖关系也可以被其他模块引用

模块的类型实际上是在module内部的build.gradle中第一行的插件类型决定的

对应关系
应用类型:

apply plugin: 'com.android.application'

资源库类型:

apply plugin: 'com.android.library'

删除模块

不能直接删除module文件夹,会编译出错

自动删除

在工具栏按钮中找到Project Structure

Android主模块 安卓 模块_根目录_03

找到要删除的module,点击减号按钮.

然后在项目目录下,删除文件夹即可

手动删除

在项目根目录下,找到setting.gradle文件,可以看到结构如下

Android主模块 安卓 模块_根目录_04

这里手动删除指定的module,然后编译通过后,就可以直接手动删除指定module文件夹

模块间依赖关系

目前常用的有两种依赖方式,implement和api

implement 类似于关键字private,如例子

moduleA implement moduleB

moduleB implement moduleC

moduleA可以引用moduleB中的资源,无法引用moduleC中的资源

api类似于关键字public,如例子

moduleA api moduleB

moduleB api moduleC

moduleA可以引用moduleB moduleC中的资源
如果其他模块依赖了moduleA,可以引用到ABC三个模块的资源

统一模块管理

每个module中都有自己的build.gradle,都有自己的编译版本和编译工具

为了统一方便管理,可以在根目录下建立一个统一的gradle配置文件,然后导入到每个module中的build.gradle中

例如

根目录下config.gradle文件

ext {
    /*发布到生产的版本号*/
    versionReleaseName = "1.0.03"
    /*仅在内部测试时使用的版本号*/
    versionDebugName   = "1.0.03_debug"
    android =[
            compileSdkVersion   : 27,
            minSdkVersion        : 19,
            targetSdkVersion    : 21,
            versionCode         : 21,
            versionName         : versionReleaseName
    ]
    /*java版本,使用Java1.8*/
    compileJavaVersion = JavaVersion.VERSION_1_8
    /*签名文件,需要放到根目录下*/
    customSign=[
            keyAlias : 'androiddebugkey',
            keyPassword : 'android',
            file : '../debug.keystore',
            storePassword :'android',
    ]
    appId =[
            "app" :"com.custom.demo",
    ]
    /**
     * 高德库
     * 可以把所有的库版本放到这里来,方便统一管理
     */
    amap = [
            "location" :'com.amap.api:location:latest.integration'
    ]
}

然后在所有的module中使用配置文件

app/build.gradle

apply plugin: 'com.android.application'

def cfg = rootProject.ext.android
def appid = rootProject.ext.appId
def customSign= rootProject.ext.customSign
android {
    //定义签名newland
    signingConfigs {
        mySign {
            keyAlias customSign.keyAlias
            keyPassword customSign.keyPassword
            storeFile file(customSign.file)
            storePassword customSign.storePassword
        }
    }
    
    compileSdkVersion cfg.compileSdkVersion
    defaultConfig {
        applicationId appid['app']
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //使用签名newland
            signingConfig signingConfigs.mySign
        }
        debug {
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.mySign
        }
    }
    //aidl文件夹
    sourceSets {
        main {
            aidl.srcDirs = ['src/main/aidl', 'src/main/aidl/com/newland/payment/aidl']
        }
    }
    //渠道打包
    android.applicationVariants.all { variant ->
        //所有渠道,打包格式 Demo-V[版本名]([版本号)]-[打包时间]
        variant.outputs.all {
            String name = "Demo-V${defaultConfig.versionName}(${defaultConfig.versionCode})-${releaseTime()}"
            outputFileName = name + ".apk"
        }
    }
    // 使用Java1.8
    compileOptions {
        sourceCompatibility rootProject.ext.compileJavaVersion
        targetCompatibility rootProject.ext.compileJavaVersion
    }
    //指定module_XX的libs库路径
    repositories{
        flatDir{
            dirs 'libs','../module_XX/libs'
        }
    }
}


dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation rootProject.ext.amap['location']
}

def static releaseTime() {
    return new Date().format("yyyyMMddHHmm", TimeZone.getTimeZone("GMT+08:00"))
}
//获取工程名
def static projectTag() {
    String projectPath = System.getProperty("user.dir")
    String projectName = projectPath.substring(projectPath.lastIndexOf('\\') + 1)
    return projectName.substring(0, projectName.lastIndexOf('-'))
}

遇到的问题

生成了两个图标

检查工程所有的AndroidManifest文件,是否有其他活动添加了主页属性

<intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

显然程序会根据配置的主页属性,出现多个对应的图标

删除掉不需要的入口即可