eclipse+adt+gradle批量打包

最近研究了一下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.0
2. gradle 1.6
3. 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,介绍完毕!有问题请留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值