原文简书地址:http://www.jianshu.com/p/dca9c323c686

1 前言

平时如果想要替换包名一般是在AS中右键Rename进行操作。但是如果遇到一份代码希望导出几种不同的包名(不是ApplicationId),并且代码还会持续更新,这时候就需要使用脚本在打包时自动导出成不同包名的apk。

有的人会说直接可以在build.gradle里面的productFlavors里面设置,然后用placeHolder填充包名就行啦。 注意,这时候就要区分ApplicationId和PackageName了。

ApplicationId,是在手机中标识唯一应用的id。(看起来就是包名)

defaultConfig {
applicationId "com.tsy.xxx"
minSdkVersion
targetSdkVersion
versionCode
versionName "1.0" multiDexEnabled true // Enabling multidex support.
}

PackageName,AndroidManifest里面标明的package和每个java文件里面的package头的包名。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tsy.xxx">
package com.tsy.xxx.xxx;

import xxx

public class MainActivity {
...
}

平时使用productFlavors+PlaceHolder导出不同包只能导出ApplicationId不同的包,的确可以导出2个同时在手机安装的包,但是其实package并没有改变。当遇到以下情况时就会出现问题。

  1. 微信第三方接入时回调要求在包名路径下的.wxapi.WXCallBackxxx 固定写死这个文件才能回调。就是说如果你修改了ApplicationId没有修改PackageName是无法收到微信回调的。
  2. 动态获取资源的时候。经常会动态根据包名和资源名获取资源,这时候由于PackageName没有修改,也是会出错。

2 怎么修改PackageName

当我们了解了ApplicationId和PackageName的区别后,该怎么修改PackageName呢。

正常情况下,修改PackageName可能是在以前的项目的基础上开发新项目,这时候手动在AS里面通过右键修改啪啪啪。即可搞定。

但是当出现以下需求呢,

  1. 希望一份代码可以导出多个不同的包。
  2. 这份代码还可以持续迭代开发,并且每次发布版本都希望导出多个不同包。

这时候如果还使用手动修改包名明显已经无法满足。希望达到先用代码开发一个能运行的版本,每次发布的时候用脚本导出多个不同包名的包。

3 导出脚本怎么写

好。前面介绍了那么多前提,干货来了。使用脚本发布不同包名的包的步骤应该是以下的:

  1. 先从标准代码复制一份临时代码出来
  2. 替换一些资源文件或者string或者配置文件。(需求是:不同的包希望图标和app名不同)
  3. 使用gradle脚本替换临时代码里的所有包名为目标包名
  4. clean & rebuild

3.1 复制临时代码

这一步就是shell脚本的执行复制,不再赘述。

3.2 替换资源文件、配置信息

这一步我使用php写的,用shell脚本调用执行php(如果只是替换资源文件用shell脚本复制就行),使用php写主要考虑到修改string.xml中的某个值,比如修改app名。

修改string.xml部分代码如下:

$app_name = “指定的app_name”;

//读取XML并解析
$string_doc = new DOMDocument();
$string_doc->load($temp_prj_dir . 'app/src/main/res/values/strings.xml');
$stringList = $string_doc->getElementsByTagName("string"); $len = $stringList->length;
for($i=;$i<$len;$i++) {
$item = $stringList->item($i);//获取列表中单条记录
if($item->getAttribute('name') == "app_name") {
$item->nodeValue = $app_name;
break;
}
}
$string_doc->save($temp_prj_dir . 'app/src/main/res/values/strings.xml');
echo "修改app_name success\n";

在这一步里可以对其他一些配置信息进行自定义和替换。用来区别不同的包。

3.3 替换包名

替换包名用gradle脚本写的。

task replacePackageName {
FileTree tree = fileTree(dir: 'src/main')
tree.include '**/*.java'
tree.include '**/*.xml'
tree.each {File mfile ->
fileReader(mfile.path, packageName)
}
fileReader("build.gradle", packageName)
} def fileReader(path, target_package) {
def readerString = "";
def hasReplace = false file(path).withReader('UTF-8') { reader ->
reader.eachLine {
if (it.find("com.tsy.xxx")) {
it = it.replace("com.tsy.xxx", target_package)
hasReplace = true
}
readerString <<= it
readerString << '\n'
} if(hasReplace) {
println(path + " has replace package.")
file(path).withWriter('UTF-8') {
within ->
within.append(readerString)
}
}
return readerString
}
}

可以看到,需要替换的文件应该是所有的java文件、xml文件还有build.gradle文件。其实就是读取文件树,正则替换。php好的人直接php也可以替换成功。

3.4 clean & rebuild

替换成功后,用gradle命令执行下clean然后再导出就OK拉。

4 结尾

最后给大家看下脚本运行的最终效果。

Android 脚本替换PackageName的更多相关文章

  1. android studio——替换全局的某个字符串

    android studio——替换全局的某个字符串 edit - > replace in path https://blog.csdn.net/dragon0103/article/deta ...

  2. 如何获取Android应用的packageName和ActivityName,识别应用中的控件

    1.获取Android应用的packageName和ActivityName A:adb logcat >log.txt 在log中搜索package B:adb shell  logcat | ...

  3. Android脚本打包

    最近项目中需要添加应用渠道,我使用的是友盟统计,对于不同渠道需要编译不同版本,对于开发者说编译一次,手动操作还是可以接受的,但是项目发布版本频率较高,而且渠道很多,这就是一个体力活,而且手动打包还比较 ...

  4. Android 脚本设计之 SL4A

    SL4A的全称为Scripting Layer for Android, 顾名思义就是Android的脚本架构层,它的目的就是可以用熟知的脚本开发语言来开发Android应用程序.其工作原理基于RPC ...

  5. 我的Android进阶之旅------>关于使用Android Studio替换App的launcher图标之后仍然显示默认的ic_launcher图标的解决方法

    前言 最近做了一个App,之前开发该App的时候一直以来都是默认的launcher图标启动的, 今天美工换了一个App的launcher 图标,因此在Android Studio中将默认的lanche ...

  6. Android 开发替换Launcher

    做android产品的时候,根据需求会制定各种各样的Launcher,因此,在此记录替换系统Launcher的流程. 1.修改frameworks/base/core/java/android/con ...

  7. Android Fragment替换View

    在BaseActivity 中添加替换方法 public void replace(int id, Fragment fragment) { getSupportFragmentManager() . ...

  8. shell 脚本替换文件中某个字符串

    1.将当前目录下包含jack串的文件中,jack字符串替换为tom sed -i "s/jack/tom/g" `grep "jack" -rl ./` 2.将 ...

  9. android开发 替换bitmap中的颜色值

    /** * 将bitmap中的某种颜色值替换成新的颜色 * @param bitmap * @param oldColor * @param newColor * @return */ public ...

随机推荐

  1. c++ <string.h>中包括哪些常用函数

    常用函数如下:strlen  求字符串长度strcmp  比较2个字符串是否一样strcat           字符串连接操作strcpy            字符串拷贝操作strncat     ...

  2. linux 防火墙设置

    防火墙的基本操作命令: 查询防火墙状态:[root@localhost ~]# service iptables status<回车> 停止防火墙:[root@localhost ~]# ...

  3. PHP网络操作函数汇总

    PHP网络操作函数汇总 投稿:junjie 字体:[增加 减小] 类型:转载   这篇文章主要介绍了PHP网络操作函数汇总,本文列举了如gethostbyaddr.gethostbyname.head ...

  4. php实现多线程

    php实现多线程 感谢 3lian8 的投递 时间:2014-01-21 来源:三联教程 有没有办法在php中实现多线程呢?假设你正在写一个基于多台服务器的php应用,理想的情况时同时向多台服务器发送 ...

  5. jQuery 利用 $.getJson() 实现跨域

    数据量不大时,跨域的不二之选,而且操作简单,易上手. a.com/test.html //这里我假定有一些数据: var formData = form.serialize(); //这里的jsonc ...

  6. Segmentation

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION There is another way ...

  7. Paging

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Both unequal fixed-si ...

  8. linux 查看系统状态方法

    Linux下如何查看系统启动时间和运行时间 1.uptime命令输出:16:11:40 up 59 days, 4:21, 2 users, load average: 0.00, 0.01, 0.0 ...

  9. 【转】Unity3D研究院之通过C#使用Advanced CSharp Messenger(五十)

    http://www.xuanyusong.com/archives/2165 Advanced CSharp Messenger 属于C#事件的一种. 维基百科中由详细的说明http://wiki. ...

  10. (转)投票系统,更改ip刷票

    前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了,不 ...