Eclipse Ant切换成AS Gradle打包

之前一直用的是Eclipse开发Android项目,并且打包也是用Ant打包。

ant打包相关的配置文件有: build.xml文件


在工程中build.xml有相关配置,此文件可以直接从其他项目拷贝然后修改。

里面有个<import file="custom_rules.xml" optional="true" />配置,custom_rules.xml配置了ant打包相关的内容

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom-rules" default="help">
    <property name="java.encoding" value="utf-8" />
    <echo message="custom-rules"></echo>
    <import file="crashlytics/crashlytics_build.xml"/>
    <property name="source.dir" location="src; src-gen-gd; src-pdf; src-test; src-framework;" />
    <property file="secure.properties" />
    <property  name="apk.dir"  value="./release"/>
    <!-- Read manifest properties , e.g.
         manifest(android:versionName) or manifest.package -->
    <xmlproperty file="AndroidManifest.xml" />
    <property name="version" value="${app_version}" />
 	<!-- process channels -->
    <taskdef resource="net/sf/antcontrib/antcontrib.properties" >
        <classpath>
            <pathelement location="libs/ant-contrib-1.0b3.jar" />
        </classpath>
    </taskdef>

    <target name="channels" >
        <mkdir dir="${apk.dir}" />
        <replaceregexp
            byline="false"
            encoding="utf-8"
            file="./AndroidManifest.xml"
            match="android:versionName="(.*)""
            replace="android:versionName="${version}""/>
        <foreach
            delimiter=","
            list="${market_channels}"
            param="channel"
            target="modify_manifest" >
        </foreach>
    </target>

    <target name="modify_manifest" >
         <tstamp/>
         <replaceregexp
            byline="false"
            encoding="utf-8"
            file="./AndroidManifest.xml"
            match="android:name="Channel"(\s*)android:value="(.*)""
            replace="android:name="Channel" android:value="${channel}"" />
        <property
            name="out.final.file"
            location="${apk.dir}/${ant.project.name}_${channel}_v${version}_${DSTAMP}.apk" />
        <antcall target="clean" />
        <antcall target="release" />
    </target>
</project>

包括<property name="source.dir" location="src; src-gen-gd; src-pdf; src-test; src-framework;" />打包的source源码的dir文件路径;配置了<target name="channels" > 打包的执行命令,这样就直接ant channels就可以执行打包了;配置了如何替换version和manifest里的channel渠道。这些配置看看就好,可以试着修改下,如果用Ant打包遇到了问题可以参照配置进行分析错误,这里不具体详细描述。


Android要想打包必须进行缩减、优化、混淆代码,而伟大的Proguard为我们提供了此功能。Android系统SDK里面也已经有proguard-android.txt和proguard-android-optimize.txt 摘抄proguard官网http://proguard.sourceforge.net/manual/examples.html#androidapplication(

  • Android SDK revision 20 and higher have a different configuration file for enabling optimization: ${sdk.dir}/tools/proguard/proguard-android-optimize.txt instead of the default ${sdk.dir}/tools/proguard/proguard-android.txt.
),自己的工程项目里的proguard-project.txt配置里面配置具体的混淆优化缩减规则。

有关配置其实也是从其他文件里拷贝过来,然后加以修改调整,里面的配置参数可以参阅Proguard官网:

http://proguard.sourceforge.net/


当我开发工具切换到AS中去时,配置好了build.gradle文件。

//根级build文件,可以将对所有子模块生效的通用配置添加到这里
buildscript {
    repositories {
        maven {
        url "http://download.crashlytics.com/maven"
          }
    }
    //Android Gradle插件依赖,版本定义
    dependencies {
        classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
    }
}

//安卓应用类型的工程构建使用com.android.application
apply plugin: 'com.android.application'
apply plugin: 'crashlytics'

//依赖设置
dependencies {
     //jar包依赖
    compile fileTree(dir: 'libs', include: ['*.jar'])
    
}

android {
     //default flavor配置,与其他 flavor共享的基础配置
     defaultConfig {
          //此处设置将会覆盖manifest文件设置
         compileSdkVersion 19
         buildToolsVersion "22.0.1"
         //versionCode 1.2
         //versionName 1.33
          manifestPlaceholders = [CHANNEL_VALUE:"Official_Channel"]

         //源码集设置
         sourceSets {
             main {
                 manifest.srcFile 'AndroidManifest.xml'
                 //Java source link
                 java.srcDirs = ['src-framework','src','src-gen-gd','src-pdf','src-test']
                 //.so 等 JNI依赖
                 jniLibs.srcDirs = ['libs']
                 resources.srcDirs = ['src']
                 aidl.srcDirs = ['src-framework','src','src-gen-gd','src-pdf','src-test']
                 renderscript.srcDirs =['src-framework','src','src-gen-gd','src-pdf','src-test']
                 res.srcDirs = ['res']
                 assets.srcDirs = ['assets']
             }
          }
     }

    //flavors 配置,渠道包
    productFlavors {
         Default_Channel {
            manifestPlaceholders = [CHANNEL_VALUE:"test_offline"]
        }
    }

    //lint配置
    lintOptions {
        // checkReleaseBuilds false
        // quiet true
        abortOnError false
    }

    //release 签名设置
    signingConfigs {
          release {
               storeFile file('keystore/****.keystore')
               storePassword '******'
               keyAlias '****'
               keyPassword '*****'
          }
     }

    //build类型,release/debug,不同于productFlavors,打type=release包时,使用proguard混淆同时使用前面定义的release签名策略
    buildTypes {
          release {
               minifyEnabled true
               proguardFile getDefaultProguardFile('proguard-android.txt')
               proguardFile 'proguard-project.txt'
               signingConfig signingConfigs.release
          }
          //debug {
          //    applicationIdSuffix ".debug"
          //}
     }

     //修改生成的apk名字
    android.applicationVariants.all{ variant->
    variant.outputs.each { output->
        def oldFile = output.outputFile
        def newName = '';
        //if(variant.buildType.name.equals('release')){
            // APK输出文件名规则:
        if(variant.productFlavors.get(0).name.equals('Default_Channel') && variant.buildType.name.equals('release')){
            // appReleaseDir对应local.properties里面定义的路径,再加上日期(格式:201503011230)文件夹,../就到上一级目录了
            output.outputFile = new File("${buildDir}/../../", "default.apk")
        }
        if(variant.buildType.name.equals('beta')){
        }
        if(variant.buildType.name.equals('debug')){
 
        }
    }
}
}

更多关于gradle的配置可以查阅具体的文档修改。里面配置了混淆用到的proguard文件,即proguard-project.txt文件。

如果直接用原始的proguard-project.txt文件,不做修改的话,gradle clean build打包一直报错,说Specifly ****.jar twice 了,就是该jar包指定了两遍。可是同样的配置用Ant打包却不会报这种错误。

看到一篇博客http://blog.csdn.net/X_i_a_o_H_a_i/article/details/41979983


里面说是是build.gradle文件配置了

dependencies {
    compile fileTree(include: '*.jar', dir: 'libs')

}

我想也是,因为前面加了个compile是编译的意思,一个android apk包是把所有依赖的class编译进dex文件里面。所以既然这里指定了jar,那就没必要再proguard-project.txt指定一遍。


这里其实要想明白 -libraryjars class_path<br/>
Specifies the library jars (or aars, wars, ears, zips, apks, or directories) of the application to be processed. The files in these jars will not be included in the output jars.这个语法的意思。官网解释是段英文,含含糊糊能说通,但是具体到底怎么回事除非你懂proguard的运行原理机制。

gradle打包需要把proguard-project.txt里的所有类似-libraryjars libs/greendao-1.3.7.jar前加上注释。


最后用Ant和gradle打包成功后,会在bin/proguard/文件下面多出mapping.txt,seeds.txt,usage.txt,dump.txt文件。

ProGuard 在运行后会输出以下文件:

dump.txt
描述 .apk 文件中所有类文件的内部结构
mapping.txt
列出原始与混淆后的类、方法和字段名称之间的对应关系。如果您从发布版本收到问题报告,则必须使用此文件,因为通过它可将混淆后的堆栈跟踪信息转换为原始的类、方法和成员名称。有关详情,请参阅解码混淆后的堆栈跟踪信息。
seeds.txt
列出未混淆的类和成员
usage.txt
列出从 .apk 删除的代码
这些文件都位于以下目录中:

<project_root>/bin/proguard(如果您使用的是 Ant)。
<project_root>/proguard(如果您使用的是 Eclipse)。

上面是Android官网关于proguard的解释https://developer.android.com/intl/zh-cn/tools/help/proguard.html

查看自己相关的class类是否被混淆了可以查找上面对应的文件。


打包成功后如果发现apk有些功能闪退,出现 at b.b.b.i$b.<cinit>等类似的错误,很明显是因为混淆后找不对应的class或者执行出错了。这个时候需要找到对应的代码,然后在proguard-project.txt配置里面keep住相应的class类。

所以其实发到市场上最终的包每个功能都必须验证一下,因为可能代码写对了,但混淆把你的代码混淆了,导致功能不可用。遇到混淆配置的问题也只要找到错误原因然后keep不不需要混淆的class。


proguard官网关于Android的配置:http://proguard.sourceforge.net/manual/examples.html#androidapplication


这是个人的理解,记录下来,如果有错误的地方误导大家,麻烦批评指正,给我留言,感激不尽!








你可能感兴趣的:(Eclipse Ant切换成AS Gradle打包)