You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

构建Android FTC机器人自定义库时java.lang.NullPointerException问题求助

自定义FTC机器人库Gradle构建NPE错误排查与解决

开发自定义FTC机器人库以简化开发流程时,尝试发布至MavenCentral、MavenLocal及GitHub Pages均出现相同错误;将库作为模块加入RobotController Android Studio项目后,问题仍存在。错误关联Gradle任务ExtDexDebugAndroidTest及publish.gradle生成的jar,核心报错为java.lang.NullPointerException。


项目配置文件

build.gradle

plugins {
    id 'com.android.library'
}

android {
    namespace 'org.overture.ftc.overftclib'
    compileSdk 34

    defaultConfig {
        minSdkVersion 16

        aarMetadata{
            minCompileSdk = 29
        }

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.7.0'
    implementation 'com.google.android.material:material:1.10.0'
    implementation project(':FtcRobotController')
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

publish.gradle

apply plugin: 'maven-publish'

ext.licenseFile = files("$rootDir/LICENSE.txt")

def pubVersion = '0.0.1'

def outputsFolder = file("$buildDir/outputs")

def versionFile = file("$outputsFolder/version.txt")

task outputVersions() {
    description = 'Prints the version of the library to a file'
    group = 'Build'
    outputs.files(versionFile)

    doFirst {
        buildDir.mkdir()
        outputsFolder.mkdir()
    }

    doLast {
        versionFile.write pubVersion
    }
}

task libraryBuild() {}

build.dependsOn outputVersions

task copyAllOutputs(type: Copy) {
    destinationDir file("$buildDir/allOutputs")
    from versionFile
    dependsOn outputVersions
}

build.dependsOn copyAllOutputs
copyAllOutputs.dependsOn outputVersions

ext.addTaskToCopyAllOutputs = { task ->
    copyAllOutputs.dependsOn task
    copyAllOutputs.inputs.file task.archiveFile
    copyAllOutputs.from task.archiveFile
}

def artifactGroupId = 'com.overture.ftc.lib'
def baseArtifactId = 'OvertureFTCLib'

// Tasks for creating additional artifacts, like sources and Javadoc
task androidSourcesJar(type: Jar) {
    classifier = 'sources'
    from android.sourceSets.main.java.srcDirs
}

task androidJavadocs(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
    classifier = 'javadoc'
    from androidJavadocs.destinationDir
}

build.dependsOn androidSourcesJar
build.dependsOn androidJavadocsJar
addTaskToCopyAllOutputs(androidSourcesJar)
addTaskToCopyAllOutputs(androidJavadocsJar)

libraryBuild.dependsOn build

def releasesRepoUrl = "$buildDir/repos/releases"

publishing {
    publications {
        androidLibrary(MavenPublication) {
            groupId = artifactGroupId
            artifactId = baseArtifactId
            version = pubVersion

            afterEvaluate {
                from components.release
            }

            artifact androidSourcesJar
            artifact androidJavadocsJar
        }
    }

    repositories {
        maven {
            url = releasesRepoUrl
        }
    }
}

task cleanReleaseRepo(type: Delete) {
    delete releasesRepoUrl
}

tasks.matching { it != cleanReleaseRepo }.all { it.dependsOn cleanReleaseRepo }

错误详情

> Task :overftclib:mergeExtDexDebugAndroidTest
AGPBI: {"kind":"error","text":"java.lang.NullPointerException: Cannot invoke \"String.length()\" because \"<parameter1>\" is null","sources":[{"file":"C:\\Users\\santy\\.gradle\\caches\\transforms-3\\9d823f17cc7bfaba9537b6c404b8a19f\\transformed\\appcompat-resources-1.7.0-runtime.jar"}],"tool":"D8"}
AGPBI: {"kind":"error","text":"java.lang.NullPointerException: Cannot invoke \"String.length()\" because \"<parameter1>\" is null","sources":[{"file":"C:\\Users\\santy\\.gradle\\caches\\transforms-3\\6303bfbaba1977f71e281e2c3baabe3f\\transformed\\appcompat-1.7.0-runtime.jar"}],"tool":"D8"}
AGPBI: {"kind":"error","text":"java.lang.NullPointerException","sources":[{"file":"C:\\Users\\santy\\.gradle\\caches\\transforms-3\\6303bfbaba1977f71e281e2c3baabe3f\\transformed\\appcompat-1.7.0-runtime.jar"}],"tool":"D8"}

> Task :overftclib:mergeExtDexDebugAndroidTest FAILED

核心错误栈:

java.lang.NullPointerException: Cannot invoke "String.length()" because "<parameter1>" is null

问题分析与解决方案

问题本质

该NPE是D8编译器处理appcompat依赖包时,遇到空字符串参数触发的异常,常见诱因包括:Gradle/AGP版本与依赖版本不兼容、本地构建缓存损坏、任务依赖逻辑冲突。

分步解决方案

  1. 清理构建缓存
    执行Gradle清理命令并删除本地缓存目录:

    ./gradlew clean build --no-build-cache
    

    手动删除Windows本地缓存路径:C:\Users\santy\.gradle\caches,避免损坏缓存文件干扰构建。

  2. 调整依赖与AGP版本

    • 升级项目根目录build.gradle中的AGP版本至与compileSdk 34兼容的版本(如7.4.2):
      dependencies {
          classpath 'com.android.tools.build:gradle:7.4.2'
      }
      
    • 降低appcompat依赖版本至更稳定的1.6.1,规避高版本与FTC SDK的兼容性冲突:
      implementation 'androidx.appcompat:appcompat:1.6.1'
      
  3. 禁用AndroidTest相关任务
    FTC库核心用于机器人运行,可暂时禁用测试任务避免Dex合并冲突,在库模块build.gradle中添加:

    android {
        // 其他配置保持不变
        tasks.whenTaskAdded { task ->
            if (task.name.contains('AndroidTest')) {
                task.enabled = false
            }
        }
    }
    
  4. 修复publish.gradle任务依赖
    当前配置中cleanReleaseRepo被设为所有任务的依赖,会反复清理仓库干扰jar生成,注释或移除以下代码:

    // tasks.matching { it != cleanReleaseRepo }.all { it.dependsOn cleanReleaseRepo }
    

内容的提问来源于stack exchange,提问作者Santiago Quintana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:48:09