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

Kotlin项目Gradle配置Java版本后仍遇NoSuchMethodError问题排查

问题:Android Kotlin项目中DataInputStream.readAllBytes()抛出NoSuchMethodError

问题代码

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun startStreaming(setImage: (ByteArray) -> Unit) {
    scope.launch {
        while (true) {
            try {
                // screenStream is an object of DataInputStream class
                val jpegImageByteArray = screenStream!!.readAllBytes() //---error-here
                withContext(Dispatchers.Main) { setImage(jpegImageByteArray) }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            Thread.sleep(1000)
        }
    }
}

报错信息

FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.example.g_stream, PID: 19524
java.lang.NoSuchMethodError: No virtual method readAllBytes()[B in class Ljava/io/DataInputStream; or its super classes (declaration of 'java.io.DataInputStream' appears in /system/framework/core-oj.jar)
    at com.example.g_stream.viewmodel.StreamViewModel$startStreaming$1.invokeSuspend(StreamViewModel.kt:119)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
    at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
    Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a113203, Dispatchers.IO]

当前Gradle配置

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'androidx.navigation.safeargs.kotlin'
}

android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.g_stream"
        minSdk 26
        targetSdk 33
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_12 //---see-here
        targetCompatibility JavaVersion.VERSION_12 //---see-here
    }
    kotlinOptions {
        jvmTarget = '11' //---see-here
    }
    buildFeatures {
        viewBinding true
        dataBinding true
    }
    namespace 'com.example.g_stream'
}

dependencies {
    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.appcompat:appcompat:1.5.1'
    implementation 'com.google.android.material:material:1.6.1' // do not update, keep 1.6.1
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

    //------------------------------------------------------------------------------------navigation
    def nav_version = "2.5.3"
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

    //--------------------------------------------------------------------------------------espresso
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    //---------------------------------------------------------------------------------------barcode
    implementation 'com.google.mlkit:barcode-scanning:17.0.3'

    //---------------------------------------------------------------------------------------CameraX
    def camerax_version = "1.3.0-alpha02"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    implementation "androidx.camera:camera-view:$camerax_version"

    //------------------------------------------------------------------------------------------Gson
    implementation 'com.google.code.gson:gson:2.10'

    //--------------------------------------------------------------------------------------joystick
    implementation 'io.github.controlwear:virtualjoystick:1.10.1'
}

原因分析与解决方案

核心原因

这不是编译版本问题,而是Android运行时API兼容问题:

  • InputStream.readAllBytes()是Java 9引入的方法,但Android系统直到API 33(Android 13,TIRAMISU)才在系统类中实现该方法。
  • 你的minSdk为26,当APP运行在低于API33的设备上时,系统的DataInputStream父类InputStream没有这个方法,因此抛出NoSuchMethodError。
  • 修改编译的Java版本(sourceCompatibility、jvmTarget)仅影响编译阶段,无法改变运行时系统类的方法存在性。

解决方法

推荐两种兼容方案:

方案1:使用AndroidX Core KTX的兼容方法

你的项目已依赖androidx.core:core-ktx,可直接使用库中提供的兼容扩展方法readBytes(),它在所有Android版本上都能正常工作:

val jpegImageByteArray = screenStream!!.readBytes()

同时可去掉@RequiresApi(Build.VERSION_CODES.TIRAMISU)注解,因为该方法无需API33支持。

方案2:自行实现读取全部字节的逻辑

如果不想依赖Core KTX,可手动实现读取逻辑:

// 扩展方法,兼容所有Android版本
fun InputStream.readAllBytesCompat(): ByteArray {
    val buffer = ByteArrayOutputStream()
    val tempBuffer = ByteArray(1024)
    var bytesRead: Int
    while (read(tempBuffer).also { bytesRead = it } != -1) {
        buffer.write(tempBuffer, 0, bytesRead)
    }
    return buffer.toByteArray()
}

// 调用扩展方法
val jpegImageByteArray = screenStream!!.readAllBytesCompat()

方案3:仅在API33+设备使用系统方法(不推荐)

若一定要用系统的readAllBytes(),需在运行时做版本判断,低版本设备使用兼容逻辑:

val jpegImageByteArray = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    screenStream!!.readAllBytes()
} else {
    // 这里用方案2的readAllBytesCompat()或者Core KTX的readBytes()
    screenStream!!.readBytes()
}

内容的提问来源于stack exchange,提问作者Vaishnav Kanhirathingal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:16:11