标签: gradle

Gradle学习系列之一——Gradle快速入门

Gradle学习系列之一——Gradle快速入门

这是一个关于Gradle的学习系列,其中包含以下文章:

    1. Gradle快速入门
    2. 创建Task的多种方法
    3. 读懂Gradle语法
    4. 增量式构建
    5. 自定义Property
    6. 使用java Plugin
    7. 依赖管理
    8. 构建多个Project
    9. 自定义Task类型
    10. 自定义Plugin

 

%title插图%num

 

 

和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作用的是Plugin。Gradle在默认情况下为我们提供了许多常用的Plugin,其中包括有构建Java项目的Plugin,还有War,Ear等。与Maven不同的是,Gradle不提供内建的项目生命周期管理,只是java Plugin向Project中添加了许多Task,这些Task依次执行,为我们营造了一种如同Maven般项目构建周期。更多有关Maven的知识,读者可以访问Maven官网,或者可以参考笔者写的Maven学习系列文章。

 

现在我们都在谈领域驱动设计,Gradle本身的领域对象主要有Project和Task。Project为Task提供了执行上下文,所有的Plugin要么向Project中添加用于配置的Property,要么向Project中添加不同的Task。一个Task表示一个逻辑上较为独立的执行过程,比如编译Java源代码,拷贝文件,打包Jar文件,甚至可以是执行一个系统命令或者调用Ant。另外,一个Task可以读取和设置Project的Property以完成特定的操作。

让我们来看一个*简单的Task,创建一个build.gradle文件,内容如下:

task helloWorld << {
   println "Hello World!"
}

 

这里的“<<”表示向helloWorld中加入执行代码——其实就是groovy代码。Gradle向我们提供了一整套DSL,所以在很多时候我们写的代码似乎已经脱离了groovy,但是在底层依然是执行的groovy。比如上面的task关键字,其实就是一个groovy中的方法,而大括号之间的内容则表示传递给task()方法的一个闭包。除了“<<”之外,我们还很多种方式可以定义一个Task,我们将在本系列后续的文章中讲到。

在与build.gradle相同的目录下执行:

gradle helloWorld

 

命令行输出如下:

复制代码
复制代码
:helloWorld
Hello World!

BUILD SUCCESSFUL

Total time: 2.544 secs
复制代码
复制代码

 

在默认情况下,Gradle将当前目录下的build.gradle文件作为项目的构建文件。在上面的例子中,我们创建了一个名为helloWorld的Task,在执行gradle命令时,我们指定执行这个helloWorld Task。这里的helloWorld是一个DefaultTask类型的对象,这也是定义一个Task时的默认类型,当然我们也可以显式地声明Task的类型,甚至可以自定义一个Task类型(我们将在本系列的后续文章中讲到)。

比如,我们可以定义一个用于文件拷贝的Task:

task copyFile(type: Copy) {
   from 'xml'
   into 'destination'
}

 

以上copyFile将xml文件夹中的所有内容拷贝到destination文件夹中。这里的两个文件夹都是相对于当前Project而言的,即build.gradle文件所在的目录。

Task之间可以存在依赖关系,比如taskA依赖于taskB,那么在执行taskA时,Gradle会先执行taskB,然后再执行taskA。声明Task依赖关系的一种方式是在定义一个Task的时候:

task taskA(dependsOn: taskB) {
   //do something
}

 

Gradle在默认情况下为我们提供了几个常用的Task,比如查看Project的Properties、显示当前Project中定义的所有Task等。可以通过一下命令查看Project中所有的Task:

gradle tasks

 

输出如下:

复制代码
复制代码
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
setupBuild - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
dependencies - Displays all dependencies declared in root project 'gradle-blog'.
dependencyInsight - Displays the insight into a specific dependency in root project 'gradle-blog'.
help - Displays a help message
projects - Displays the sub-projects of root project 'gradle-blog'.
properties - Displays the properties of root project 'gradle-blog'.
tasks - Displays the tasks runnable from root project 'gradle-blog'.

Other tasks
-----------
copyFile
helloWorld

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

Total time: 2.845 secs
复制代码
复制代码

 

可以看到,除了我们自己定义的copyFile和helloWorld之外,Gradle还默认为我们提供了dependencies、projects和properties等Task。dependencies用于显示Project的依赖信息,projects用于显示所有Project,包括根Project和子Project,而properties则用于显示一个Project所包含的所有Property。

在默认情况下,Gradle已经为Project添加了很多Property,我们可以调用以下命令进行查看:

gradle properties

 

输出如下:

复制代码
复制代码
:properties

------------------------------------------------------------
Root project
------------------------------------------------------------

allprojects: [root project 'gradle-blog']
ant: org.gradle.api.internal.project.DefaultAntBuilder@1342097

buildDir: /home/davenkin/Desktop/gradle-blog/build
buildFile: /home/davenkin/Desktop/gradle-blog/build.gradle
...
configurations: []
convention: org.gradle.api.internal.plugins.DefaultConvention@11492ed
copyFile: task ':copyFile'
...
ext: org.gradle.api.internal.plugins.DefaultExtraPropertiesExtension@1b5d53a
extensions: org.gradle.api.internal.plugins.DefaultConvention@11492ed
...
helloWorld: task ':helloWorld'
...
plugins: [org.gradle.api.plugins.HelpTasksPlugin@7359f7]
project: root project 'gradle-blog'
...
properties: {...}
repositories: []

tasks: [task ':copyFile', task ':helloWorld']
version: unspecified

BUILD SUCCESSFUL

Total time: 2.667 secs
复制代码
复制代码

 

在以上Property中,allprojects表示所有的Project,这里只包含一个根Project,在多项目构建中,它将包含多个Project;buildDir表示构建结果的输出目录;我们自己定义的helloWorld和copyFile也成为了Project中的Property。另外,Project还包括用于执行Ant命令的DefaultAntBuilder(Property名为ant)和Project的描述属性description。

 

Android studio 如何查看 library 间的依赖关系

一、配置环境
Android Studio中使用的 gradle 版本一般不是*新版,所以在使用其自带的 Terminal 时容易报版本过低的错误,为了方便使用,我从 gradle
官网下载了*新版的 gradle ,然后配置好 gradle 的环境变量以方便使用。

二、gradle task 相关内容
gradle 本身不提供查看 library 依赖关系的命令,幸好 Android Studio 提供了可供查看的 task ,位于各个 module 的 help 任务堆中,如下图:

%title插图%num

%title插图%num

双击 dependencies 执行该任务,可以看到在 gradle console 中均没有得到依赖关系,结果如下图所示:

%title插图%num

从上图可以看出无论我们执行哪个 module 下的 dependencies 其结果都是相当于在 Root project 执行了该任务;那么在 app project 或者 test01library project 中执行该 dependencies 任务呢?此时就需要我们通过命令行的方式执行 dependencies 了。

1.查看 app project 的依赖关系
在该路径下打开命令行工具,输入

gradle dependencies

稍等一会,便可看到 library 的依赖关系,如下图所示:

%title插图%num

但是命令行中会生成大量内容,并且无法看到全部信息,为了方便查看,我们将输出信息写入文本文件中

gradle dependencies >log.txt

在当前目录下将生成一个 log.txt 文件里面包括所有 app project 所依赖 library 的所有依赖关系(test01library 同理) 。

2.查看指定类型的依赖关系
由于 dependencies 的配置类型太多这里仅以编译时 library 为例说明:

// 查看 compile 时的依赖关系
gradle dependencies –configuration compile

关于其他配置类型可以通过这条命令获得:

gradle dependencies –info

可以看到有很多参数

%title插图%num

3.在 Root project 下查看依赖关系
在项目根目录下我们可以通过下面命令达到和上面相同的效果,如:

// gradle :project name:dependencies [–configuration compile]
gradle :app:dependencies –configuration compile

三、总结
查看各 library 的依赖关系是为了避免出现java.util.zip.ZipException: duplicate entry exception android/support/vX/…/xxx.class 异常;由于 app project 必定会直接或间接引用其他所有 project, 所以,只查看这一个 project 的依赖关系即可得到全部信息。

android 7.0文件读写权限配置

在gradle中指定applicationId,这里也会跟着变了AdroidManifest.xml

android:authorities=”${applicationId}.fileProvider”
<provider
android:name=”android.support.v4.content.FileProvider”
android:authorities=”${applicationId}.FileProvider”
android:exported=”false”
android:grantUriPermissions=”true”>
<meta-data
android:name=”android.support.FILE_PROVIDER_PATHS”
android:resource=”@xml/rc_file_path” />
res/xml/rc_file_path.xml 文件的名字没有要求,只要放在xml文件夹下面就可以了
<?xml version=”1.0″ encoding=”utf-8″?>
<paths>

<external-path path=”.” name=”name” />

</paths>
paths这个元素内可以包含以下一个或多个

<files-path name=”name” path=”path” />对应内部内存卡根目录:Context.getFileDir() + /path/

<cache-path name=”name” path=”path” />对应应用默认缓存根目录,物理路径相当于Context.getCacheDir() + /path/

<external-path name=”name” path=”path” />对应外部内存卡根目录,物理路径相当于Environment.getExternalStorageDirectory() + /path/

<external-files-path name=”name” path=”path” />对应外部内存卡根目录下的APP公共目录,物理路径相当于Context.getExternalFilesDir(String) + /path/

<external-cache-path name=”name” path=”path” />对应外部内存卡根目录下的APP缓存目录,物理路径相当于Context.getExternalCacheDir() + /path/

拍照:

//创建图片存放file
File imgFile = new File(“照片存放目录”);
Uri uri;
//根据当前系统版本决定使用哪个api,N是Android7.0的代号
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//*个参数是上下文,第二个参数来自清单文件,必须完全一样,第三个参数为上面创建的照片file
uri = FileProvider.getUriForFile(this, “${applicationId}.FileProvider”, imgFile);
} else {
//Android7.0还用原先的api
uri = Uri.fromFile(imgFile);
}
//设置拍照后保存目录
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
应用安装
//创建安装包file
File apkFile = new File(path);
Uri uri;
//根据当前系统版本决定使用哪个api,N是Android7.0的代号
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, “{applicationId}.FileProvider”, apkFile);
} else {
//Android7.0还用原先的api
uri = Uri.fromFile(apkFile);
}
//当前代码在Activity里则下面这句可省略
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//授权Intent读取URI和写URI的权限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.setDataAndType(uri,”application/vnd.android.package-archive”);
context.startActivity(intent);
 

Gradle打包失败处理

为什么标题这么诡异,其实主要是同一个问题导致的。*近项目Unity版本从5.6.4升级到了Unity2017.4.7版本,然后使用Gradle打包,发现失败,提示这个错误CommandInvokationFailure: Gradle build failed。如下图:

%title插图%num
刚开始还是以为版本问题导致,换成不用Gradle打包,成功,但这没什么卵用,因为项目这边需要出AAR包(也就是所谓的母包),所以这个问题一定要解决,然后各种查,得到好几个方案:
1.更改jdk版本,改成JDK 1.8.161。
2.更改android的SDK版本,改成SDK 25.2.5。

%title插图%num
3.更改gradle版本, 改成Android plugin version 2.3.0和Gradle version 4.0.1。

%title插图%num
4.删除StreamingAssets的文件,使得数量不要超过250个。

%title插图%num
折腾了一天,下载JDK,下载AndroidSDK,下载Gradle版本,然后打包测试,发现前3个方案根本没有用,都快要*望了,然后试*后一个方案,成功解决了。为了测试苹果有没有这个问题,也打了个包测试下,苹果没有问题,估计这是Gradle的bug了。
但是因为首包资源需要放在StreamingAssets中,所以这个问题还需要解决,解决方案就是打成一个zip包,解压就行,但因为有lua代码,大佬说会有mono内存增加的问题,需要把lua的ab包拷贝到持久化目录中,但因为Unity中是只读的,所以需要在java处理。刚好之前写了个Utility的jar包获取CPU信息,继续在上面加个接口。参考了下这篇大佬的文章https://segmentfault.com/a/1190000004849884。

Java这边的代码是这样的,只是返回一个是否成功的bool值:

public boolean CopyFile(Object object, String oldPath, String newPath) {
Log.v(“ZP”, “1111111”);
AssetManager assetManager = (AssetManager)object;
String[] filenames = null;
InputStream input=null;
FileOutputStream output = null;
boolean bIsNull = assetManager == null;
if(bIsNull)
Log.v(“ZP”, “Is Null”);
else
Log.v(“ZP”, “Is Not Null”);
try {
filenames = assetManager.list(oldPath);
Log.v(“ZP”, “filenames.length: ” + filenames.length);
if(filenames.length <= 0)
{
Log.v(“ZP”, “222222”);
File newFlie = new File(newPath);
if(!newFlie.exists()){
newFlie.createNewFile();
}
else
{
return false;
}
//将内容写入到文件中
input=assetManager.open(oldPath);
output= new FileOutputStream(newFlie);
byte[] buffer = new byte[1024];
int len = 0;
while((len=input.read(buffer))!=-1){
output.write(buffer, 0, len);
}
output.flush();
Log.v(“ZP”, “33333333”);
return true;
}
}catch(IOException e)
{
e.printStackTrace();
}finally{
try {
if(output != null)
{
output.close();
output = null;
}
if(input != null)
{
input.close();
input=null;
}
// if(assetManager != null)
// {
// assetManager.close();
// assetManager = null;
// }
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}

C#调用的代码是这样的,代码还是蛮清楚的,个人认为。

/// <summary>
/// 调用: AndroidUtility.CopyLuaFile(“test.unity3d”, Application.persistentDataPath + “/test.unity3d”);
/// </summary>
/// <param name=”oldPath”></param>
/// <param name=”newPath”></param>
/// <returns></returns>
public static bool CopyLuaFile(string oldPath, string newPath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
var activity = new AndroidJavaClass(“com.unity3d.player.UnityPlayer”).GetStatic<AndroidJavaObject>(“currentActivity”);
var assetManager = activity.Call<AndroidJavaObject>(“getAssets”);
var javaClass = new AndroidJavaClass(“com.zp.utility.api”);
var javaObject = javaClass.CallStatic<AndroidJavaObject>(“instance”);
return javaObject.Call<bool>(“CopyFile”, assetManager, oldPath, newPath);
#endif
return false;
}

Android自动化构建之Ant多渠道打包实践

前言
Ant是历史比较悠久的一个自动化构建工具,Android开发者可以通过它来实现自动化构建,也可以实现多渠道打包,关于apk打包的方式一般有Ant、Python、Gradle三种,这三种打包方式都各自有优点和缺点,本篇博文先给大家介绍如何使用Ant来实现自动构建和多渠道发布。

开发环境
Window7
Ant
jdk
android sdk
mac系统下所需要的运行环境也是类似的,我们都需要配置Ant、jdk、sdk的环境变量,我们可以看一下window下是环境变量配了些什么:
ANT_HOME : D:\android\apache-ant-1.9.4
JAVA_HOME : C:\Program Files\Java\jdk1.6.0_45
ANDROID_SDK_HOME : D:\android\adt-bundle-windows-x86_64-20140321\sdk
PATH: %JAVA_HOME%/bin;%ANDROID_SDK_HOME%\platform-tools;%ANDROID_SDK_HOME%\tools;%ANT_HOME%\bin;
CLASSPATH : .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\tools.jar

以上环境变量配好之后,你才可以进入下一步,不会配?回家吧,开发不适合你。

先说APK构建过程
下面来简单描述下apk构建的过程:
1. 使用aapt生成R.java类文件
2. 使用android SDK提供的aidl.exe把.aidl转成Java文件
3. 使用javac命令编译.java类文件生成class文件
4. 使用android SDK提供的dx.bat命令行脚本生成classes.dex文件
5. 使用android SDK提供的aapt.exe生成资源包文件
6. 使用apkBuilder.bat生成未签名的apk安装文件
7. 使用jdk的jarsigner对未签名的包进行apk签名
8. 使用Zipalign工具对apk进行优化

我们从上面的描述可以知道apk具体的步骤和使用到的工具,对应的工具在sdk中都可以找到,自己去翻翻吧,但你会发现新的sdk版本,aapt被放到了build-tools目录下,apkBuilder.bat文件在tools目录找不到了,你可以去网上去下一个,然后放到tools目录下。为了让大家更清楚apk构建的过程,放上官方的一张图:

%title插图%num

有了这张图,相信大家已经清楚了apk到底是如何生成的吧,不多说了。

构建命令详解
aapt命令生成R.java文件
示例命令:

aapt package -m -J <R.java文件夹> -S <res路径> -I <android.jar路径> -M<AndroidManifest.xml路径>

命令解释:

-f 如果编译出来的文件已经存在,强制覆盖
-m 使生成的包的目录存放在-J参数指定的目录
-J 指定生成的R.java 的输出目录
-S res文件夹路径
-A assert文件夹路径
-I 某个版本平台的android.jar的路径
-F 具体指定APK文件的输出

aidl命令生成.aidl文件
示例命令:

aidl -p<framework.aidl路径> -I<src路径> -o<目标文件目录> .aidl文件

注意:命令和路径是没有空格的。

javac命令生成.class文件
示例命令:

javac -d destdir srcFile

参数解释:
-d 指定存放类的文件夹
-bootclasspath 覆盖引导类文件的位置
-encoding 指定源文件使用的编码
-sourcepath 指定查找输入源文件位置

dx命令生成classes.dex文件
示例命令:
dx –dex –output classes.dex bin/classes/ libs/

命令解释:将bin/classes下的class文件和libs下的jar文件编译成classes.dex文件

aapt生成资源包文件resources.ap_
命令示例:

aapt package -m -J <R.java文件夹> -S <res路径> -I <android.jar路径> -A <asset路径> -M<AndroidManifest.xml路径> -F <resources.ap_文件路径>

apkbuilder.bat已经过时了,使用以下方法
示例命令:

java -cp <sdklib.jar路径> com.android.sdklib.build.ApkBuilderMain <未签名.apk> -v -u -z bin\resources.ap_ -f bin\classes.dex -rf src

通过jarsigner来生成
示例命令:
jarsigner -verbose -keystore <keystore路径> -signedjar -<输出签名apk路径> <未签名apk路径> <keystore别名>

*后一步使用zipalign工具进行apk对齐优化
示例命令:

zipalign [-f] [-v] <alignment> infile.apk outfile.apk

上面的8个步骤就是实现apk构建的过程,都是通过命令来一步一步实现,要注意每一步生成的东西。

小结
本篇博文主要给大家介绍了Android中apk构建的过程,也详细的讲解了每一步具体的命令操作,由于不想一篇把所有东西堆在一起,我将会在下一篇来具体使用Ant脚本实现自动化构建和多渠道打包,大家可以继续关注。

 

Android多模块构建合并aar解决方案

前段时间,我在实现gradle多模块构建遇到一个问题,以前我们基本上是以jar包形式让开发者集成到工程中使用,但自从Android Studio中有了多module的概念,而我们的SDK也是分了多个模块进行构建的,但我们这里有个问题就是模块之间是相互关联的,不能针对每个模块单独打包,而每个module都会生成对应的aar,但并不会把依赖的module代码打进去,别问我为什么知道,你将aar后缀改为zip,然后反编译classes.jar就可以看到。所以我们这边就有了合并aar这样的一个需求,下面就告诉大家怎么来实现。

android-fat-aar

当时我遇到这个问题,就去github搜了一下,已经有人将合并aar的脚本开源出来了,开源地址如下:

https://github.com/adwiv/android-fat-aar

什么是aar?

什么是aar?它跟jar包有什么区别?它该怎么样使用?相信大家一定会有这些疑问。首先aar是针对Android Library而言的,你可以理解为IDE针对Android Library的打包,一个aar包含什么东西?
它的文件后缀名是.aar,它本身是一个zip文件,强制包含以下文件:

/AndroidManifest.xml
/classes.jar
/res/
/R.txt

另外,AAR文件可以包括以下可选条目中的一个或多个:

/assets/
/libs/name.jar
/jni/abi_name/name.so (where abi_name is one of the Android supported ABIs)
/proguard.txt
/lint.jar

具体看到这里看如何创建一个Android Library:
https://developer.android.com/studio/projects/android-library.html#aar-contents

jar包跟aar包有什么区别?
jar:只包含了class文件与清单文件,不包含资源文件,如图片等所有res中的文件。
aar:包含所有资源,class以及res资源文件全部包含。

如果你只是简单实用一些类库,你可以直接使用*.jar文件,而如果你想既想使用类库,又想实用资源,那么你就可以创建一个Android Library,使用它生成的*.aar文件。

jar文件的使用方式我们应该比较熟悉了,将它复制到工程的libs目录下,然后在gradle中添加以下脚本:

dependencies {
compile fileTree(include: [‘*.jar’], dir:’libs’)
}

aar文件使用同样需要复制到libs目录下,并按照以下方式集成:

repositories {
flatDir {
dirs’libs’
}
}

dependencies {
compile(name:’your aar’, ext:’aar’)

多模块构建合并aar

这个是本文的重点,我们可以再每个module下的build/outputs/aar下找到编译生成的*.aar文件。

步骤1:
将gradle文件’fat-aar.gradle’到你的项目目录,然后apply:

apply from: ‘fat-aar.gradle’

步骤2:定义嵌入的依赖关系
你需要修改你以前依赖项,并将compile更改为embedded,作为你想要合并的aar。使用例子如下:

%title插图%num

通过以上的方式你可以将多个module生成的aar合成一个,大家可以新建一个demo工程来测试下

%title插图%num

android 开发只能用 gradle 吗?

个人总结 gradle 缺点:

1.api 未稳定,不同版本不兼容。
2.下载软件包用 hash 作目录,难以分辨,难以清理。不同版本的 gradle 竟然各自重复维护相同版本的软件包。
3.同样是从那三个仓库下软件包,为什么 gradle 就比 maven 慢这么多(来自 java 后端项目开发时的体验对比)?
4.出错提示太简陋,无法定位错误原因。
5.脚本编写没有约束,也就是太灵活,不利于协作。
6.耗内存,甚至超过 idea 占用的内存。这个是 gradle 特性决定的。为了节省构建时间,gradle 会在敲代码期间一直在后台对待构建内容进行缓存。所以能在构建时快于 maven (但我的实际体验感觉也没快多少)。maven 平时是不运行的。而且我不知道为啥 gradle 要另起个进程,而不是像 maven 那样内置在 idea 里通过 api 调用。难道是因为 gradle 是 groovy 写的所以没法内置到 idea 里?要知道两个 jvm 进程可不同于两个 native 进程,相当于跑在两个虚拟机里,需要两倍的虚拟层和运行时的资源开销。而如果把守护进程关掉,那么在构建时,gradle 会巨慢无比。

旧版只能用 groovy 写脚本也算个缺点,这个语言太灵活。本身 gradle 对脚本编写没有约束就很灵活了,这样一来一个构建脚本在项目复杂之后都很有可能变得难以阅读。

很久以前 idea 还能用 maven,不知道现在还能不能用?
%title插图%num
• 2021-03-03 20:41:36 +08:00
fatelight 1
fatelight 26 天前 ❤️ 1
gradle 慢是你的网络问题==
CrazyBoyFeng 2
CrazyBoyFeng 26 天前
@fatelight 第 3 条,同一个项目用 maven 和 gradle 对比得出的结论。没个参照对象怎么敢说慢呢?

另外,“网络不行”、“配置不行”这类吐槽其实挺无用的。我是觉得它不好用,又不是用不了必须换网加配置。说着轻巧,难道不要成本吗,而且能带来增益多少可难说。
lionseun 3
lionseun 26 天前 via Android
maven 扩展性不如 gradle,ps:关闭 gradle Damon 不是正常操作吗
winterbells 4
winterbells 26 天前 ❤️ 1
lz 是来找认同的,不是要你们解释反驳
CrazyBoyFeng 5
CrazyBoyFeng 26 天前 via Android
@winterbells 我是来找替代解决方案的。我不需要寻求认同。
HongJay 6
HongJay 26 天前
网络不行就是不行啊。。。只能说明你不懂啥叫谷歌
pursuer 7
pursuer 26 天前
github 上可以找到 android-maven-plugin,不过我没用过。
hantsy 8
hantsy 26 天前 ❤️ 3
Maven 也有第三方维护的 Plugin (不止一个)。

https://www.vogella.com/tutorials/AndroidBuildMaven/article.html

Google 可以比较喜欢自定义的,相对比较灵活,之前很多项目如 Gwt 等用的是 Ant,现在主要 Gradle 。

国内的 Gradle 体验比 Maven 真的差太多,特别 Gradle 配置的兼容性坑爹(一年一次的大版本升级,对前面版本没法兼容,而 Maven 3 现在还可以运行十几前的 Maven 2 程序),Puglin 的名称时常改动,很多一两年内的 Plugin,在新 Gradle 版本要么找不到,要么不能运行。

Gradle Wrapper 下载 Dist 和 Gradle 的 Plugin 不支持 Maven Repo 那样 Mirror 配置, 不能从 Maven Repo 更新这是*扯蛋,国内速度慢得要命。Gradle 特别依赖的 Jcenter 国内我这里是不能访问的,本身也是龟速,而且 Jcenter 马上要关闭了,到时又是一堆 Gradle 项目 Breaking 。

即使从 Maven Repos (不管远程还是本地)下载了依赖,Gradle 自己又建立一套本地依赖库,而且 Folder 名全部用 Sha 命名。

如果用 Gradlew 来 Build 项目,它会尝试下载一个 Dist 到个人目录下(如果不存在),几个版本下来,这样硬盘很多就被掉几十 G 。

Gradle 运行过程中,Gradle Damon 一直跑后台,太吃内存了。另外在个人目录,Gradle 为配合 Damon,生成堆积如山的 Cache 文件。

我很少用 Gradle,个人目录下 Gradle 乱七八糟的文件多达 40G 。这比 5 年来下载的 Maven Deps 还多一倍。如果我是日常用 Gradle,5 年下来估计 500G 硬盘都是不够用的。
CrazyBoyFeng 9
CrazyBoyFeng 26 天前 via Android
@pursuer @hantsy 感谢分享,我也搜到了这个 plugin,不过它似乎是弃坑状态,三年未更新。我现在正尝试在 idea 上运行它。
darktiny 10
darktiny 26 天前 ❤️ 1
愿意折腾,就 Buck 吧

hantsy 11
hantsy 26 天前
@CrazyBoyFeng https://github.com/simpligility/android-maven-plugin
https://groups.google.com/g/maven-android-developers/c/QzFg158CMww/m/Z3G3ZveHIKoJ
Team 12
Team 26 天前 ❤️ 2
在这个网站上讨论一些比较严肃的问题,要注意经常屏蔽

有很大一部分人的回答,每次就几个字儿*多不超过一句话

而且讨论的问题往往也不是什么严肃的问题

所以他们的回答出现在这里基本上就是没用的,甚至还有害
fatelight 13
fatelight 25 天前
@CrazyBoyFeng 我试过,完全清理本地缓存的话,maven 和 gradle 速度下载速度没啥差距。gradle 比 maven 墙的厉害,你不代理可能下载都能出错。所以我说慢,可能是你网络问题。自己抓包看看下载包的速度就知道了。或者项目配置 gradle 镜像源或者贵司自己有专门同步的库
fatelight 14
fatelight 25 天前
@Team 对有害,请 block 我,你的非常有用
zhanlanhuizhang 15
zhanlanhuizhang 25 天前 ❤️ 1
可以使用 maven
参考项目: https://github.com/zxing/zxing
还可以使用:bazel 。
CrazyBoyFeng 16
CrazyBoyFeng 25 天前
@darktiny 感谢分享。简单了解了一下 buck,挺好的东西,已经出现好几年了,我竟不知道。
我试用了一下 buck,是比 gradle 要快,内存消耗也不多,不会卡住 idea 。不过我只是测试一下首次全量构建,没有连续使用,不知道增量的效果怎么样。害怕 daemon 随着 repo 长大会不会像 gradle 那样反客为主。不过全量构建这么快,如果不是巨大的应用,感觉平常应该不开 daemon 也可以。
脚本格式是 python 语法,不过 buck 本身是 java 写的,运行在 jvm 上。python 语法简单易读,懂的人也多。
CrazyBoyFeng 17
CrazyBoyFeng 25 天前
@zhanlanhuizhang 感谢分享。阅读 pom.xml 得知,zxing 正是使用了楼上所说的 android-maven-plugin 。不过 zxing 也是三年没更新了,我都怀疑它是 eclipse 写的遗留代码,那个目录结构也像 eclipse 。eclipse 上现在没有官方 android 支持了,kotlin 支持也不好。用第三方插件怕踩坑。
bazel 感觉跟 buck 很像。而且 idea 插件还在更新。buck 的 idea 插件两年没动了。
elonmask 18
elonmask 25 天前 via Android
放弃安卓吧,搞 AI 去
GM 19
GM 25 天前 ❤️ 1
身处墙外,装了 10000000Mbps 宽带,用着 128G 内存+9900K+10T SSD 的开发机的某些人说:
我这没问题,你网络不好不要怪 gradle 不行!你机器烂不要怪 gradle 卡!你投资生产工具的钱都不愿意花,还做什么码农?

说完一转身,云淡风轻,不带走一丝云彩,深藏功与名。

留下台下那群拿着平均线工资、用着雇主给的垃圾开发机的码畜们一脸懵逼。
newee 20
newee 25 天前
实际上只是因为网络的问题,使用的时候会出现半天下不动的情况。在海外其实不会有这种情况,几十 M,1 分钟不要就下载完了。

所以在这种网络下能正常使用,也是开发的基本操作。

另外 gradle 还是有一定优势的,只是当前的应用场景没用到这些优势,体会不到。才会简单的把这个当成一个导包工具。其实还是有一些优点的,要是没啥优点,还不早就被淘汰了。

当然很多东西,有一些优劣,比如说火狐浏览器比 chrome 更占内存,android studio 比 vs code 更占内存。但是挡不住大势,大势是什么。现在可能用着 4 核 4 线程的电脑,16G 内存。但是总有一天要升级 10 核,64G 内存,是不是?

我刚做开发的时候,天天想着给哪些低端机做适配,想方设法去改善性能。然而几年之后低端机一样还是没有人用了。
a719031256 21
a719031256 25 天前
@fatelight 国内 gradle 下载都慢,我试过公司的专线网络也慢,家里的百兆光纤也慢,以前尝试过自己弄个安卓 app 来弄,结果卡在 gradle 上了,还有一个就是 gradle 的版本问题,好像小版本不同的 gradle 兼容性也有问题,我网上下的 app 源码原本想改改来用,结果就比源码版本高两个小版本号就报错,感觉 gradle 就是谷歌强推出来的,并不好用但强制你用
janus77 22
janus77 25 天前
1 日常开发不需要做兼容,你项目制定版本号就行了
2 同上,如果你的版本号不变动,自然在清理的时候也就不费力
3 网络问题,maven 一样很多人换 aliyun 镜像
4 新系统这方面确实欠缺,主要靠经验累积和自己搜索解决。开发久了就好了
5 java 写久了不灵活也是罪?脚本语言不灵活凭啥被用于脚本啊
6 占用大这个也是新系统一直以来的缺陷,我没法回答
fatelight 23
fatelight 25 天前
@a719031256 我都挂代理,走中转专线
coolesting 24
coolesting 25 天前 via Android
除了吃内存之外,没感觉不太好的地方。
否则也不会有 kill gradle 的插件出现。
Jirajine 25
Jirajine 25 天前 via Android
不要用 gradlew,构建脚本用 kts,基本还可以。
CrazyBoyFeng 26
CrazyBoyFeng 25 天前
我试了一下 bazel,目前感觉良好。idea 里的插件也好用。google 自己做的工具也不错啊,为什么不推广呢?
我会尝试用久一点再分享我的体验。
不过,需要用到第三方 gradle 插件的项目,目前还是只能使用(指定版本的) gradle 。
systemcall 27
systemcall 25 天前 via Android
感觉 gradle 确实很垃圾,可以和 keil 礦 ision 并列的那种
一个浪费硬盘而且占的是家目录、需要强大的梯子、电脑配置要求高,一个浪费生命还时不时崩溃
怀念以前拿 vb6.0 写程序的日子,那个时候就没这么多破事,用 vs 写安卓也没这么多破事,起码安装的时候会告诉你会吃掉多少磁盘空间、方便卸载掉
HangoX 28
HangoX 25 天前 ❤️ 1
楼主说的 5 个问题对于熟悉 gradle 的人都不是问题。第 6 个是楼主自己勾选了编辑即构建,idea 可以关闭,我重来不开那个。deamon 不是这样的意思,deamon 是下次构建的时候可以重新使用虚拟机和内存达到更快的目的,不喜欢关闭即可
楼主没有对比相同项目下 maven 和 gradle 的构建时间对比,gradle 是比 maven 快很多的,官方就有对比 https://gradle.org/gradle-vs-maven-performance/ ,毕竟那么多缓存摆在那里,想不快都难。磁盘占用问题,这个东西加磁盘就能加速的事情为什么不干
hantsy 29
hantsy 25 天前
@newee 海外当然不会有问题。 在国内你用 Gradlew 编译一下,下一个 Dist 几 K 到十几 K,而且经常断。项目依赖可以借 Maven Mirror 。这东西还有它的插件系统连 Mirror 都没有,必须从官方下载。

国内的 5G,如果在开发过程的检验也就是 2G 速度而已。
chenjiajia9411 30
chenjiajia9411 24 天前
不用 Gradle 完全可以啊,自己下好配好依赖之后用 build-tools 自己编译就行了。
Anonywp 31
Anonywp 23 天前
https://maven.aliyun.com/mvn/guide
yike47 32
yike47 23 天前
俺就没有感同身受了。公司配置 32G 运存+固态。自己的是 Mac 高配。 从来都是一把梭,秒开……….
imzcg2 33
imzcg2 22 天前
as 绑定 gradle,换个好电脑和代理就好了把
systemcall 34
systemcall 21 天前
你可以换成 Harmony Studio,之后等待自主研发的分布式 5G 可形式化验证的国产软件取代 gradle。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速