一、需求背景

在测试阶段,有时需要在同一个设备上同时安装debug、beta、release等不同编译类型的包,或者同时安装当前版本与某个历史版本的包,以方便比较查看;但是,在同一个设备上,一个包名只能安装一个应用,本文将围绕该问题介绍完整的解决方案。


二、实践

1. 基本概念

在上一篇文章《 Gradle实际应用(一):批量打包》中我们已经介绍过packageapplicationIdPlaceHolder的概念,本文主要通过这三个参数来实现多包共存。

2. 修改应用名称

  • AndroidManifest文件中的label采用PlaceHolder的形式,使其可以在build.gradle文件中动态赋值,因此实现不同的编译类型有不同的应用名称

    <application
    android:name="com.company.appname.myApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="${app_label}" //将label值设置为变量
    android:theme="@style/Theme.AppCompat.NoActionBar"
    tools:replace="android:icon,android:theme,android:label">
  • 增加string值

    <string name="app_name">Test</string>
    <string name="app_name_beta">Test-beta</string>
    <string name="app_name_debug">Test-debug</string>
  • 同理,我们也可实现对icon的修改。

3. build.gradle文件中配置:

  • debug为例

    //设置全局变量,作为开关
    def isCoexist = false; //需要多包共存时设为true /**
    * 如果采用jekins打包时,执行命令:./gradlew assembleDebug -DmultiApp='true'
    * 如果采用AS打包时,修改变量:isCoexist = true
    */
    String appId = defaultConfig.applicationId // 读取原始的applicationId
    String multiApp = System.properties['multiApp'] // 读取打包命令中设置的系统参数
    if (isCoexist) {
    multiApp = "true"
    }
    debug() {
    if ("${multiApp}" != "${null}") { //采用该方式是因为某些机器上equals方法失效,暂无解
    appId = defaultConfig.applicationId + ".debug" //拼上后缀
    applicationIdSuffix ".debug" //拼上后缀(gradle自带方法)
    }
    manifestPlaceholders = [app_label: "@string/app_name_debug"] // AndroidManifest文件中的label就会被赋值
    println "applicationId: " + appId + " (debug)"
    }

4. Failure [INSTALL_FAILED_CONFLICTING_PROVIDER] 问题解决

如果应用中未使用ContentProvider,则上述配置即可;如果使用了ContentProvider,比如集成了个推推送,其中有一个DownloadProvider,因此安装时会报错,解决参考,解决如下:

// 在AndroidManifest文件中,修改authorities,如:
<provider
android:name="com.igexin.download.DownloadProvider"
android:authorities="downloads.com.company.appname.contentprovider"
android:process=":pushservice"/> 改为: <provider
android:name="com.igexin.download.DownloadProvider"
android:authorities="downloads.${DownloadProvider}.contentprovider"
android:process=":pushservice"/> 相应地,在build.gradle文件中添加DownloadProvider的赋值: manifestPlaceholders = [app_label: "@string/app_name_debug", DownloadProvider: appId]

5. 第三方应用appkey验证失败问题解决

以百度地图为例,百度地图需要开发者在其开放平台以包名和签名为应用注册一个appkey,生成的appkey填写在AndroidManifest文件中,如下:

<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="your_baidu_appkey"/>

此时,我们如果安装debug包,则包名变成了com.company.appname.debug,那么,appkey就无法验证通过了,百度地图也将无法展示。试想,我们能否修改百度地图验证时上传的包名呢?然而,经过一番努力,查看了百度地图sdk包,我们无法实现这一点。那么,只能为测试包申请一个appkey了,然后再通过PlaceHolder动态地设值。相应的修改如下:

<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="${BaiduMap_API_KEY}"/>

build.gradle文件中,以debug为例,修改如下:

manifestPlaceholders = [app_label: "@string/app_name_debug", DownloadProvider: appId,
BaiduMap_API_KEY: your_baidu_appkey_debug]

深入学习

Gradle实战:不同编译类型的包同设备共存的更多相关文章

  1. Gradle实战:发布aar包到maven仓库

    查看原文:http://blog.csdn.net/u010818425/article/details/52441711 Gradle实战系列文章: <Gradle基本知识点与常用配置> ...

  2. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  3. Gradle 使用本地的Jar包(gradle oracle ojdbc14 )

    Gradle 使用本地的Jar包(gradle oracle ojdbc14 ) 因为Oracle的驱动包在Maven上是没办法直接下载到的,所以在使用Gradle的使用,会导致无法加载Oracle, ...

  4. (android 地图实战开发)2 创建MapActivity,根据设备当前位置,显示地图

    (android 地图实战开发)2 创建MapActivity,根据设备当前位置,显示地图 http://www.cnblogs.com/macroxu-1982/archive/2011/09/13 ...

  5. gradle导出依赖的jar包

    gradle导出依赖的jar包 http://blog.csdn.net/yuhentian/article/details/50426896

  6. Gradle | Gradle项目无法导入依赖包

    Gradle | Gradle项目无法导入依赖包 背景 今天使用idea导入一个Gradle项目,使用 gradle build构建成功,但是项目还是无法正常导入依赖包,显示错误如下: 解决方案 后来 ...

  7. Http实战之Wireshark抓包分析

    Http实战之Wireshark抓包分析 Http相关的文章网上一搜一大把,所以笔者这一系列的文章不会只陈述一些概念,更多的是通过实战(抓包+代码实现)的方式来跟大家讨论Http协议中的各种细节,帮助 ...

  8. 如何解决使用Gradle时出现的jar包冲突

    前言 在我之前使用Gradle的博文中已经提到,Gradle对依赖的管理是比较智能的,如果有两个包依赖于相同的包,而版本不同的时候,Gradle会进行自动的选择,从而避免jar包的冲突. 也就是说,在 ...

  9. Android 逆向实战篇(加密数据包破解)

    1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...

随机推荐

  1. Session和Cookie的分析与区别

    首先说一下Web.config文件中的cookieless="false"的理解 cookieless="false"表示: 如果用户浏览器支持cookie时启 ...

  2. ACM之递推递归

    Hdu 2569 突破蝙蝠的包围,yifenfei来到一处悬崖面前,悬崖彼岸就是前进的方向,好在现在的yifenfei已经学过御剑术,可御剑轻松飞过悬崖. 现在的问题是:悬崖中间飞着很多红,黄,蓝三种 ...

  3. CodeForces 711B Chris and Magic Square (暴力,水题)

    题意:给定n*n个矩阵,其中只有一个格子是0,让你填上一个数,使得所有的行列的对角线的和都相等. 析:首先n为1,就随便填,然后就是除了0这一行或者这一列,那么一定有其他的行列是完整的,所以,先把其他 ...

  4. Javascript(JS)对Cookie的读取、删除、写入操作帮助方法

    var CookieUtils = { get: function (name) { var cookieName = encodeURIComponent(name) + '=', cookieSt ...

  5. 如何自学Java 经典

    JAVA自学之路 JAVA自学之路 一:学会选择 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等. 那么究竟 ...

  6. 【WebForm】Js调用后台C#方法

    因业务的需要,有这么个需求,需要前台的JS传参调用C#后台的方法.现在有这么个方法可以解决,整理如下. 首先,先说一下基本实现,前台用Jquery的ajax将其中的URL后加方法,然后在Data中传递 ...

  7. C++ 初始化与赋值

    1.初始化与赋值的区别: 二者的区别不是看,是否有=这个赋值操作符,而是看操作的时候,对象是否已经有值. 初始化:创建对象,并给它设置初始值. 赋值:对象已经有值,擦除对象的当前值,并使用新值代替. ...

  8. Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径

    C. Civilization Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/probl ...

  9. Oracle数据库备份与恢复的常用方法

    Oracle数据库有三种常用的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入备份是一种逻辑备份,相对于导出/导入来说,热备份.冷备份是一种物理备份. 导出/导入(Export ...

  10. asmack

    https://github.com/zhuqizhi/tlbs1409 https://github.com/maxting/IM_Project150126 https://github.com/ ...