使用AndroidStudio的过程中,对build.gradle文件配置以及导入支持包的问题的一些总结,在此记录下来。有时候,头疼的不是面对新功能无从下手,而是为了可以正常敲代码与编译环境作斗争。
关于build.gradle配置
compileSdkVersion
SDK的版本号,也就是API Level,例如API-19、API-20、API-21等等,一般保持最新即可。
buildeToolVersion
构建工具的版本,其中包括了打包工具aapt、dx等等,这个一般与CompileSdkVersion对应。
这个工具的目录位于..your_sdk_path/build-tools/XX.XX.XX,这个版本号一般是API-LEVEL.0.0。
可以用高版本的build-tool去构建一个低版本的sdk工程
例如build-tool的版本为20,去构建一个sdk版本为18的
compileSdkVersion 18、buildToolsVersion "22.0.1"
这样也是OK的。targetSdkVersion与minSdkVersion与清单文件中配置一样,含义一样。
android:minSdkVersion
表示APP所兼容的最低API版本,这个一般是项目初期就定好的,轻易不会改动。
指明应用程序运行所需的最小APIlevel。如果不指明的话,默认是1。也就是说该应用兼容所有的android版本。我们应该总是声明这个属性。如果系统的APIlevel低于android:minSdkVersion设定的值,那么android系统会阻止用户安装这个应用。
报错信息为:INSTALL_FAILED_OLDER_SDK
如果指明了这个属性,并且在项目中使用了高于这个API level的API, 那么会在编译时报错。android:targetSdkVersion
表示应用程序目标API Level的一个整数,一般设置成最高的API版本。如果不设置,默认值和minSdkVersion相同。
这个属性通知系统,你已经针对这个指定的目标版本测试过你的程序,系统不必再使用兼容模式来让你的应用程序向前兼容这个目标版本。应用程序仍然能在低于targetSdkVersion的系统上运行。
为了让应用程序支持每个Android版本,应当提高targetSdkVersion的值到最新的APIlevel,然后在对应的平台上彻底的测试你的应用。可知,targetSdkVersion这个属性是在程序运行时期起作用的,系统根据这个属性决定要不要以兼容模式运行这个程序。一般情况下,应该将这个属性的值设置为最新的API level 值,这样的话可以利用新版本系统上的新特性。
关于v4、v7的导入
假如项目是APPModule,需要依赖另外两个Module,A和B。但是ModuleA和ModuleB都需要导入V4包,各自在相应的gradle文件中compile v4即可,不过最好版本保持一致,这样是没问题的。假如此时APP Module需要v4包,就不必引入v4了,因为在依赖ModuleA和ModuleB的时候,已经也依赖了v4包。假如此时APP Module需要v7包,只需要在APP Module的gradle里面compile v7包就可以了,这样并不会冲突。
v7里面包含了v4的所有内容,所以如果导入了v7,就不用再导入v4。
如果原来项目中引入的v7版本是19,后来想升级到23,直接改相应的数字就可以,但是这个版本要存在。同时,要修改相应的compileSdkVersion、buildeToolVersion、targetSdkVersion版本号,保持一致,不然会出现
Process 'command 'd:\Program\Android\sdk\build-tools\23.0.3\aapt.exe'' finished with non-zero exit value 1
这种错误。
错误类型
aapt.exe” finished with non-zero exit value 1
这种错误一般是由compileSdkVersion、buildeToolVersion、targetSdkVersion这种版本号与v4或v7的版本号不一致导致的,修复的方法就是修改这些数字,使版本号一致。当项目中存在多个Module的时候,最好将compileSdkVersion、buildeToolVersion、targetSdkVersion等配置成一样的,防止出现莫名其妙的问题。
Multiple dex files define XXXXandroid/support/v4/aXXXX
这种错误,一定是v4或v7包重复引用导致的,除了要看build.gradle文件的compile的支持包以外,还要看libs文件夹下是不是也有了这些支持包。相应的,如果报错信息Multiple dex files define是这种开头的,一定是导包重复造成的,有可能重复导入了其他的第三方,具体是哪个重复,从报错信息里应该能看出来。
Error: No resource found that matches the given name: attr XXXXXX
这种错误一定是compileSdkVersion、buildeToolVersion、targetSdkVersion这种版本号与v4或v7的版本号不一致导致的,修复的方法就是修改这些数字,使版本号一致。比如原来是引用的v4的19.0.0版本,后来改成23.1.1,但是targetSdkVersion却还是原来的19,这样编译的时候,编译的时候使用的是v4的23.1.1版本,但是找资源的时候,还是找的v4的19.0.0版本的,就会找不到。
Attribute has already been defined XXXXXXXXXXXX
这种错误一是重复导包导致,二是自定义的属性与系统中(一般是支持包中)的属性名字重复。如果确定没有重复导包,就复制那个重复的属性名字,Android Studio中按Ctrl + H组合键,全局搜索,肯定可以找到自己定义的那个属性。不要觉得自己根本没有定义过这个属性,因为有可能项目的其他成员定义过,或者自己忘了,都有可能发生,利用工具,相信工具。一般是在attr.xml这个文件中。
com.android.dex.DexIndexOverflowException: Cannot merge new index XXXXXX into a non-jumbo instruction!(这个XXX数字一定大于65536)
以及com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536”错误原因:
这个错误可能在导入第三方的时候会出现。
原因是同时在工程中引入了多个第三方jar包,导致调用的方法数超过了android设定的65536个(DEX 64K problem),进而导致dex无法生成,也就无法生成APK文件。
限制原因:早期的Dalvik VM内部使用short类型变量来标识方法的id,就有了 最大方法数的限制65536。
解决办法有两种:第一种是忽略方法数限制的检查
这样做的缺点是apk无法再低版本的设备上面安装,会出现错误:
INSTALL_FAILED_DEXOPT
在App Module的build.gradle文件的android节点下添加如下代码:dexOptions { jumboMode = true }
第二种是分包
通过在defaultConfig中设置multiDexEnabled可以开启分包模式,分包之后的Dex就低于了限制数,保证了正常的打包。
defaultConfig {
multiDexEnabled=true
}
//这时还要
compile 'com.google.android:multidex:0.1' 0.1是版本号,用最新的就行。
程序包org.apache.http 、org.apache.http.client.utils等不存在
解决:在build.gradle(Module:app) 文件的android的那个括号里加上
useLibrary 'org.apache.http.legacy'
参考
总结
在项目中,对于第三方的SDK或者jar等,可以在build.gradle中compile的就compile,不要导入Module,再compile project,容易出问题。
导入第三方的时候,一定要仔细参考官方文档集成说明或者官方demo。
遇到这些问题的时候,谁都会头大,就这些问题,折腾了我一个多星期,慢慢熬,去google上多看看别人的相同或相似问题,看看大神们的解答,最好明白其中的道理,记录下来,看多了有时候说不定就突然把问题解决了。