怎样建立网站卖东西,什么是网络推广员,医院网站建设公司价格低,电子商务网站建设详细策划查看原文#xff1a;http://blog.csdn.net/u0108184... Gradle实战系列文章#xff1a;《Gradle基本知识点与常用配置》《Gradle实战#xff1a;Android多渠道打包方案汇总》《Gradle实战#xff1a;不同编译类型的包同设备共存》《Gradle实战#xff1a;执行sql操作hive… 查看原文http://blog.csdn.net/u0108184... Gradle实战系列文章 《Gradle基本知识点与常用配置》《Gradle实战Android多渠道打包方案汇总》《Gradle实战不同编译类型的包同设备共存》《Gradle实战执行sql操作hive数据库》 aar简介 aar文件是Google为Android开发所设计的一种library格式全名为Android Archive Library与Java Jar Library不同的是aar除了java code之外还包含资源文件即xml文件、图片、文字等。本文着重介绍发布过程和遇到的一些坑及其解决方案文中的maven仓库是指公司搭建的maven仓库如果要发布到jCenter或maven central可以参考文章最后的“深入学习“。 1. 准备工作 开发工具Android Studio复习《Gradle基本知识点与常用配置》本文会用到gradle中全局属性设置、文件读取、shell指令执行等相关知识点 工程必须是lib工程即该工程对应的build.gradle文件中要引用 apply plugin: com.android.library 在根目录的build.gradle文件中添加 allprojects { apply plugin: idea
apply plugin: mavenconfigurations {deployerJars
} } configurations.all { resolutionStrategy.cacheChangingModulesFor 0, seconds//不使用缓存使用仓库中最新的包 } subprojects { //表示除主工程外所有子模块 dependencies {deployerJars org.apache.maven.wagon:wagon-http:2.2
} } ext { //仓库选择标记 repoType remote //发布到远程仓库下文中会用到 // repoType local //发布到本地仓库方便调试避免调试期间频繁上传到maven仓库下文中会用到} 在gradle.properties文件中添加 releaseRepositoryUrlxxx //正式包仓库地址下文中会用到snapshotRepositoryUrlxxx //测试包仓库地址下文中会用到repositoryGroupcom.company.appname // 定义要上传的aar所在仓库的Group可自定义但后续引用处要与此一致 在工程根目录下新建一个名为“mavenAccount.properties”文件并将该文件加入到ignore 中该文件用于存放访问maven仓库的账户和密码以及本地仓库地址只有该模块的开发者才有权发布该aar包。 repositoryUserNamexxxrepositoryPasswordxxxlocalRepositoryUrlfile:///Users/admin/Documents/Android/repo/ 2. 编写上传脚本 生成aar包 在工程根目录下新建一个名为“release-as-aar.gradle”的文件其中脚本如下uploadArchives() { repositories {mavenDeployer {configuration configurations.deployerJarsprintln repoType : rootProject.ext.repoTypeif ((rootProject.ext.repoType).equals(remote)) { //发布到远程仓库snapshotRepository(url: snapshotRepositoryUrl) { // 测试包//从本地文件读取仓库账号和密码def File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(repositoryUserName) props.containsKey(repositoryPassword)) {def repositoryUserName props[repositoryUserName]def repositoryPassword props[repositoryPassword]authentication(userName: repositoryUserName, password: repositoryPassword)println 上传到远程仓库} else {println 没有发布权限}} else {println 没有发布权限}}repository(url: releaseRepositoryUrl) { // 正式包def File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(repositoryUserName) props.containsKey(repositoryPassword)) {def repositoryUserName props[repositoryUserName]def repositoryPassword props[repositoryPassword]authentication(userName: repositoryUserName, password: repositoryPassword)println 上传到远程仓库} else {println 没有发布权限}} else {println 没有发布权限}}} else { // 发布到本地仓库def localRepositoryUrldef File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(localRepositoryUrl)) {localRepositoryUrl props[localRepositoryUrl]snapshotRepository(url: localRepositoryUrl)repository(url: localRepositoryUrl)println 上传到本地仓库} else {println 没有发布权限}} else {println 没有发布权限}}}
} } 生成jar包 在工程根目录下新建一个名为“release-as-jar.gradle”的文件其中脚本如下task androidJavadocs(type: Javadoc) { failOnError false
source android.sourceSets.main.java.srcDirs
ext.androidJar ${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar
classpath files(ext.androidJar) } task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { classifier javadoc
from androidJavadocs.destinationDir } task androidSourcesJar(type: Jar) { classifier sources
from android.sourceSets.main.java.srcDirs } uploadArchives { repositories {mavenDeployer {configuration configurations.deployerJarsprintln repoType : rootProject.ext.repoTypeif ((rootProject.ext.repoType).equals(remote)) { //发布到远程仓库snapshotRepository(url: snapshotRepositoryUrl) {def File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(repositoryUserName) props.containsKey(repositoryPassword)) {def repositoryUserName props[repositoryUserName]def repositoryPassword props[repositoryPassword]authentication(userName: repositoryUserName, password: repositoryPassword)println 上传到远程仓库} else {println sorry你没有上传aar包的权限}} else {println sorry你没有上传aar包的权限}}repository(url: releaseRepositoryUrl) {def File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(repositoryUserName) props.containsKey(repositoryPassword)) {def repositoryUserName props[repositoryUserName]def repositoryPassword props[repositoryPassword]authentication(userName: repositoryUserName, password: repositoryPassword)println 上传到远程仓库} else {println sorry你没有上传aar包的权限}} else {println sorry你没有上传aar包的权限}}} else {//发布到本地仓库def localRepositoryUrldef File propFile new File(../mavenAccount.properties)if (propFile.canRead()) {def Properties props new Properties()props.load(new FileInputStream(propFile))if (props ! null props.containsKey(localRepositoryUrl)) {localRepositoryUrl props[localRepositoryUrl]snapshotRepository(url: localRepositoryUrl)repository(url: localRepositoryUrl)println 上传到本地仓库} else {println sorry本地仓库路径不存在}} else {println sorry本地仓库路径不存在}}}
} } artifacts { archives androidSourcesJar
archives androidJavadocsJar } 3. 子模块中相关配置 在子模块的build.gradle文件中添加 group repositoryGroup//version 0.0.1version 0.0.1-SNAPSHOT //表示测试版正式发版时去掉“-SNAPSHOT” //打成aar格式apply from: ../release-as-aar.gradle //引用上传插件 //打成jar格式//apply from: ../release-as-jar.gradle 4. 打包上传 编译通过后打开android studio自带的终端进入相应的module目录下输入gradle uploadArchives5. 使用aar 在需要引用aar包的工程中根目录的build.gradle文件中进行如下配置 allprojects { repositories { // jcenter(); //注释jcenter表示不直接从jcenter仓库获取而是通过公司私服仓库去获取 maven {name xxx //key与value之间有空格url xxx //key与value之间有空格}mavenLocal();
} } 在子模块的build.gradle文件中进行如下引用 dependencies { compile group: repositoryGroup, name: xxx, version: 0.0.1, ext: aar, changing: true } 6. 踩到的坑 问题一上传时找不到服务器上传时需关闭android studio的翻墙代理设置且注释settings.gradle中自动生成的代理服务器相关配置否则上传时会报找不到仓库服务器的错误。 问题二aar包无法更新 有时上传了最新的snapshot包引用的地方也sync、clean了但引用的还是旧的包此时需要删除“~/.gradle”中的相关记录。为方便执行我们可以在应用工程根目录的build.gradle文件中采用shell命令删除该命令会在你执行clean操作时先执行 task deleteDescriptors(type: Exec) { //执行shell命令executable shargs -c, rm -rf ~/.gradle/caches/modules-2/metadata-2.16/descriptors/com.company.appname //此处的“com.company.appname“就是之前定义的“repositoryGroup“。}task clean(type: Delete, dependsOn: deleteDescriptors) { //clean工程时顺带执行上述任务delete rootProject.buildDir} 此时再clean一下引用的就是最新的aar包了。 问题三无法设置debug编译类型 在lib工程中无论怎么设置编译类型最后生成的aar包中始终都是release版本该问题见google反馈。既然不可设置编译类型我们可以在aar包代码中通过反射来获取应用的编译类型 private Object getBuildConfigValue(Context context, String fieldName) {try {Class? clazz Class.forName(context.getPackageName() .BuildConfig);Field field clazz.getField(fieldName);return field.get(null);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return null;}//使用String buildType getBuildConfigValue(ctx,BUILD_TYPE).toString();if (!TextUtils.isEmpty(buildType) buildType.equals(debug)) { // debug...} else { // release...} 但是这里面还有一个坑系统版本在4.4以下的设备中该方法无法获得包名会抛空指针错误。以下我们给出完整的解决方案 public class BuildConfigProvider {private static Context sContext;private static String packageName;public static String getBuildType() {String buildType (String) getBuildConfigValue(BUILD_TYPE);if (debug.equals(buildType)) {buildType debug;}if (release.equals(buildType)) {buildType release;}return buildType;}public static final boolean isDebug() {return BuildConfig.DEBUG;}/*** 通过反射获取ApplicationContext** return*/private static Context getContext() {if (sContext null) {try {final Class? activityThreadClass Class.forName(android.app.ActivityThread);final Method currentActivityThread activityThreadClass.getDeclaredMethod(currentActivityThread);final Object activityThread currentActivityThread.invoke(null);final Method getApplication activityThreadClass.getDeclaredMethod(getApplication);final Application application (Application) getApplication.invoke(activityThread);sContext application.getApplicationContext();} catch (Exception e) {e.printStackTrace();}}return sContext;}/*** 通过反射获取包名** return*/private static String getPackageName() {if (packageName null) {try {final Class? activityThreadClass Class.forName(android.app.ActivityThread);final Method currentPackageName activityThreadClass.getDeclaredMethod(currentPackageName);packageName (String) currentPackageName.invoke(null);} catch (Exception e) {packageName getContext().getPackageName();}}return packageName;}public static Object getBuildConfigValue(String fieldName) {try {Class? clazz Class.forName(packageName .BuildConfig);Field field clazz.getField(fieldName);return field.get(null);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IndexOutOfBoundsException e) {e.printStackTrace();}return ;}} 当然有人可能会说既然可以通过反射得到ApplicationContext就没必要再去反射获得包名了这里只是提供不同的解决方案以作参考。 问题四多包共存模式下获得编译类型为空 在上一篇博客《 Gradle实际应用二同名包共存》中我们可以在一个设备中安装同一个应用不同编译类型的包。但是非release包中我们获得的包名是带有编译类型后缀的如“com.company.appname.debug“而编译类型我们是通过反射获取“BuildConfig“所在的包名还是原始的、不加后缀的包名如“com.company.appname“此时我们拿到的编译类型为空那么我们可以在获取包名后做一个检查 private static String checkPackageName(String packageName) {String[] temp packageName.split(\\.);String sub temp[temp.length - 1];//如果多包共存模式剔除包名中的后缀if (sub.equals(debug)) {StringBuilder sb new StringBuilder();for (int i 0; i temp.length - 1; i) {sb.append(temp[i]);if (i ! temp.length - 2) {sb.append(.);}}packageName sb.toString();}return packageName;}深入学习 同步aar到jCenter与maven centralAndroid Studio使用Gradle上传AAR至Mavenaar无法设置debug问题解决参考查看原文http://blog.csdn.net/u0108184...