Android Studio之配置编译

学习网址:

https://developer.android.com/studio/build

如下文字是经过学习官网知识点,结合自身的需求进行整理的文档。这里,如有疑问,强烈建议看官网文档、强烈建议看官网文档、强烈建议看官网文档。

提问:

1.怎么多渠道管理apk的发布

2.各种渠道的apk,相互之间源码和资源文件都有差异,但仍希望使用同一套代码进行管理。

例如:AndroidManifest.xml有差异、某一个功能有差异、可能apk包名、签名也有差异也有差异

重点记录:

Android应用模块的编译流程

apk生成流程.png

Android 应用模块的默认项目结构

apk项目结构.png

模块下面的build.gradle分析

问题一、因应用商城的不同,需要上传自定义的不同的apk版本:

android {
        ...
        defaultConfig {...}
        buildTypes {
            debug{...}
            release{...}
        }
        // Specifies one flavor dimension.
        flavorDimensions "version"
        productFlavors {
            huawei {
                // Assigns this product flavor to the "version" flavor dimension.
                // This property is optional if you are using only one dimension.
                dimension "version"
                applicationIdSuffix ".huawei"
                versionNameSuffix "-huawei"
            }
            oppo {
                dimension "version"
                applicationIdSuffix ".oppo"
                versionNameSuffix "-oppo"
            }
        }
    }

关键点:
1)flavorDimensions
2)productFlavors
因为每个商场的渠道不一样,导致可能需要更改不同的版本信息。此时,huawei渠道有两个版本:debug和
release,oppo也有两个版本debug和release。所以,这里的编译版本有[huawei, oppo]x[debug, release]
编译方式:
gradlew build  //4个编译出来
gradlew assemblehuaweiDebug //只编译华为的Debug版本
gradlew assemblehuaweiRealse //只编译华为的Release版本
注:huawei可以换成oppo

问题二、同一个apk,但是因不同的机器,需要的api版本不一样:

android {
      ...
      buildTypes {
        debug {...}
        release {...}
      }

      // Specifies the flavor dimensions you want to use. The order in which you
      // list each dimension determines its priority, from highest to lowest,
      // when Gradle merges variant sources and configurations. You must assign
      // each product flavor you configure to one of the flavor dimensions.
      flavorDimensions "api", "mode"

      productFlavors {
        huawei{
          // Assigns this product flavor to the "mode" flavor dimension.
          dimension "mode"
          ...
        }

        oppo{
          dimension "mode"
          ...
        }

        // Configurations in the "api" product flavors override those in "mode"
        // flavors and the defaultConfig block. Gradle determines the priority
        // between flavor dimensions based on the order in which they appear next
        // to the flavorDimensions property above--the first dimension has a higher
        // priority than the second, and so on.
        minApi24 {
          dimension "api"
          minSdkVersion 24
          // To ensure the target device receives the version of the app with
          // the highest compatible API level, assign version codes in increasing
          // value with API level. To learn more about assigning version codes to
          // support app updates and uploading to Google Play, read Multiple APK Support
          versionCode 30000 + android.defaultConfig.versionCode
          versionNameSuffix "-minApi24"
          ...
        }

        minApi23 {
          dimension "api"
          minSdkVersion 23
          versionCode 20000  + android.defaultConfig.versionCode
          versionNameSuffix "-minApi23"
          ...
        }

        minApi21 {
          dimension "api"
          minSdkVersion 21
          versionCode 10000  + android.defaultConfig.versionCode
          versionNameSuffix "-minApi21"
          ...
        }
      }
    }
    ...
    
    关键点:
    1)flavorDimensions "api", "mode"有两个值。谁在前面,谁的优先级高。也就是不能modeapi
    2)productFlavors 下的版本级别,跟dimension关联,如果都是api,说明,这两个是同一个级别
    也就是说,huawei和oppo都是mode,是一个级别;而minApi21、minApi23、minApi24是同一个级别。
    这里编译的版本组合有:
    这里的编译版本有[minApi21, minApi23, minApi24]x[huawei, oppo]x[debug, release],即12种
    
    编译方式:
    gradlew build //编译全部
    gradlew assembleminApi21 //编译出来的版本[minApi21]x[huawei, oppo]x[debug, release],4种
    gradlew assembleminApi21huawei //编译[minApi21]x[huawei]x[debug, release],2种

问题三、问题一的进一步展开,不同渠道的apk中的AndroidManifest.xml、java文件、资源文件都有点区别,应该怎么处理?

apk多渠道源集处理.png

只要huawei和oppo目录的名称跟productFlavors保持一致即可,android studio编译的是会自动编译此目录下的相关文件。如果不按照这种方式处理,就需要使用闭包:sourceSets。我们Android studio默认使用main/src的源码集合。这里,我们通过sourceSets自然也可以更改,例如:

android {
      ...
      sourceSets {
        // Encapsulates configurations for the main source set.
        main {
          // Changes the directory for Java sources. The default directory is
          // 'src/main/java'.
          java.srcDirs = ['other/java']

          // If you list multiple directories, Gradle uses all of them to collect
          // sources. Because Gradle gives these directories equal priority, if
          // you define the same resource in more than one directory, you get an
          // error when merging resources. The default directory is 'src/main/res'.
          res.srcDirs = ['other/res1', 'other/res2']

          // Note: You should avoid specifying a directory which is a parent to one
          // or more other directories you specify. For example, avoid the following:
          // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
          // You should specify either only the root 'other/res1' directory, or only the
          // nested 'other/res1/layouts' and 'other/res1/strings' directories.

          // For each source set, you can specify only one Android manifest.
          // By default, Android Studio creates a manifest for your main source
          // set in the src/main/ directory.
          manifest.srcFile 'other/AndroidManifest.xml'
          ...
        }

      }
    }

规则

1、资源文件的覆盖,图片、音频、 XML 类型的 Drawable 等资源文件,将会进行文件级的覆盖。

2、资源文件的合并,字符串、颜色值、整型等资源以及 AndroidManifest.xml ,将会进行元素级的覆盖(不同版本只要写与主版本不同的元素即可)。

3、代码资源的准备,代码文件不会覆盖或合并,同一个类文件, 在不同目录(buildTypes 、 productFlavors 、 main)中只能存在一次,否则会有类重复的错误。

特别说明AndroidManifest.xml

合并原理:

AndroidManifest合并原则.png

合并算法

关键的操作可以参考官网说明:

https://developer.android.com/studio/build/manifest-merge

问题四、build.gradle怎么与应用代码共享自定义字段和资源值

android {
      ...
      buildTypes {
        release {
          // These values are defined only for the release build, which
          // is typically used for full builds and continuous builds.
          buildConfigField("String", "BUILD_TIME", "\"${minutesSinceEpoch}\"")
          resValue("string", "build_time", "${minutesSinceEpoch}")
          ...
        }
        debug {
          // Use static values for incremental builds to ensure that
          // resource files and BuildConfig aren't rebuilt with each run.
          // If they were dynamic, they would prevent certain benefits of
          // Instant Run as well as Gradle UP-TO-DATE checks.
          buildConfigField("String", "BUILD_TIME", "\"0\"")
          resValue("string", "build_time", "0")
        }
      }
    }
    ...
    在构建时,Gradle 将生成 BuildConfig 类,以便您的应用代码可以检查与当前构建有关的信息。
    我们还可以使用 buildConfigField() 方法从 Gradle 构建配置文件将自定义字段添加到 BuildConfig 类,
    并在应用的运行时代码中访问这些值。同样,我们也可以使用 resValue() 添加应用资源值。
    重点说明,我们gradle自动创建的BuildConfig类,可以让我们很方便用debug属性判断是否开启Log。因为
    BuildConfig.DEBUG在Debug版本为true,在Release版本为false。例如:
    Log.i(TAG, BuildConfig.BUILD_TIME);
    Log.i(TAG, getString(R.string.build_time));

问题五、build.gradle怎么让AndroidManifest.xml和应用代码共享属性?

android {
      // For settings specific to a product flavor, configure these properties
      // for each flavor in the productFlavors block.
      defaultConfig {
        // Creates a property for the FileProvider authority.
        def filesAuthorityValue = applicationId + ".files"
        // Creates a placeholder property to use in the manifest.
        manifestPlaceholders =
          [filesAuthority: filesAuthorityValue]
          // Adds a new field for the authority to the BuildConfig class.
          buildConfigField("String",
                           "FILES_AUTHORITY",
                           "\"${filesAuthorityValue}\"")
      }
      ...
    }
    ...
    关键点:buildConfigField、manifestPlaceholders 配合使用
    
    AndroidManifest.xml如下:
        
      ...
      
        ...
        
          ...
        
      
    
    
    代码如下:
        ...
    Uri contentUri = FileProvider.getUriForFile(getContext(),
      BuildConfig.FILES_AUTHORITY,
      myFile);

问题六、不同的渠道的签名不一样,怎么此需求?

android {
    defaultConfig {
        ······
    }
    signingConfigs {
        huawei_sign {
            storeFile file("../key/xxx.keystore")
            storePassword "xxxxxx"
            keyAlias "xxx"
            keyPassword "xxxxxx"
        }

        oppo_sign {
            storeFile file("../key/xxx.keystore")
            storePassword "xxxxxxx"
            keyAlias "xxx"
            keyPassword "xxxxxxx"
        }
    }
    flavorDimensions "default"
    productFlavors {
        huawei {
            ···
            signingConfig  signingConfigs.huawei_sign
        }

        oppo {
            ···
            signingConfig = signingConfigs.oppo_sign
        }

    }

    buildTypes {
        release {
            ···
            signingConfig null
        }

        debug {
            ···
            signingConfig null
        }
    }
}
关联点三处:
1)productFlavors 把各自signingConfig值定义了
2)buildTypes把signingConfig置为null
3)signingConfigs进行统一申明

常用命令

gradle命令一般是./gradlew +参数, gradlew 代表gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties 文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

  • ./gradlew -v 版本号
  • ./gradlew clean 清除app目录下的build文件夹
  • ./gradlew build 检查依赖并编译打包

这里注意的是 ./gradlew build 命令把debug、release环境的包都打出来,如果正式发布只需要打Release的包,该怎么办呢,下面介绍一个很有用的命令 assemble, 如:

  • ./gradlew assembleDebug 编译并打Debug包
  • ./gradlew assembleRelease 编译并打Release的包

除此之外,assemble还可以和productFlavors结合使用:

  • ./gradlew installReleaseRelease模式打包并安装
  • ./gradlew uninstallRelease 卸载Release模式包

Android Studio其实用的就是gradle打包,所以,可以直接使用gradle指令进行打包,这样可以更加快捷。

参考学习

https://blog.csdn.net/u014314614/article/details/83868648

https://www.jianshu.com/p/d485db2970f9

https://developer.android.com/studio/build

https://blog.csdn.net/growing_tree/article/details/74938536

https://blog.csdn.net/m0_37168878/article/details/81530499

https://blog.csdn.net/s13383754499/article/details/80312514

https://www.cnblogs.com/ldq2016/p/7568906.html

https://yq.aliyun.com/articles/687780

你可能感兴趣的:(Android Studio之配置编译)