Android Studio 一个工程打包多个不同包
转: https://blog.csdn.net/kdsde/article/details/88639194
AS主要是利用gradle来实现这个需求的,具体做法如下:

修改app的build.gradle文件

假设我们同一套代码编译2个app:app1和app2

android {

productFlavors {

// app1

app1 {

// 设置applicationId(这里很重要,两个相同applicationId的apk不同同时安装在同一台Android手机中)

applicationId “com.johan.demo”

// 自动生成@string/app_name为demo

resValue “string”,“app_name”,“demo”

// 定义app_icon字段,在AndroidManifest.xml文件中用到

manifestPlaceholders = [app_icon : “@mipmap/ic_launcher”]

}

// app2

app2 {

// 解释同app1

applicationId “com.johan.demo1”

resValue “string”,“app_name”,“demo1”

manifestPlaceholders = [app_icon : “@mipmap/ic_launcher1”]

}

}

lintOptions {

checkReleaseBuilds false

abortOnError false

}

}

注意啦,这里有个坑,我们上面写了

?

1

resValue “string”,“app_name”,“demo”

运行之后,AS会自动生成@string/app_name,内容是这样的

?

1

demo

那么问题来了,如果你在app的strings.xml文件也定义了

?

1

demo

编译的时候就会出现问题,因为有2个app_name,所以我们要把app的strings.xml去掉,编译就会正常了。

再注意啦,我们 只能在app的build.gradle文件配置各个版本的值 ,如

?

1

2

3

4

5

6

app1 {

buildConfigField “int”, “TYPE”, “1”

}

app2 {

buildConfigField “int”, “TYPE”, “2”

}

如果你在其他子模块配置的话,编译时出现乱七八糟的错误!!

如果子模块需要配置的值,可以在公共模块定义静态变量,在app模块取出配置值后,设置到公共模块定义的静态变量中,这样的话各个模块都可以取到!!

修改AndroidManifest.xml文件

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<manifest xmlns:android=“http://schemas.android.com/apk/res/android”

package=“com.johan.demo”>

<application

android:allowBackup=“true”

// 注意啦,这里改为${app_icon}

android:icon="${app_icon}"

android:label="@string/app_name"

android:supportsRtl=“true”

android:theme="@style/AppTheme">

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

注意啦,icon属性的值是${app_icon},虽然为红色,但是不要紧,我们在build.gradle文件中加入了这么一段代码:

?

1

2

3

4

5

6

7

android {

lintOptions {

checkReleaseBuilds false

abortOnError false

}

}

这里的作用就是即使项目中报错也不会停止打包 。

打包并签名APK

我们打包时,就会出现2个app:

我们选择2个app,AS就会帮我们打包2个不同的APK了,就这么简单!!

填坑

今天按照以上步骤在开发项目尝试了一下,虽然可以打包不同版本的apk,但是不能同时安装到同一台设备,提示:xx有相同组件之类的。然后查看两个apk的包名是否一样,结果两个apk的包名是不同的。就这个问题查了一整天,果然皇天不负有心人,被我找到了,原因是我在AndroidManifest文件定义了一个provider:

记住,provider标签的authorities属性的值一定要是唯一的,如果两个app的authorities属性值一样,就会提示安装失败,一定要记住!!

查看包名的方法:

因为我们此时的apk不能安装的手机上,所以只有apk这个包,这时,我们使用aapt命令(aapt是sdk自带的一个工具,在sdk\builds-tools\目录下):

?

1

aapt dump badging D:\apk\xxx.apk | findstr package

由于已经集成在gradle中,所以能直接在gradle中使用,在app的build.gradle中创建productFlavors结构

android{
#…
productFlavors{
productA{
#这里定义产品A的特性
}

    productB{#这里定义产品B的特性}#更多产品 ...
}

进行编译,在Build Variants版块里面我们能看到生成出来的不同Build Variant

这里切换不同的product能够切换到不同的产品上面去。

那么怎么样才能在不同产品上体现出差异化呢??
肯定是在对应的product括号下添加对应的属性,我们看下写法…
productA{
buildConfigField ‘String’, ‘HOST’, ‘”http://192.168.0.208:7001/“’
}

productB{
buildConfigField ‘String’, ‘HOST’, ‘”http://192.168.0.30:7001/“’
}

首先我们添加一个名为HOST的字符串对象,实现编译, 然后我们在app的build/generated/buildConfig/productA(由于当前选的是productA项目)/包名/下有个BuildConfig.java的文件,打开看下

首先我们可以看到这个文件是自动生成的且无法修改的,可以看到文件里面有DEBUG,AOOLICATION_ID这些参数,这些都是默认有的,我们看重点

这不就是我们在productA里面声明的HOST参数吗,系统帮我们声明了一个名为HOST的String对象,那么在Activity里面怎么使用它呢,很简单,只要BuildConfig.HOST就可以拿到HOST对象了。

由于我们现在是在productA项目下,我们在Build Variants里面将现场切换成ProductB试一下。然后我们在刚才Activity声明的HOST变量 点进去看一下,发现跳到了ProductB的BuildConfig.java文件来了

很显然,HOST的对象已经变了,变成了productB的对象值。

此外,除了String对象,我们还可以定义其他不同的对象,比如boolean,Class对象等等,

buildConfigField ‘boolean’, ‘displayFamilyName’, ‘true’ //列表Item前面是显示姓还是名
buildConfigField ‘Class’, ‘scheduleAddr’, ‘cn.com.minstone.httplogic.schedule.addr.PASys.class’

都是能够生成出来的。

替换manifest字段
在mainfest里按照一定格式自定义个可变的字段,在gradle里根据不同版本赋予不同的值.
注意:自定义mainfest字段的格式为:
YOURNAME;例如{ YOURNAME };例如YOURNAME;例如{APP_NAME}
具体写法是

productA{
manifestPlaceholders = [“APP_KEY”: “123456789”,]
}

在manifest文件里面可以这么引用

<meta-data
android:name = “APP_KEY”
android:value = “${APP_KEY}”

定义res对象
我们还可以定义资源对象,具体用法
productA{
resValue “string”, “appName”, ‘“柳州数字质监移动办公”’
}

然后在strings.xml文件里面使用

@string/appName`

此外,我们还可以定义像versionCode,versionName这样的字段,这里我就不一一类出来了。

假如所有现场都有一个统一的变量,这时候我总不能每个product里面都申明一模一样的变量吧??放心,这个问题productFlavors也帮我们考虑了,我们可以定义一个叫跟productX同级的defaultConfig的标签,标签里面可以放所有现场共用的属性和变量,具体操作是

android{
defaultConfig{
//存放公共变量
buildConfigField ‘String’, ‘COMMON’, ‘“admin”’
}
productA{

}
productB{

}
}

这样的话在productA和productB项目里都可以用到COMMON变量,假如productA的COMMON变量跟其他现场不一样怎么办?可以在productA标签下重写该变量进行差异化区分。

productA{
buildConfigField ‘String’, ‘COMMON’, ‘“aaaa”’
}

通过productFlavors,我们可以很方便地对每个现场的变量进行控制,只需要鼠标点击只能切换到对应的项目,并且变量的值也能够对应切换,这样我们就能够去掉恶心的if else语句,可维护性更高。

最后,我说下我根据自己项目特点使用productFlavors的一些小技巧。
首先,随着项目的增大,你会发现每个标签下的变量越来越多,这样的话会导致app的build.gradle文件的行数会越来越多,影响可阅读性。所以,我将不同现场的标签抽取出来,分成个个文件,然后在app的build.gradle引用这些文件

这样的话显得更加的直观 结构更加清晰,并且减少了build.gradle的代码量

2.假如我一个现场的主页面要导航页的5个功能,另外一个现场只要其中的4个功能,导致功能性的差异,这时候使用productFlavors怎么做?
这里我提供一种解决思路,也是使用String变量来存,但是存放的值是Json字符串

        buildConfigField 'String', 'workBenchMenu', '"[{\\"title\\": \\"所有公文\\",\\"icon\\": \\"workbench_review\\"},{\\"title\\": \\"消息\\",\\"icon\\": \\"workben_message\\"},{\\"title\\": \\"任务\\",\\"icon\\": \\"workben_task\\" },{\\"title\\": \\"联系人\\",\\"icon\\": \\"workben_contact\\"},{\\"title\\": \\"单位动态\\",\\"icon\\": \\"workbench_dynamic\\"},{\\"title\\": \\"行程\\",\\"icon\\": \\"workben_schedule\\"},{\\"title\\": \\"公文分类\\",\\"icon\\": \\"workbench_documentrank\\"}]"'

然后Activity里面通过解析该json去生成布局,实现功能性差异。

1.创建productFlavors

在APP的gradle中添加:

android {

//创建productFlavors
productFlavors {
ceshi{//配置测试版包名和应用名
applicationId “ceshi.yb.com.wanandroid”
manifestPlaceholders = [APP_NAME: “@string/app_name_ceshi”]
}
shengchan{//配置生产版包名和应用名
applicationId “shengchan.yb.com.wanandroid”
manifestPlaceholders = [APP_NAME: “@string/app_name_shengchan”]
}
}
}

此时应该报以下错误:
Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
在defaultConfig 中加上:

defaultConfig {

flavorDimensions “versionCode”
}
再重新编译下就OK了.

2.创建统一文件夹

切换到Project模式的目录:

在src目录下新建ceshi(/shengchan)包:

再新建以下包和文件:

资源文件同:

调试时点击 Build Variant 选择自己需要的版本即可正常引用

3.配置不同的应用名或其他属性

首先strings.xml中添加:

<string name="app_name_ceshi">测试版WanAndroid</string>
<string name="app_name_shengchan">生产版WanAndroid</string>

然后manifest中改下lable:

<application
android:name=".base.BaseApp"
android:allowBackup=“true”
android:icon="@mipmap/ic_launcher"
android:label="${APP_NAME}"//引用gradle中定义的变量
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl=“true”
android:theme="@style/AppTheme">

通过配置Flavors和自定义buildConfigField进行多个服务器地址打包

productFlavors{ } 是配置多渠道打包的.1).productFlavors{ } 与 buildTypes{ }里面的配置是多对多的关系。2).productFlavors{ } 其实是defaultConfig{ }的子集defaultConfig {}中的属性在productFlavors{}中都可以单独设置,若重复会以productFlavors{}中的属性为最终属性.a.可以对单独的productFlavors{ } 设置applicationId进而达到多个相同应用安装到同一台设备(现applicationId为唯一标识,区别于packageName)b.对单独的productFlavors{ }进行一些单独的配置或者操作

其中需要关注的是三部分:
defaultConfig {},buildTypes {},productFlavors {}
这三部分均可以对applicationId,图标及appname进行设置,但是优先级不同。优先级如下:

buildTypes > productFlavors > defaultConfig
设置AndroidManifest.xml中的属性可以通过manifestPlaceholders 进行设置,不同场景下的常量可以通过buildConfigField进行设置,资源的引用通过resValue 进行设置

  eg:单独对company的flavors进行了applicationId、minSdk、和JUnit测试限制操作,这样打出的包只会对company的有影响,其他的flavors无影响defaultConfig的相关设置属性可直接在ProjectStructure中查看并设置

buildConfigField是用于解决Beta版本服务和Release版本服务地址不同
或者一些Log打印需求控制的.
形式:buildConfigField “boolean”, “LOG_DEBUG”, “true”
三个字段分别表示为: 自定义字段类型 自定义字段名 自定义字段值
将buildConfigField写入到Flavors中在打包编译时就会单独的编入进去(PS.请注意单双引号的使用,对于链接需要额外的单引号buildConfigField的放置位置很灵活,如果Flavors的buildConfigField是一样的话,直接放入到debug{}和release{}中即可.)
eg:查看时请注意路径,另外如果创建了多个Flavors时同步后可能只出现了第一个Flavors的文件夹.手动针对其他Flavors编译即可.

设置buildConfigField的IS_PUBLIC无用
一个app,两个module,一个是application module,另外一个是library module;
在library中设置buildConfigField,如下

release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
buildConfigField(“boolean”, “IS_PUBLIC”, “true”)
}

debug{
buildConfigField(“boolean”, “IS_PUBLIC”, “false”)
}
用来控制http及debug在测试环境,和正式环境的不同;
然而,无论如何都只能得到IS_PUBLIC为false;

最后子stackoverflow上得到了解决
http://stackoverflow.com/questions/20176284/buildconfig-debug-always-false-when-building-library-projects-with-gradle

解决方法如下
With Android Studio 1.1 and having also the gradle version at 1.1 it is possible:

Library

android {
publishNonDefault true
}
App

dependencies {
releaseCompile project(path: ‘:library’, configuration: ‘release’)
debugCompile project(path: ‘:library’, configuration: ‘debug’)
}

致谢:

https://www.jianshu.com/p/533240d222d3

https://blog.csdn.net/u010818425/article/details/52335844

https://blog.csdn.net/reancool/article/details/50673762

https://blog.csdn.net/xx326664162/article/details/49247815

https://blog.csdn.net/u010818425/article/details/52319382

https://developer.android.com/studio/publish/app-signing
————————————————
版权声明:本文为CSDN博主「快乐的飞鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kdsde/article/details/88639194

Android Studio 一个工程打包多个不同包相关推荐

  1. Android studio 多渠道版本打包方法 flavor dimension

    Android studio 多渠道版本打包方法 flavor dimension 前言 开始 新建项目 修改build.gradle 创建差异化文件 创建图标 修改APP配色 修改APP名字 APP ...

  2. android项目打包apk,Android Studio将程序打包成APK的步骤详解

    第一步:先点击Build选择GenerateSigned APK 第二步:如果之前有编译成APK的话,就直接选择Choose existing已经存在的key:如果没有编译成APK那就选择Create ...

  3. Uniapp中使用高德地图,并在android studio中离线打包

    Uniapp中使用高德地图,并在android studio中离线打包 带高德地图功能的Uniapp的android离线打包 1. Uniapp中使用高德地图的方式 2. 高德地图中申请key 3. ...

  4. android studio一个好看的字体设置

    android studio一个好看的字体设置 用了很多字体,觉得这个字体,大小和款式都很好看 如下 as 版本 Android Studio Electric Eel | 2022.1.1 RC 1 ...

  5. Android导入一个工程时提示 Invalid project description的解决方法

    今天在网上下了个源码,导入的时候发现出现Invalid project description的提示,翻译成中文就是"无效的项目描述"的意思,搞不明白遂百度找到了解决办法,现记录并 ...

  6. Android Studio 单工程、多工程级联依赖下的aar的引用

    Android Studio 多工程级联依赖下的aar的引用 背景: application A 依赖 library B library B 依赖 library C library C 引用aar ...

  7. Android Studio删除工程、项目的操作步骤

    Android Studio删除工程.项目的操作步骤. 移除工程 主要用于从最近打开的项目列表中移除.硬盘中还是存在这个项目的. File--Close Project 注意:不要点击项目.(点击项目 ...

  8. android studio gradle 添加jar,android studio学习----通过gradle来导入jar包

    转载地址:http://www.th7.cn/Program/Android/201507/495477.shtml File->Project Structure 可以打开下面的图: 1.通过 ...

  9. android 删除一个工程,Android Studio该怎样删除项目?

    Android Studio该怎样删除项目?当你想在Android Studio中删除某个module时,大家习惯性的做法都是选中要删除的module,右键去找delete.但是在android St ...

最新文章

  1. 算法与数据结构重点归纳
  2. 绿色版Tomcat 启动 + 停止 + 随系统自动启动 - - 博客频道 - CSDN.NET
  3. 矩阵分析相关证明(一) —— 正交与投影
  4. Mysql 自动增长 重置
  5. 一篇文章让你彻底了解Java内部类
  6. 日常笔记-snownlp情感分析计算情感得分
  7. 六爻预测,前沿科学?伪科学?
  8. rtthread学习之(2)——STM32 系列外设驱动添加指南
  9. 人工智能导论(3)——确定性推理(Certainty Reasoning)
  10. 六州歌头 本周(1216-1220)部分GAN论文
  11. 七公江湖烤翅防骗子—常见网络骗子骗术防御要点
  12. IDEA 添加插件后启动闪退问题
  13. mysql数据迁移不停机_数据迁移还需要停机?不停机上线的正确姿势你能get到吗?...
  14. 华为手机怎么使用读卡器_手机nfc功能怎么打开(华为手机nfc功能使用步骤)
  15. im4java+GraphicsMagick 的问题
  16. 时间观——《天行九歌》第51集《一叶知秋》台词与典故
  17. eof() 和fail()
  18. float与double的MAX-MIN
  19. 数字营销公司HubSpot成功的9个经验
  20. video 标签 禁止下载 亲测有效 隐藏按钮 三个点 亲测有效

热门文章

  1. 什么是跨站脚本 (XSS)?
  2. ClearType消除锯齿的原理-上
  3. 电商微营销茶会第1期 | “客转粉”之评价有礼玩法解析
  4. 路易威登春夏23男装秀
  5. 电力动力柜能源采集物联网在线监控系统
  6. 上帝与集合的正确用法
  7. 律师事务所寄件管理教程
  8. ffmpge视频尺寸裁剪
  9. windows运行atxserver2-android-provider报错
  10. DB2第一步 — 创建表