Exception java.lang.NoSuchMethodError: decodeBase64 in Android devices with API < 28

未关闭
#603 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
android, java
领域
mobile-dev

调研方向

从 com.google.api.client.util.Base64.java 和 PemReader 开始,定位 stack trace 到达不兼容的 decodeBase64 调用的位置,然后检查 Apache Commons Codec 依赖项是如何为 Android 解析的。在低于 28 的 API 上使用 Android 语音示例复现,并验证加载凭据时不再抛出 NoSuchMethodError。

由索引模型根据 Issue 内容生成。

描述

type: feature request

Hi,
We have found that the library is throwing an exception in any Android device with and API < 28 (Android 9.0) after version com.google.cloud:google-cloud-speech:0.70.0-beta. The problem is related with this issue. As far as we know, Apache common codec library dependency version is 1.10 in this project, but Android in versions below 9.0 has the same classes in boot classpath, so classes from the version 1.10 will never be loaded. This issue will not be solved in Android, thus we would like to ask for a solution here, removing/replacing the dependency in some way.
Thanks in advance.

Please include as much information as possible:

Environment details
  • OS: Android API < 28
  • Java version:1.8
  • google-cloud-java version(s): from 0.71.0-beta
Steps to reproduce

1. Zip file attached or get Android speech example source code from:
https://github.com/GoogleCloudPlatform/android-docs-samples/tree/master/speech/SpeechRecognitionClient

2. Import app into Android Studio.

3. Modify build-gradle (module app) file to update dependencies in
section dependencies:

 // add these dependencies for the speech client
    implementation 'io.grpc:grpc-okhttp:1.18.0'
    implementation 'com.google.cloud:google-cloud-speech:0.71.0-beta'

4. Build app with Android Studio and run in development mode on Android device below API 28.

Stacktrace
2019-02-21 10:56:28.171 12310-12310/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.google.cloud.examples.speechrecognition, PID: 12310
    java.lang.NoSuchMethodError: No static method decodeBase64(Ljava/lang/String;)[B in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar)
        at com.google.api.client.util.Base64.decodeBase64(Base64.java:101)
        at com.google.api.client.util.PemReader.readNextSection(PemReader.java:106)
        at com.google.api.client.util.PemReader.readFirstSectionAndClose(PemReader.java:135)
        at com.google.auth.oauth2.ServiceAccountCredentials.privateKeyFromPkcs8(ServiceAccountCredentials.java:290)
        at com.google.auth.oauth2.ServiceAccountCredentials.fromPkcs8(ServiceAccountCredentials.java:280)
        at com.google.auth.oauth2.ServiceAccountCredentials.fromJson(ServiceAccountCredentials.java:210)
        at com.google.auth.oauth2.GoogleCredentials.fromStream(GoogleCredentials.java:174)
        at com.google.auth.oauth2.GoogleCredentials.fromStream(GoogleCredentials.java:141)
        at com.google.cloud.examples.speechrecognition.MainActivity$mSpeechClient$2$1$1.getCredentials(MainActivity.kt:69)
        at com.google.cloud.examples.speechrecognition.MainActivity$mSpeechClient$2$1$1.getCredentials(MainActivity.kt:47)
        at com.google.api.gax.rpc.ClientContext.create(ClientContext.java:132)
        at com.google.cloud.speech.v1.stub.GrpcSpeechStub.create(GrpcSpeechStub.java:94)
        at com.google.cloud.speech.v1.stub.SpeechStubSettings.createStub(SpeechStubSettings.java:126)
        at com.google.cloud.speech.v1.SpeechClient.<init>(SpeechClient.java:144)
        at com.google.cloud.speech.v1.SpeechClient.create(SpeechClient.java:126)
        at com.google.cloud.examples.speechrecognition.MainActivity$mSpeechClient$2.invoke(MainActivity.kt:68)
        at com.google.cloud.examples.speechrecognition.MainActivity$mSpeechClient$2.invoke(MainActivity.kt:47)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.google.cloud.examples.speechrecognition.MainActivity.getMSpeechClient(MainActivity.kt)
        at com.google.cloud.examples.speechrecognition.MainActivity.onResume(MainActivity.kt:105)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1270)
        at android.app.Activity.performResume(Activity.java:6830)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3407)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3470)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1528)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6121)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

Code snippet
 private val mSpeechClient by lazy {
        // NOTE: The line below uses an embedded credential (res/raw/sa.json).
        //       You should not package a credential with real application.
        //       Instead, you should get a credential securely from a server.
        applicationContext.resources.openRawResource(R.raw.google_cloud_credentials).use {
            SpeechClient.create(SpeechSettings.newBuilder()
                    .setCredentialsProvider { GoogleCredentials.fromStream(it) }
                    .build())
        }
    }
Any additional information below

Thanks!

主要语言
Java
星标
1.4k
派生
476
平均合并
10 小时 47 分钟
30 天内合并 PR
3

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

googleapis/google-http-java-client 的其他 Issue

查看 googleapis/google-http-java-client 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。