android多渠道包(风味包)——安卓gradle

目录
1、前言
2、咱们须要解决的问题
一、所要达到的效果
二、须要解决的问题
3、编码时刻
4、效果演示
5、写在最后
php

1、前言

通过前几篇 安卓gradle 文章的介绍,童鞋们应该对 安卓gradle 更加熟悉了。java

一、defaultConfig——安卓gradleandroid

二、buildTypes——安卓gradlegit

三、flavorDimensions和productFlavors——安卓gradlegithub

这几篇文章中,咱们或多或少的提到 “渠道包” 和 “风味包” ,今天咱们就来分享下,如何机遇一套代码,编译出多个 “能够并存” 且 “存在有些许差别” 的apk包。微信

完整代码:github传送,若是对你有帮助,给个star吧。app

2、咱们须要解决的问题

咱们先理清楚作这件事情所要达到的效果 和 中间存在的问题ide

一、所要达到的效果

  • 一套核心代码编译出多个 “能够并存” 的apk包
  • 能够有差别化,eg:logo、app名字、签名、统计渠道 等能够根据不一样的apk有些许不一样
  • 易维护,耦合度低

二、须要解决的问题

根据咱们须要想要达到的效果,咱们须要解决如下几个问题post

  • 可以配置多个 applicationId
  • 可以动态的设置 AndroidManifest.xml 中的数据
  • 可以使用不一样的资源,但又不污染核心代码
  • 可以实现差别化逻辑

接下来咱们就来解决这些问题,达到咱们预期的效果gradle

3、编码时刻

一、创建 维度 和 风味

对 维度 和 风味 陌生的童鞋,能够移步查看小盆友的另外一片博文:flavorDimensions和productFlavors——安卓gradle

咱们进入应用级的 build.gradle 中,增长如下代码

android {
    // 省略其余代码...

    // 建立风味维度
    flavorDimensions('abi')
    productFlavors {
       	x86 {
            // 建立维度
            dimension 'abi'
        }

        armV7 {
            dimension 'abi'
        }
    }
}
复制代码

至此,咱们能够编译出两个apk包:“x86” 和 “armV7”。从编译器的提示,咱们也能够看出已经有 四种变体

由于 “x86” 和 “armV7” 两个风味各自都默认有 “release” 和 “debug” 两种编译类型,因此 2x2 则有 四种变体。

二、让两种风味并存

咱们须要给他们各自定一个 applicationId ,这样才能够并存不冲突。

android {
    // 省略其余代码...

    // 建立风味维度
    flavorDimensions('abi')
    productFlavors {
       	x86 {
            // 建立维度
            dimension 'abi'

            // 配置 风味的applicationId
            applicationId 'com.zinc.bear'
        }

        armV7 {
            dimension 'abi'
            
            applicationId 'com.zinc.shark'
        }
    }
}
复制代码

这样第一个问题解决了!!😊很简单吧,继续前行。 但此时运行起来,是两个彻底相同的apk,还没进行差别化的配置。

三、动态的设置 AndroidManifest.xml 中的数据

经过使用 manifestPlaceholders 达到这一效果

首先仍是在 build.gradle 中添加如下代码

productFlavors {
    x86 {
       dimension 'abi'
    
       applicationId 'com.zinc.bear'
    
       manifestPlaceholders = [
    		hostName: "www.x86.com",
    		logo    : "@drawable/logo",
    		appName : "bear",
       ]
    }
    
    armV7 {
        dimension 'abi'
    
        applicationId 'com.zinc.shark'
    
        manifestPlaceholders = [
    		hostName: "www.armv7.com",
    		logo    : "@drawable/logo",
    		appName : "shark",
        ]
    }
}
复制代码

接着咱们进入 AndroidManifest.xml 中,进行替换 logo 和 app名字,还有设置了一个 meta-data 的参数。

咱们在 AndroidManifest.xml 中使用 manifestPlaceholders 的参数规则为 ${参数名字},具体完整代码以下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zinc.flavordemo">

    <application android:allowBackup="true" android:icon="${logo}" android:label="${appName}" android:supportsRtl="true" android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <meta-data android:name="host" android:value="${hostName}"/>
    </application>

</manifest>
复制代码

咱们选择 “Merged Manifest”(此时为 armV7Debug 变体),能够看到 Android Studio 已经将咱们设置的参数替换为真实的参数。

至此, 咱们解决了第二个问题 “可以动态的设置 AndroidManifest.xml 中的数据”。

三、使用不一样的资源

不一样的apk,固然会出现 同个地方,使用一样的资源名,但又要表现不一样(emmm,很绕😂),咱们举个例子,细心的童鞋会发现咱们 logo 的资源名是同样的,咱们接下来看看如何配置。

这里的 配置有两种方法 ,小盆友就自做主张的起两个名字: “文件夹配置”“Library 配置”。咱们接下来一一展现。

3.1 文件夹配置

(1)咱们在跟 main 同级 的地方创建和 风味同样名字 的文件夹,这里使用 "armV7" 做为例子,则命名为 armV7。而后按照和 main 文件夹一样的格式创建结构,具体以下图。

(2)最后将咱们的 logo.png 图片放入 drawable 中便可。 在编译包时,会将armV7 文件夹中的资源覆盖在 main 中同名的资源。

(3)这种方式也一样适用于其余资源。例如:此处咱们也一样创建了 strings.xml 文件,其中也写入 app_name 的 string资源,最终编译 armv7 时,造成的 app_name 则会为 flavor_armv7。

armV7 下的 strings.xml 资源

main 下的 strings.xml 资源

3.2 Library 配置

(1)建立一个library,名称没有规定,这里取名为 “flavor_x86”。

(2)在 drawable 一样放入 logo.png 的图片,结构以下。
(3)最后在咱们项目级的 build.gradle 中加入以下代码,将其引入。注意此处不是使用 implementation, 而是使用 [风味名称]+Implementation,这样引入的 library 只会做用于该风味,例如此处只会做用于 x86 风味。

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

	// ...其余引入
	
	// 为风味 x86 引入 library flavor_x86
    x86Implementation project(':flavor_x86')
}
复制代码

(4)其余资源也一样适用,和 “文件夹配置” 的第三小点是同样的,就不赘述了。

3.3 两种方法的比较

小盆友我的比较喜欢 “Library 配置” 的方法,在真实的项目中也是使用这方案。

主要考虑到以下两点:

  • 真正的解耦,由于 “文件夹配置” 这一方案在小盆友看来,其实和 “main”文件夹(核心代码)仍是有共用一些资源,例如 build.gradle。
  • 易去除,“Library 配置” 方案在移除或更换依赖的 Library 时,很是简单,只须要更改 [风味名]Implementation 所引入的 Library。

四、可以实现差别化逻辑

聪明的童鞋其实已经发现,咱们在第三小点中,有存在一个 “java” 的文件夹,咱们只须要保持每一个风味都存在相同的类便可(类路径要彻底同样,这样切换不一样的风味包都不须要任何更换逻辑)。

4.1 代码时刻

咱们须要在不一样的风味包中调用以下代码,但又要避免污染核心代码。

// armv7 风味包
public class LogicUtils {
    public static String calculate(int a, int b) {
        return "armv7:" + (a + b);
    }
}

// x86 风味包
public class LogicUtils {
    public static String calculate(int a, int b) {
        return "x86:" + (a + b);
    }
}

复制代码

使用方法

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tvContent = findViewById(R.id.tv_content);
        tvContent.setText("LogicUtils:" + LogicUtils.calculate(1, 2));
    }
}

复制代码

项目结构

至此,咱们第四个问题就解决了。

4、效果演示

完整代码:github传送,若是对你有帮助,给个star吧。

4.1 运行效果

4.2 并存效果

4.3 两个应用

5、写在最后

若是喜欢的话请给我一个赞,并关注我吧。文章中若有写的不妥的地方,请评论区或加我微信与我讨论吧,共同进步。

欢迎加我微信,进行更多的交流

若是以为文章有很大的帮助,快来赞扬一次吧😄
相关文章
相关标签/搜索