eclipse+adt+gradle批量打包

来源:互联网 发布:淘宝网冬装女装 编辑:程序博客网 时间:2024/05/17 09:01
最近研究了一下Android的批量打包,之前本人使用ant打包,大家都知道ant打包慢而且配置多而复杂,后来出现了gradle,优点多多,十分受欢迎,于是本人也就适应潮流开始学习使用Gradle,学习过程中遇到很多问题,也参考了很多网上大牛写的教程,要么很老,要么写得不清楚,要么工具跟本人使用的不匹配而出现问题,并且想过放弃,但是最后还是成功了,在这里把这个过程分享给和我一样遇到类似问题的小伙伴们。   android的IDE目前主流的选择有三个,一个是传统的eclipse,然后是IntelliJ IDEA和android studio。其中android studio就是IntelliJ IDEA的演进版,只是专门为Android开发加了一些插件和优化。目前eclipse的使用者应该占多数,至少我还在使用eclipse。其它两种IDE对Gradle的支持非常好,在此不作研究。本人使用的开发环境是:1. eclipse adt 22.3.02. gradle 1.63. windows 7 utimate 64习惯使用eclipse的用户应该会遇到多渠道发包的问题,多渠道打包的方法有很多种,也有很多第三方为此开发了一些简单易用的插件,不过原理都差不多,都是基于ant或者gradle。为了学习使用专业的打包工具,咱们还是接触原生的工具比较好。正式进入主题吧,下面开始讲解使用eclipse adt和gradle怎么打包。打包的原理很简单,就是gradle会根据build.gradle的配置文件执行编译打包指令,我们要做的就是修改build.gradle文件。第一步当然是搭建好你的环境。adt最好使用22或以上的,以方便生成build.gradle文件。没有的可以在我的微云下载:http://share.weiyun.com/150965ebab5aa3ae76586f36c075370a 这是eclipse+adt的集成版。adt不是22的也没有关系,继续往下看,把我的build.gradle复制过去就行了。第二步去gradle官网下载gradle1.6,推荐使用1.6。目前gradle已经更新到了2.2.0,本人开始下载的就是2.2.0结果不成功,试过1.9也不成功,1.6成功了。可能新版的gradle对eclipse支持不太好吧。第三步就是配置好系统环境变量。把你下载的gradle解压放到d盘或e盘某个位置,在环境变量path中加上gradle的bin目录,以方便在cmd下使用gradle命令。第四步就是使用编写build.gradle文件。这个可以从其它地方复制或者用adt导出,用adt导出的方法是右键你的android工程-export-android-generate gradle build file-finish就ok了。然后你的工程根目录下就会有一个build.gradle文件。里面adt已经帮你写好了最基本的配置,下面就是根据你的需求添加自己的配置。打包需要配置keystore的路径和密码,在android{ }这个标签中加上:
signingConfigs {      myConfig{      storeFile file("keystore.release")        storePassword "xxxxx"        keyAlias "xxxxx"        keyPassword "xxxxx"      }    }

buildTypes{      release {        signingConfig  signingConfigs.myConfig        runProguard true        proguardFile 'proguard-project.txt'     }    }

为了防止乱码,把你工程编码设为utf-8然后在build.gradle最外层加上:

tasks.withType(Compile) {        options.encoding = "UTF-8" }  

其中xxxx原名思议就是keystore文件的配置。自己去填吧!buildTypes里的配置就是生成正式的包。
然后在cmd下切换到工程根目录,执行gradle clean初始化一下,第一次需要下载一些东西,稍等两分种左右,如果没问题就会显示build successful。如果失败可能是build配置有问题或者你的gradle的版本的问题了。然后执行gradle build命令开始编译打包。然后在你的工程目录下就会生成build文件夹,里面有一个apk文件夹就是生成的三个apk文件,只有[工程名]-relaase.apk才是我们要的。
以上是生成一个签名的apk,那么怎么生成多渠道的apk呢?以友盟为例。
首先在你的manifest文件的application标签中加上:

  <meta-data android:name="UMENG_CHANNEL" android:value="UMENG_CHANNEL_VALUE"/>
然后在build.gradle文件中的android{}标签中加上:
 defaultConfig {        versionCode getVersionCode()        versionName getVersionName()        minSdkVersion 8        targetSdkVersion 19    }     productFlavors {        wandoujia{        }        yingyongbao{        }        google{        }    }

然后在再外层加上:

android.applicationVariants.all{ variant ->     variant.processManifest.doLast{        copy{            from("${buildDir}/manifests"){                include "${variant.dirName}/AndroidManifest.xml"            }            into("${buildDir}/manifests/$variant.name")            filter{                String line -> line.replaceAll("UMENG_CHANNEL_VALUE", ("${variant.productFlavors[0].name}"-'_'))            }            variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")        }       }}

productFlavors里面配置的就是要生成的渠道列表,以上示例生成wandoujia、yingyongbao和google三个渠道包。当然可以继续添加。网上有另一种配置:

productFlavors {            wandoujia{                manifestPlaceholders = [ UMENG_CHANNEL_VALUE:name]            }            google_play{                manifestPlaceholders = [ UMENG_CHANNEL_VALUE:name]            }        }
   这种写法目前的gradle版本和adt是不支持的!   OK,到此为此配置已经搞定了。下面就执行gradle clean,gradle build命令跑一下吧!最后在build文件夹的apk文件夹中会生成若干个各渠道的apk文件。可以代码中加上显示UMENG_CHANNEL值的功能:   
    public class MainActivity extends Activity {    private TextView tv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv=(TextView)findViewById(R.id.textView1);        String msg="渠道号——"+getMetadata("UMENG_CHANNEL");        tv.setText(msg);    }    private String getMetadata(String name){        Object value = null;        PackageManager packageManager = this.getPackageManager();        ApplicationInfo applicationInfo;        try {            applicationInfo = packageManager.getApplicationInfo(this                    .getPackageName(), 128);            if (applicationInfo != null && applicationInfo.metaData != null) {                value = applicationInfo.metaData.get(name);            }        } catch (NameNotFoundException e) {            throw new RuntimeException(                    "Could not read the name in the manifest file.", e);        }        if (value == null) {            throw new RuntimeException("The name '" + name                    + "' is not defined in the manifest file's meta data.");        }        return value.toString();    }}

示例工程目录结构:
示例工程目录结构
示例build.gradle文件:

buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'com.android.tools.build:gradle:0.5.0+'    }}apply plugin: 'android'dependencies {    compile fileTree(dir: 'libs', include: '*.jar')}android {    compileSdkVersion 19    buildToolsVersion "19.0.0"    sourceSets {        main {            manifest.srcFile 'AndroidManifest.xml'            java.srcDirs = ['src']            resources.srcDirs = ['src']            aidl.srcDirs = ['src']            renderscript.srcDirs = ['src']            res.srcDirs = ['res']            assets.srcDirs = ['assets']        }        // Move the tests to tests/java, tests/res, etc...        instrumentTest.setRoot('tests')        // Move the build types to build-types/<type>        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...        // This moves them out of them default location under src/<type>/... which would        // conflict with src/ being used by the main source set.        // Adding new build types or product flavors should be accompanied        // by a similar customization.        debug.setRoot('build-types/debug')        release.setRoot('build-types/release')    }    signingConfigs {      myConfig{      storeFile file("keystore.release")        storePassword "xxxxxx"        keyAlias "xxxxxx"        keyPassword "xxxxxx"      }    }    buildTypes{      release {        signingConfig  signingConfigs.myConfig        runProguard true        proguardFile 'proguard-project.txt'     }    }   defaultConfig {        versionCode getVersionCode()        versionName getVersionName()        minSdkVersion 8        targetSdkVersion 19    }     productFlavors {        wandoujia{        }        yingyongbao{        }        google{        }    }}tasks.withType(Compile) {        options.encoding = "UTF-8" }  android.applicationVariants.all{ variant ->     variant.processManifest.doLast{        copy{            from("${buildDir}/manifests"){                include "${variant.dirName}/AndroidManifest.xml"            }            into("${buildDir}/manifests/$variant.name")            filter{                String line -> line.replaceAll("UMENG_CHANNEL_VALUE", ("${variant.productFlavors[0].name}"-'_'))            }            variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")        }       }}

OK,介绍完毕!有问题请留言。

0 0
原创粉丝点击