[Android]_[gradle]_[gradlew.bat报错KotlinNullPointerException]
2020-05-10 04:09
2923 查看
场景
- 在构建
Android App
的时候,最常用的构建工具就是gradle
,这个工具使用一种.gradle
的文本进行任务描述. 最常见的就是根据build.gradle
的配置指定使用gradle
的版本。接着根据项目的配置下载所依赖的jar
包并编译.
dependencies { classpath 'com.android.tools.build:gradle:3.6.2' }
- 我对
gradle
还没系统的学习过. 今天在编译google
的例子项目时在项目根目录使用命令行运行gradlew.bat
就报以下错误. 项目都是用的java
代码编写,何来的kotlin
错误?
* What went wrong: A problem occurred configuring project ':app'. > kotlin.KotlinNullPointerException (no error message) * 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
说明
- 注意这个
gradle
是针对android
的构建插件,而android
目前官方推荐使用kotlin
语言开发, 所以gradle
插件需要集成kotlin
包也不奇怪. 我们根据提示运行增加参数gradlew.bat --stacktrace
. 在命令行运行输出了一段比较长的错误, 其中就有KotlinNullPointerException
抛出的源码位置. 可见在文件DataBindingCompilerArguments.kt
的 170 行的createArguments
方法抛出了异常. 而这个 170 行就是sdkDir = globalScope.sdkComponents.getSdkFolder()!!,
获取SDK
目录时抛出的异常。很明显了,就是获取不到Android SDK
目录.
Caused by: kotlin.KotlinNullPointerException at com.android.build.gradle.internal.tasks.databinding.DataBindingCompilerArguments$Companio n.createArguments(DataBindingCompilerArguments.kt:170)
-
那么设置
Android SDK
我所知道的有3种方法. [ol] 在我的电脑右键属性->高级->环境变量->用户变量增加ANDROID_HOME
作为变量名,E:\software\Android\sdk
你自己的Android SDK
安装目录. 这个变量值在所有新建的命令行有效. - 在当前命令行输出回车
set ANDROID_HOME=E:\software\Android\sdk
,那么这个变量值在当前的命令行有效. - 在当前的项目目录增加一个
local.properties
的文本文件,增加文本值sdk.dir=E\:\\software\\Android\\sdk
即可.
设置完之后这个编译步骤就会成功,当然剩下的下载
jar包可能由于网络不通造成下载失败就是另外的问题了。
至于这个文件
DataBindingCompilerArguments.kt源码只能通过
bing是搜不到的. 至于这个类所在的包
com.android.build.gradle.internal.tasks.databinding和它所在的
jar在
gradle下载的包
gradle-3.6.2.jar里, 当然根据依赖的
gradle插件版本判断,我这里是
com.android.tools.build:gradle:3.6.2. 所以在
3.6.2目录下.
C:\Users\用户名\.gradle\caches\modules-2\files-2.1\com.android.tools.build\gradle\3.6.2\a5e817cf4833326b12f3e599f97486a04fe62756\gradle-3.6.2.jar
顺便说一下,
gradle下载的第三方
jar,包括
gradle的
android插件包是在以下目录里:
C:\Users\用户名\.gradle\caches\modules-2\files-2.1
而安装的
gradle,注意不是插件包, 是在以下目录:
C:\Users\用户名\.gradle\wrapper\dists
- 我们来看看这个项目的
.gitigore
忽略设置, 就包含了当前项目的local.properties
文件,所以这个项目里这个文件的是提交不了的.
*.iml .idea .gradle /local.properties .DS_Store build/ /captures .externalNativeBuild
源码参考
DataBindingCompilerArguments.kt
/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.build.gradle.internal.tasks.databinding import android.databinding.tool.CompilerArguments import com.android.build.gradle.internal.scope.InternalArtifactType import com.android.build.gradle.internal.scope.InternalArtifactType.DATA_BINDING_BASE_CLASS_LOG_ARTIFACT import com.android.build.gradle.internal.scope.InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS import com.android.build.gradle.internal.scope.InternalArtifactType.DATA_BINDING_LAYOUT_INFO_TYPE_MERGE import com.android.build.gradle.internal.scope.InternalArtifactType.DATA_BINDING_LAYOUT_INFO_TYPE_PACKAGE import com.android.build.gradle.internal.scope.InternalArtifactType.FEATURE_DATA_BINDING_BASE_FEATURE_INFO import com.android.build.gradle.internal.scope.InternalArtifactType.FEATURE_DATA_BINDING_FEATURE_INFO import com.android.build.gradle.internal.scope.VariantScope import com.android.build.gradle.options.BooleanOption import org.gradle.api.file.Directory import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.process.CommandLineArgumentProvider import java.io.File /** * Arguments passed to data binding. This class mimics the [CompilerArguments] class except that it * also implements [CommandLineArgumentProvider] for input/output annotations. */ @Suppress("MemberVisibilityCanBePrivate") class DataBindingCompilerArguments constructor( @get:Input val incremental: Boolean, @get:Input val artifactType: CompilerArguments.Type, // Use module package provider so that we can delay resolving the module package until execution // time (for performance). The resolved module package is set as @Input (see getModulePackage() // below), but the provider itself should be set as @Internal. private val modulePackageProvider: () -> String, @get:Input val minApi: Int, // We can't set the sdkDir as an @InputDirectory because it is too large to compute a hash. We // can't set it as an @Input either because it would break cache relocatability. Therefore, we // annotate it with @Internal, expecting that the directory's contents should be stable and this // won't affect correctness. @get:Internal val sdkDir: File, @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val dependencyArtifactsDir: Provider<Directory>, @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val layoutInfoDir: Provider<Directory>, @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val classLogDir: Provider<Directory>, @get:Optional @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val baseFeatureInfoDir: Provider<Directory>, @get:Optional @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val featureInfoDir: Provider<Directory>, @get:Optional @get:OutputDirectory val aarOutDir: Provider<Directory>, @get:Optional @get:OutputFile val exportClassListOutFile: File?, @get:Input val enableDebugLogs: Boolean, // We don't set this as an @Input because: (1) it doesn't affect the results of data binding // processing, and (2) its value is changed between an Android Studio build and a command line // build; by not setting it as @Input, we allow the users to get incremental/UP-TO-DATE builds // when switching between the two modes (see https://issuetracker.google.com/80555723). @get:Internal val printEncodedErrorLogs: Boolean, @get:Input val isTestVariant: Boolean, @get:Input val isEnabledForTests: Boolean, @get:Input val isEnableV2: Boolean ) : CommandLineArgumentProvider { @Input fun getModulePackage() = modulePackageProvider() override fun asArguments(): Iterable<String> { val arguments = CompilerArguments( incremental = incremental, artifactType = artifactType, modulePackage = getModulePackage(), minApi = minApi, sdkDir = sdkDir, dependencyArtifactsDir = dependencyArtifactsDir.get().asFile, layoutInfoDir = layoutInfoDir.get().asFile, classLogDir = classLogDir.get().asFile, baseFeatureInfoDir = baseFeatureInfoDir.orNull?.asFile, featureInfoDir = featureInfoDir.orNull?.asFile, aarOutDir = aarOutDir.orNull?.asFile, exportClassListOutFile = exportClassListOutFile, enableDebugLogs = enableDebugLogs, printEncodedErrorLogs = printEncodedErrorLogs, isTestVariant = isTestVariant, isEnabledForTests = isEnabledForTests, isEnableV2 = isEnableV2 ).toMap() // Don't need to sort the returned list as the order shouldn't matter to Gradle. // Also don't need to escape the key and value strings as they will be passed as-is to // the Java compiler. return arguments.map { entry -> "-A${entry.key}=${entry.value}" } } companion object { @JvmStatic fun createArguments( variantScope: VariantScope, enableDebugLogs: Boolean, printEncodedErrorLogs: Boolean ): DataBindingCompilerArguments { val globalScope = variantScope.globalScope val variantData = variantScope.variantData val variantConfig = variantScope.variantConfiguration val artifacts = variantScope.artifacts return DataBindingCompilerArguments( incremental = globalScope.projectOptions .get(BooleanOption.ENABLE_INCREMENTAL_DATA_BINDING), artifactType = getModuleType(variantScope), modulePackageProvider = { variantConfig.originalApplicationId }, minApi = variantConfig.minSdkVersion.apiLevel, sdkDir = globalScope.sdkComponents.getSdkFolder()!!, dependencyArtifactsDir = artifacts.getFinalProduct(DATA_BINDING_DEPENDENCY_ARTIFACTS), layoutInfoDir = artifacts.getFinalProduct(getLayoutInfoArtifactType(variantScope)), classLogDir = artifacts.getFinalProduct(DATA_BINDING_BASE_CLASS_LOG_ARTIFACT), baseFeatureInfoDir = artifacts.getFinalProduct( FEATURE_DATA_BINDING_BASE_FEATURE_INFO ), featureInfoDir = artifacts.getFinalProduct(FEATURE_DATA_BINDING_FEATURE_INFO), aarOutDir = artifacts.getFinalProduct(InternalArtifactType.DATA_BINDING_ARTIFACT), exportClassListOutFile = variantScope.generatedClassListOutputFileForDataBinding .takeIf { variantData.type.isExportDataBindingClassList }, enableDebugLogs = enableDebugLogs, printEncodedErrorLogs = printEncodedErrorLogs, isTestVariant = variantData.type.isTestComponent, isEnabledForTests = globalScope.extension.dataBinding.isEnabledForTests, isEnableV2 = true ) } /** * Returns the module type of a variant. If it is a testing variant, return the module type * of the tested variant. */ @JvmStatic fun getModuleType(variantScope: VariantScope): CompilerArguments.Type { val variantData = if (variantScope.variantData.type.isTestComponent) { variantScope.testedVariantData!! } else { variantScope.variantData } return if (variantData.type.isAar) { CompilerArguments.Type.LIBRARY } else { if (variantData.type.isBaseModule) { CompilerArguments.Type.APPLICATION } else { CompilerArguments.Type.FEATURE } } } /** * Returns the appropriate artifact type of the layout info directory so that it does not * trigger unnecessary computations (see bug 133092984 and 110412851). */ @JvmStatic fun getLayoutInfoArtifactType(variantScope: VariantScope): InternalArtifactType<Directory> { return if (variantScope.variantData.type.isAar) { DATA_BINDING_LAYOUT_INFO_TYPE_PACKAGE } else { DATA_BINDING_LAYOUT_INFO_TYPE_MERGE } } } }
参考
DataBindingCompilerArguments.kt
kotlin.KotlinNullPointerException (no error message) while building APK using Jenkins
相关文章推荐
- [Android--Tool]Gradle sync started: NullPointerException: null
- Android Gradle Build NullPointerException解决方案
- Android异常 NullPointerException: Attempt to invoke virtual method int java.lang.Integer.intValue()
- android 中碰到:java.lang.NullPointerException状况
- Android布局文件使用<include>标签出现NullPointerException问题
- Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View andro
- Android中,在onAnimationEnd方法中调用 viewgroup.removeview,报 nullpointerexception异常的解决方法
- Android NullPointerException解决方法
- Android Switch 控件 空指针异常 NullPointerException
- Android 界面设计 java.lang.NullPointerException 异常的解决方法
- Android Custom View NullPointerException
- Android 发送短信 抛出Caused by: java.lang.NullPointerException 09-18 15:11:00.905: E/AndroidRuntime(10159)
- android setImage nullPointerException错误
- android在fragment中实现onTouchEvent办法出现的java.lang.NullPointerException
- Android NullPointerException at android.text.BoringLayout.isBoring
- android开发之NullPointerException
- Android编译报Errors running builder 'Android Pre Compiler' on project 'XXX' java.lang.NullPointerException
- 使用Eclipse开发Android出现java.lang.NullPointerException错误的解决方法
- Android NullPointerException FragmentHostCallback.getHandler()
- Android N 指纹识别 NullPointerException: Attempt toFragment.mNextAnim 的错误