不用AS生成apk


大家应该经常能碰见这么一个场景,你的项目中有一个需求,要用一些第三方库,然后你就去网上搜,然后就github下了一大堆项目,用as一个个打开,一个个装到你的手机上。
是不是很麻烦??我也经常很烦,就想有没有什么可以直接打包的东西。
下面就介绍一下我不用AS生成apk的流程。本人行文相当口语化,嫌啰嗦的可以直接看最后的总结~

首先我先下载好项目工程,改改版本配置(gradle版本,support版本,sdk版本啥的,都习惯了,不喜欢各种版本都存在我的电脑上。。。。)

然后凭着记忆,在项目根目录启动cmd,输入

gradlew assembleRelease

然后控制台里就出现了一行字。。。

Downloading https://services.gradle.org/distributions/gradle-5.1.1-all.zip

我擦?什么情况? 赶紧使用“复制”终止命令行。(ctrl+c 在cmd中是中断当前操作,真正的复制是,你选中目标字符串,然后华丽丽的轻敲一下回车车键~~)

额。。。我明明下载过gradle。。。为啥又让我重新下载??
因为我改过gradle默认目录,然后去C盘一看,果然里面有下载残留。
嗯。。如何让他使用我下载过的gradle包呢?
经过一番baidu,得知他会检查项目中的/gradle/wrapper/gradle-wrapper.properties文件,下载其中distributionUrl对应的字段。
把之前下载过的zip包,放到/gradle/wrapper/目录下,然后将distributionUrl字段改成zip包的名字gradle-5.1.1-all.zip,先执行一个小命令试一下。

gradlew -v

又出现了下面的文字

Downloading
 file:/D:/develop/AS-workspace/**/gradle/wrapper/gradle-5.1.1-all.zip
 …
 Unzipping
 C:\Users\USER-PC.gradle\wrapper\dists\gradle-5.1.1-all\8mirmttuugrzl5l1j9b5p0az9\gradle-5.1.1-all.zip to C:\Users\USER-PC.gradle\wrapper\dists\gradle-5.1.1-all\8mirmttuugrzl5l1j9b5p0az9

嗯。。。倒是不下载了,解压又解压进了C盘。不行!C盘这么神圣的地方,绝对不允许侵占!!
是不是什么环境变量或者参数中配置了C盘的默认目录??
查了一下项目跟目录的gradlew和gradlew.bat文件,在gradlew.bat文件中发现了这样一行代码

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

看你不像一段正经代码,果断查看此jar!
果然!发现其中有这么一个文件

public class GradleUserHomeLookup
{
  public static final String DEFAULT_GRADLE_USER_HOME = System.getProperty("user.home") + "/.gradle";
  public static final String GRADLE_USER_HOME_PROPERTY_KEY = "gradle.user.home";
  public static final String GRADLE_USER_HOME_ENV_KEY = "GRADLE_USER_HOME";

  public static File gradleUserHome()
  {
    String gradleUserHome;
    if ((gradleUserHome = System.getProperty("gradle.user.home")) != null) {
      return new File(gradleUserHome);
    }
    if ((gradleUserHome = System.getenv("GRADLE_USER_HOME")) != null) {
      return new File(gradleUserHome);
    }
    return new File(DEFAULT_GRADLE_USER_HOME);
  }

}

嘿,让我找到了,大意就是定义gradleUserHome文件,gradle.user.home和GRADLE_USER_HOME我猜应该是定义的环境变量和配置参数,我这两个都没设置过,那就是DEFAULT_GRADLE_USER_HOME = System.getProperty(“user.home”) + “/.gradle”;这个了。人赃俱获!没毛病!

把/gradle/wrapper/gradle-wrapper.properties中的 distributionBase和zipStoreBase改成"…/…/"试试(相对目录,指向项目根目录),再次执行gradlew命令,又出现了以下错误。

Exception in thread “main” java.lang.RuntimeException: Base: …/…/ is unknown
at org.gradle.wrapper.PathAssembler.getBaseDir(PathAssembler.java:97)
at org.gradle.wrapper.PathAssembler.getDistribution(PathAssembler.java:43)
at org.gradle.wrapper.Install.createDist(Install.java:44)
at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:107)
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)

哎嗨,这太熟悉了,一秒钟定位到PathAssembler.java:97

public class PathAssembler    {
...
private File getBaseDir(String base) {
    if (base.equals("GRADLE_USER_HOME"))
      return this.gradleUserHome;
    if (base.equals("PROJECT")) {
      return new File(System.getProperty("user.dir"));
    }
    throw new RuntimeException("Base: " + base + " is unknown");
  }
  ...
}

哦。。原来已经帮我们定义好了一个常量PROJECT,很人性化嘛~
继续将distributionBase和zipStoreBase改成PROJECT,再再次执行gradlew命令。
终于出现了正常的信息,然后执行编译命令

gradlew assembleRelease

啊哈。。电影中黑客的镜头来了,控制台中源源不断地输出信息。。。
等他扑棱完了,一看,what????FAILED???

Starting a Gradle Daemon (subsequent builds will be faster)

FAILURE: Build failed with an exception.

  • What went wrong: A problem occurred configuring project ‘:app’.
    SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project’s
    local properties file at
    ‘D:\develop\AS-workspace**\local.properties’.
  • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
  • Get more help at https://help.gradle.org

BUILD FAILED in 1m 5s

哦。。。原来是太兴奋,忘了配置local.properties。
从别的项目copy一份过来,继续编译。
额。。。又出错了。。

  • What went wrong: Execution failed for task ‘:commonsdk:verifyReleaseResources’.
    1 exception was raised by workers: com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource
    linking failed
    D:\develop\AS-workspace**\build\intermediates\res\merged\release\layout\card_item_picture.xml:11:
    error: attribute cardCornerRadius (aka
    com..:cardCornerRadius) not found.
    D:\develop\AS-workspace*\commonsdk\build\intermediates\res\merged\release\layout\card_item_picture.xml:11:
    error: attribute cardElevation (aka com..:cardElevation)
    not found.
    D:\develop\AS-workspace*
    **\build\intermediates\res\merged\release\layout\card_item_picture.xml:11:
    error: attribute cardPreventCornerOverlap (aka
    com..:cardPreventCornerOverlap) not found. error: failed
    linking file resources.

找不到attribute??这个貌似必须打开as才行了。。。
我打开as后,也没发现这个地方有错误啊。。突然间暼到一行字

22:06 Executing tasks: [:app:assembleDebug]

恍然大悟啊。。。重新执行命令:

gradlew app:assembleRelease

哎嗨。终于成功了!!
等会,怎么是app-release-unsigned.apk???
手动添加signingConfig signingConfigs.release
再次执行命令。。。。。。。。。。。。。。
喜大普奔啊~~

难道release不自带signingConfig signingConfigs.release属性????

最后总结一下:
\gradle\wrapper\gradle-wrapper.properties

# distributionBase=GRADLE_USER_HOME
distributionPath=gradle/wrapper/dists
# zipStoreBase=GRADLE_USER_HOME
zipStorePath=gradle/wrapper/dists

#下面两句 决定下载和解压环境 PROJECT为项目目录
distributionBase=PROJECT
zipStoreBase=PROJECT
# 默认路径是/gradle/wrapper/ 提前将zip包放到对应目录  可以指定其他本地路径
distributionUrl=gradle-5.1.1-all.zip

app(主module)的build.gradle

buildTypes {
        release {
       		//添加签名信息
            signingConfig signingConfigs.debug
        }
    }
  1. 想要不重新下载gradle包,
    1).先将之前的zip放到/gradle/wrapper目录下
    2).然后配置gradle-wrapper.properties中的distributionUrl=gradle-5.1.1-all.zip
  2. 想要不污染C盘
    1) 配置gradle-wrapper.properties
    distributionBase=PROJECT
    zipStoreBase=PROJECT
  3. 如果你的gradle仓库目录没有改,自然也就不会出现上面的问题
  4. 即使你配置了第一步、第二部,C盘依然会生成一些缓存文件,哈哈哈哈哈哈
  5. 记得添加 local.properties
  6. 编译要使用app:assembleRelease,要不然编译的时候可能会找不到module之间的依赖关系。app当然是你主module的名字
  7. 要显式的声明signingConfig signingConfigs.release(可是我记得是默认的啊。。。)
  8. apk的输出依然是build的目录里面。
  9. 网上的东西绝大多数都是抄来抄去,尽信百度则不如无百度。要有自主分辨的能力,也要有知其然知其所以然的意志。