gradle 多渠道打包一

1. 验证APK的签名

验证APK的签名需要用到下面2个命令:
查看签名文件的属性

keytool -list -keystore 签名文件

F:\mygithub\test1>keytool -list -keystore test1.jks
输入密钥库口令:

密钥库类型: JKS
密钥库提供方: SUN

您的密钥库包含 1 个条目

key0, 2019-10-16, PrivateKeyEntry,
证书指纹 (SHA1): 35:45:24:74:42:D7:3C:81:3C:2F:40:3B:04:E4:4C:DF:65:53:80:3F

查看apk的签名,解压apk,获取 CERT.RSA(位于解压目录下 /META-INF 下)
以下命令行是在 apk 解压目录下执行

keytool -printcert -file META-INF/CERT.RSA

F:\mygithub\test1>keytool -printcert -file CERT.RSA
所有者: CN=test1
发布者: CN=test1
序列号: 42f9a6e7
有效期开始日期: Wed Oct 16 14:37:54 CST 2019, 截止日期: Sun Oct 09 14:37:54 CST 2044
证书指纹:
         MD5: CE:F4:41:DC:39:1F:8B:6E:4C:76:E8:99:BC:1A:EB:41
         SHA1: 35:45:24:74:42:D7:3C:81:3C:2F:40:3B:04:E4:4C:DF:65:53:80:3F
         SHA256: 4A:0B:84:23:C5:12:29:EB:FF:A8:0D:F6:D9:4B:96:D4:CE:80:65:0A:DC:9F:9F:7D:AF:9A:77:DB:23:B9:DD:64
         签名算法名称: SHA256withRSA
         版本: 3

扩展:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 9E 61 88 DE F6 C2 43 30   A4 DD 75 18 67 D7 E4 86  .a....C0..u.g...
0010: 4C 27 96 FE                                        L'..
]
]

注意问题

网上说debug配置签名无效,配置方式是这样的:

buildTypes {
   release {
       minifyEnabled true
       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       shrinkResources true

       //多个 flavor ,指定 flavor 使用指定 签名
       productFlavors.flavors_default.signingConfig signingConfigs.flavors_default
       productFlavors.flavors_dev.signingConfig signingConfigs.flavors_dev
   }
   
   //如果 debug 包需要测试诸如微信、地图等第三方 sdk ,则可以指定 debug 包使用 release 包的签名
   //debug 并不能设置多个签名
   //debug {
   //   productFlavors.flavors_default.signingConfig signingConfigs.flavors_default
   //   productFlavors.flavors_dev.signingConfig signingConfigs.flavors_dev
   //}
}

是在buildTypes里面配置的,文中指出配置失效的原因是:debug 签名只能指定一个或者使用默认的 debug 签名。
具体没有测试,在这里做一个记录,以备以后查阅。
这里使用另外一种方式是有效的,具体配置方式是不在buildTypes里面配置签名,在productFlavors里面配置,这样debug和release都使用的是自己的签名
 

buildTypes {
    ...
    debug {
        ...
        signingConfig null // 配置debug模式下的签名,在productFlavors里面配置
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
    }
}
    
productFlavors {
    c_vivo {
        dimension "company"
    }

    v_test1 {
        signingConfig signingConfigs.test1
        dimension "version"
    }
}

2. 修改applicationId

往往同一个applicationId的应用在同一台设备只能安装一个,不能同时安装多个,这是因为applicationId是同一个的原因。
我们可以用其 applicationId 属性来实现多个 Apk 安装在同一设备上。

    productFlavors {
        c_vivo {
            dimension "company"
        }

        v_test1 {
            signingConfig signingConfigs.test1
            applicationId "com.cold.test1"
            dimension "version"
        }

        v_test2 {
            signingConfig signingConfigs.test2
            applicationId "com.cold.test2"
            dimension "version"
        }
    }

可以使用aapt查看AndroidManifest.xml的信息
aapt dump xmltree ***.apk AndroidManifest.xml

F:\mygithub\test1>D:\sdk\build-tools\29.0.2\aapt.exe dump xmltree app-c_vivo-v_test2-debug.apk AndroidManifest.xml
N: android=http://schemas.android.com/apk/res/android
  E: manifest (line=2)
    A: android:versionCode(0x0101021b)=(type 0x10)0x1
    A: android:versionName(0x0101021c)="1.0" (Raw: "1.0")
    A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d
    A: android:compileSdkVersionCodename(0x01010573)="10" (Raw: "10")
    A: package="com.cold.test2" (Raw: "com.cold.test2") // 这个就是替换后的applicationId
    A: platformBuildVersionCode=(type 0x10)0x1d
    A: platformBuildVersionName=(type 0x10)0xa
    E: uses-sdk (line=7)
      A: android:minSdkVersion(0x0101020c)=(type 0x10)0xf
      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1d
    E: application (line=11)

3. 替换 AndroidManifest.xml 中的属性

可以通过设置占位符来实现动态替换属性值,占位符的使用方法是${},中括号里面的内容表示需要替换的内容。
当AndroidManifest.xml合并的时候,会把占位符的内容设置成build.gradle设置的值。
占位符使用manifestPlaceholders实现。

    productFlavors {
        c_vivo {
            dimension "company"
        }

        v_test1 {
            ...
            manifestPlaceholders = [NAME : "test1"]
        }

        v_test2 {
            ...
            manifestPlaceholders = [NAME : "test2"]
        }
    }

在AndroidManifest.xml 中使用定义的NAME:

        <meta-data
            android:name="name"
            android:value="${NAME}" />

可以通过在程序中验证设置是否正确:

    private String readMeta() {
        String metaStr = "";
        try {
            ApplicationInfo applicationInfo =
                    getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
            if (applicationInfo != null && applicationInfo.metaData != null) {
                metaStr = (String) applicationInfo.metaData.get("name"); // 这里为对应meta-data的name
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return metaStr;
    }

4. 使用不同的资源文件

不同渠道的资源可能会有点出入,例如显示图标,应用名称,启动页面等等。可以在main同级目录下创建以渠道名命名的文件夹,
然后创建资源文件,各文件名称和存放路径需要与main下的一致,否则替换不成功。使用gradle打包的时候会自动替换成渠道下
的资源。这种方法对于不同的源码文件也是有效的,例如在渠道目录下添加自己的源码文件,处理不同的业务逻辑。
gradle合并的资源来自3种来源:
1. 主资源,和main sourceSet相关联,大多位于src/main/res
2. 渠道特有资源Flavor(s).
3. Library项目依赖,通过它们的aar bundle提供资源。
优先级为:Flavor -> main -> Dependencies.

添加完对应的Flavor目录后,切换到不同Variant,对应Variant下的res木有有个黄色方块,表示该目录下的资源会参与编译并合并。

5. 自定义BuildConfig

使用buildConfigField定义BuildConfig

    buildConfigField "boolean", "LOG_DEBUG", "false" // 是否输出LOG信息

6. sourceSets配置不同的资源文件


java插件引入了一个概念叫做SourceSets,通过修改SourceSets中的属性,可以指定哪些源文件(或文件夹下的源文件)要被编译,哪些源文件要被排除

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }
}

例如:

    sourceSets {
        v_test1 {
            java.srcDirs += ['../flavors/v_test1/src'] // 指定源码目录
            res.srcDirs += ['../flavors/v_test1/res'] //资源目录
        }
        ...
    }

使用 "+=" 会把后面的路径添加到对应的目录集合中,而是用 "=" 会直接覆盖之前设置的路径。例如使用 "+" 设置的app/src/v_test1
这个路径就会失效。
上面配置的目录都属于Flavor这一层级,配置的相关资源不能和其他同为Flavor目录内的资源同名,否则会报Duplicate resources

发布了70 篇原创文章 · 获赞 16 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq282330332/article/details/103131975