zoukankan      html  css  js  c++  java
  • Android 脚本替换PackageName

    原文简书地址: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 9
        targetSdkVersion 23
        versionCode 1
        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=0;$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
    ";

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

    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 << '
    '
            }
    
            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 结尾

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

    copy, replace config and packageName

    clean and rebuild

    export success

  • 相关阅读:
    数据库sql常见优化方法
    String字符串创建与存储机制
    ==运算符和equals()方法的区别
    Math类中round、ceil和floor方法的功能
    String、StringBuffer和StringBuilder类的区别
    Flask 系列之 构建 Swagger UI 风格的 WebAPI
    Docker 系列之 常用镜像
    Docker 系列之 基础入门
    在 DotNetCore 3.0 程序中使用通用协议方式启动文件关联应用
    .NET Framework VS .NET Core
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/6113854.html
Copyright © 2011-2022 走看看