AndroidStudio中gradle到底是什么?

  gradle是什么?我也不知道,自从我接触android以来,一提到这东西就我头疼。因为被qiang的原因,每次去网上找一些学习代码、git上弄来一些有用的工具类、找个demo之类的,导入的时候95%会给我卡gradle。在初学的时候真的是吃够了苦头,试想:你还是个萌新,基本上得看着教程学,然后你下载的教程打不开,好不容易打开了满脸都是红的提示框,你还有学下去的欲望吗。。。。
  现在,我们去百度看一眼gradle,看懂了么、、反正我没看懂。现在的水平也就只能想几个法子,来应对一下AndroidStudio使用过程中gradle可能会出现的麻烦。

麻烦! 下载别人的代码AS打不开?

  经常在csdn,或者git上面找来的as工程代码,然后打开始会卡在 building gradle 这一步,因为在下载的项目文件夹中 bulid.gradle文件的配置是原作者使用的gradle版本,换了个编译环境,gradle版本变了,所以AS会去自动下载符合的gradle,那个下载的地址可以在/gradle/wrapper/gradle-wrapper.properties 中看到,由于被qiang的情况下,基本上是等到死都下载不完的。
  这个解决方法就是在打开项目之前就手动去修改这些设置,首先随便找一个你能打开的项目(一般来说新建一个新的项目就好了),左边的显示模式选为android

第一步

  去找到build.gradle(你的项目名),将其中的dependence复制 (主要是 classpath 这一条后面的内容 比如’com.android.tools.build:gradle:2.2.3’),去替换你要打开的项目对应的那一条,文件路径为/bulid.gradle。

第二步

  找到gradle-wrapper.properties,其中最后一条,distributionUrl=xxxx ,将这一条复制,去替换你要打开的项目中对应的那个地址,路径为上面提到过的/gradle/wrapper/gradle-wrapper.properties

第三步

  打开build.gradle(app),这个括号里的app其实就是module名,打开它,找到android 这个block,其中 buildToolsVersion 后面的版本复制下来。然后同样的,去替换掉你要打开的项目的对应条,具体路径为/app/build.gradle 注意!!! 这个app仅仅是module名,实际替换的时候你要找到目标代码的module,因为这个名字不是固定的,app只是一个默认的名字。同样的,如果目标module依赖了其他的library,则需要将所有被依赖的lib中的build.gradle,中的buildToolsVersion 都替换。
   经过这以上3步,则可以打开项目了,但并不代表一定能跑起来,可能还得根据编译器的提示做进一步的工作。不过已经打开了这个项目了,那么剩下的工作也已经不是什么大问题了。

指定jniLibs地址

  曾经做过一个项目,其中用到的jar库需要用到一些so文件,也就是c那边的一些源码,可能涉及到ndk 我不是很懂了。 但是仅仅就将so文件放在lib文件加下的话,也许,也许并没有什么卵用,得去指定一下文件的路径,指定方法为:找到该module的build.gradle文件,然后android block中添加以下代码

1
2
3
4
5
6
7
8
android {
...
sourceSets.main {
jniLibs.srcDirs = ['libs'] //设置目标的so存放路径
jni.srcDirs = [] //disable automatic ndk-build call
}
...
}

多渠道打包的小应用

  有时候一份代码写出来,可能要给不同的客户演示,但是你总不能把客户A家的logo,给客户B看吧。所以得区分开,最蠢的方法就是吧代码完全的复制一份,修改一些特性化的地方(真的蠢,我一开始就是这么干的),但是随着版本的更新,我发现我要开始维护2份代码了,虽然是相同的代码,但是写ctrlCV一遍也很累啊,而且容易弄混,A家的app里面跑着跑着出现的B家的图片,每次更新很是痛苦。直到有一天,我们有了客户C。。。
  我觉得是时候根治这个问题了,在网上查询很久,最后看到了productFlavors,这个功能普遍被用来实现多渠道打包,将一份代码打上不同渠道的标识。思索很久,也看了很多教程,我打算将他修改一下…
  一个例子:我打算将一个自己写的小游戏,light,打包成2个不同的app light1,和light2,同时他们有不同的app图标,不同的app包名(其实是appid),以及不同的ui,不同的素材等等…但是他们的根本,代码文件是一样的。OK,开始吧!

第一步 独立的文件

  首先将左边的文件试图模式由默认的android改为project,在app/src下新建文件夹light1和light2,注意这2个文件夹应该与main是同一级别,作为存放不同的 个性化的文件夹。
  现在我将预先写好的 2个xml layout文件分别放在light1 和light2中,注意,所有资源的路径应该与main下的路径一致,且名字相同。在构建app时,main下所有的文件是作为默认文件,但是构建light1时,当检测到light1下也有相同的文件时,会优先使用light1下的文件。
  值得注意的是,所有资源文件的性质是替换,而代码文件的性质则是合并。这有什么区别呢?举个例子,main,lghit1,light2下都有 以下文件 MainActivity.java,main_layout.xml,icon.png。那么编译的时候会发生什么呢? 答案是无法编译,出错!
  main_layout.xml,icon.png 是资源文件所以没有问题。编译不同模块的时候会使用不同模块下的这2个文件,但是java文件不是这样,编译器会提示你:已经有了java文件了,为什么还会存在2个同名的文件!!!!在所有的文件下,不能有重复的java文件,因此一般想实现代码上的不同,可以在java文件中写一个判断,来检测现在编译的是什么,分别给不同的情况写上不用的代码即可。

第二步 manifests配置

  打开manifests,这里就演示一下替换图标(其实我不会)

1
android:icon="${app_icon}" 

第三步 buildgradle中的设置

  打开module的build.gradle,在android block中增加代码块 productFlavors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
android {
....
productFlavors {
light1 {
applicationId "com.magic.light1"
resValue "string", "app_name", "light1"
manifestPlaceholders = [app_icon : "@mipmap/icon_light1"]
}

light2 {
applicationId "com.magic.light2"
resValue "string", "app_name", "light2"
manifestPlaceholders = [app_icon : "@mipmap/icon_light2"]
}
}
.....
}

  其中 light1 和 light2 是我要区别打包的2个对象(这里要注意,light1 和 light2 的这2个名字虽然是自定义的,但是必须和第一步中在project下新建的文件夹名对应相同),每一个中设置了相关的信息,就以上面的为例:applicationId这一行 是设置本模块的appid(不同的appid)。resValue 一行是在打包时设置app的名字(不同的名字)。最后一行是设置manifests中的替换部分,这里是使用了不同的资源文件(不同的图标)。