如何解决 Android 中的预期 API 级别为 21+ 但实际为 19 的问题

42

在我的应用程序中,我想从服务器获取数据,为了连接到服务器,我使用了RetrofitOkHttp
但是当运行应用程序时,出现了强制关闭错误。
在Android api 21+中没有错误,但在api 21以下会显示强制关闭错误。

ApiClient类的代码:

class ApiClient constructor(private val deviceUUID: String) {

    private val apiServices: ApiServices

    init {
        //Gson
        val gson = GsonBuilder()
            .setLenient()
            .create()

        //Http log
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level =
            if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

        //Http Builder
        val clientBuilder = OkHttpClient.Builder()
        clientBuilder.interceptors().add(loggingInterceptor)
        clientBuilder.addInterceptor { chain ->
            val request = chain.request()
            request.newBuilder().addHeader(AGENT_NAME, AGENT_VALUE).build()
            chain.proceed(request)
        }
        clientBuilder.addInterceptor { chain ->
            val request = chain.request()
            request.newBuilder().addHeader(X_CLIENT_VERSION, APP_VERSION_NAME).build()
            chain.proceed(request)
        }
        clientBuilder.addInterceptor { chain ->
            val request = chain.request()
            request.newBuilder().addHeader(UUID_NAME, deviceUUID).build()
            chain.proceed(request)
        }

        //Http client
        val client = clientBuilder
            .readTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS)
            .writeTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS)
            .connectTimeout(NETWORK_CONNECTIONS_TIME, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .build()

        //Retrofit
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
            .build()

        //Init apiServices
        apiServices = retrofit.create(ApiServices::class.java)
    }

    companion object {
        private var apiClient: ApiClient? = null

        fun getInstance(deviceUUID: String): ApiClient =
            apiClient ?: synchronized(this) {
                apiClient ?: ApiClient(deviceUUID).also {
                    apiClient = it
                }
            }
    }

    /**
     * Send apiServices to ApisUseCase for initialize all of apis
     */
    fun apisUseCase(): ApisUseCase {
        return ApisUseCase(apiServices)
    }
}

在这个方法val client = clientBuilder中的.build()这一行给我显示错误信息。

我将此代码添加到gradle.build文件中。

compileOptions {
    sourceCompatibility = '1.8'
    targetCompatibility = '1.8'
}

但是再次显示错误!

错误信息:

java.lang.ExceptionInInitializerError
    at okhttp3.OkHttpClient.newSslSocketFactory(OkHttpClient.java:263)
    at okhttp3.OkHttpClient.<init>(OkHttpClient.java:229)
    at okhttp3.OkHttpClient$Builder.build(OkHttpClient.java:1015)
    at com.app.android.data.services.ApiClient.<init>(ApiClient.kt:56)
    at com.app.android.ui.splash.SplashPresenterImpl.checkUpdate(SplashPresenterImpl.kt:18)
    at com.app.android.ui.splash.SplashActivity.onCreate(SplashActivity.kt:40)
    at android.app.Activity.performCreate(Activity.java:5231)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2243)
    at android.app.ActivityThread.access$800(ActivityThread.java:135)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5019)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.IllegalStateException: Expected Android API level 21+ but was 19
    at okhttp3.internal.platform.AndroidPlatform.buildIfSupported(AndroidPlatform.java:238)
    at okhttp3.internal.platform.Platform.findPlatform(Platform.java:202)
    at okhttp3.internal.platform.Platform.<clinit>(Platform.java:79)

Gradle.Build 代码:

    apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'androidx.navigation.safeargs'
apply plugin: 'kotlin-kapt'
apply plugin: 'io.fabric'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.app.android"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 100
        versionName "2.5.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }
}

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
    implementation 'androidx.core:core-ktx:1.2.0-alpha02'
    implementation 'com.google.android.material:material:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'androidx.viewpager:viewpager:1.0.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.core:core:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    //JWT decoder
    implementation 'com.auth0.android:jwtdecode:1.2.0'
    //Anko lib
    implementation "org.jetbrains.anko:anko-commons:0.10.8"
    implementation "org.jetbrains.anko:anko-design:0.10.8"
    //Rx
    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
    implementation "io.reactivex.rxjava2:rxjava:2.2.8"
    //OkHttp
    implementation 'com.squareup.okhttp3:okhttp:3.14.1'
    implementation "com.squareup.okhttp3:logging-interceptor:3.14.0"
    //Retrofit
    implementation "com.squareup.retrofit2:retrofit:2.5.0"
    implementation "com.squareup.retrofit2:adapter-rxjava2:2.5.0"
    implementation "com.squareup.retrofit2:converter-gson:2.5.0"
    //Gson
    implementation 'com.google.code.gson:gson:2.8.5'
    //Image
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    //Calligraphy
    implementation 'io.github.inflationx:calligraphy3:3.1.0'
    implementation 'io.github.inflationx:viewpump:1.0.0'
    //Navigation
    implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0-alpha05'
    implementation 'androidx.navigation:navigation-ui-ktx:2.1.0-alpha05'
    //Preferences lib
    implementation 'com.github.MrNouri:GoodPrefs:1.0'
    //Multiple sizes
    implementation 'com.intuit.sdp:sdp-android:1.0.6'
    // OnBoarding
    implementation 'com.codemybrainsout.onboarding:onboarder:1.0.4'
    //Alerter
    implementation 'com.tapadoo.android:alerter:4.0.2'
    //Fabric answer
    implementation('com.crashlytics.sdk.android:answers:1.4.7@aar') { transitive = true }
    //Fabric crash
    implementation('com.crashlytics.sdk.android:crashlytics:2.9.9@aar') { transitive = true }
    //Adjust
    implementation 'com.adjust.sdk:adjust-android:4.17.0'
    implementation 'com.android.installreferrer:installreferrer:1.0'
    //Google and firebase services
    implementation 'com.google.android.gms:play-services-analytics:16.0.8'
    implementation 'com.google.firebase:firebase-core:16.0.9'
    implementation 'com.google.firebase:firebase-messaging:17.6.0'
    //Support MultiDex
    implementation 'androidx.multidex:multidex:2.0.1'
    //Room
    implementation 'androidx.room:room-runtime:2.1.0'
    annotationProcessor 'androidx.room:room-compiler:2.1.0'
    //Android svg and noneOldAndroid
    implementation 'com.caverock:androidsvg-aar:1.3'
    implementation 'com.nineoldandroids:library:2.4.0'
    //Animations
    implementation 'com.daimajia.easing:library:2.0@aar'
    implementation 'com.daimajia.androidanimations:library:2.3@aar'
}
apply plugin: 'com.google.gms.google-services'

我该如何修复它?

12个回答

83

对于minSDK小于21的情况,在gradle中像这样将您的OkHttp版本更改为3.12.12 -

  //OkHttp
  implementation ("com.squareup.okhttp3:okhttp:3.12.12"){
      force = true //API 19 support
  }
  implementation 'com.squareup.okhttp3:logging-interceptor:3.12.12'

应该可以正常工作!


1
抱歉,4.4 失败。 - kangear
2
3.12.5是截至2019年9月的最新版本。 - Eneko
2
您可以在此处找到最新的3.12.x版本:https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp - DoomGoober
19
新的Gradle语法:implementation('com.squareup.okhttp3:okhttp') { version { strictly '3.12.12' } } - Matt
@Matt 没有适用于参数类型的java.lang.String.call()方法签名。 - Iman Marashi
显示剩余3条评论

10

对我很有帮助。感谢提供链接以便更加自信地做出决定。谢谢! - Maurici Guell Hernandez

7

对于仍需要旧版本Android库的所有人,您需要使用OkHttp 3.12.x分支。该分支的最新版本是3.12.6。我已经测试并确认此版本适用于三星平板SM-T116NU(Android 19)。

以下是OkHttp的摘录:

OkHttp 3.12.x分支支持Android 2.3+(API级别9+)和Java 7+。这些平台不支持TLS 1.2,因此不应使用。但由于升级困难,我们将通过2020年12月31日向3.12.x分支回溯关键修复。


6
根据 Okhttp文档 ,他们不再支持Android 4。
解决方案是使用3.12.x版本的Okhttp:
def okhttp_version="3.12.0"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
implementation("com.squareup.okhttp3:okhttp") {
    version { strictly "$okhttp_version" }
}

您还可以在Square博客中了解此更改的原因:
引用: 为什么选择Android 5+?为什么现在?
TLS是使HTTPS调用安全、私密和验证的机制。OkHttp意识到五个版本:SSLv3(1996年),TLSv1(1999年),TLSv1.1(2006年),TLSv1.2(2008年)和TLSv1.3(2018年)。我们在2014年响应POODLE攻击后放弃了对SSLv3的支持。
现在是时候放弃TLSv1和TLSv1.1,并将TLSv1.2作为新的最低标准。 10月15日,我们的谷歌同事,Mozilla,Microsoft和Apple宣布他们的浏览器将从2020年初开始要求使用TLSv1.2或更高版本。
谷歌在Android 5.0中增加了对TLSv1.2的支持。 Oracle在Java 8中添加了对其的支持。在OkHttp 3.13中,我们要求主机平台具有内置的对TLSv1.2的支持。
那么Android 4.x怎么办?
谷歌的分发仪表板显示,2018年10月访问Play商店的设备中约有11%运行Android 4.x。 我们创建了一个分支,OkHttp 3.12.x,以支持这些设备。 如果我们遇到任何严重的错误或安全问题,我们将回溯修复并发布。 我们计划在2020年12月31日之前维护此分支。
如果您确实需要在Android 4.x上使用TLSv1.2,那是可能的! Ankush Gupta编写了一份详细的指南,解释了如何让Google Play服务进行设置。 即使您按照此过程操作,仍应将OkHttp 3.12.x与Android 4.x设备一起使用。

3

感谢 @ https://stackoverflow.com/users/5773044/anupam 这段代码在Android API 19中可行:

// Note: 3.12.+ to support Android API 19
implementation 'com.squareup.okhttp3:okhttp:3.12.10'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.10'

implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.4'
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
implementation 'com.squareup.retrofit2:converter-scalars:2.6.4'
testImplementation 'com.squareup.retrofit2:retrofit-mock:2.6.4'
androidTestImplementation 'com.squareup.retrofit2:retrofit-mock:2.6.4'

非常感谢这个,因为OkHttp通常与Retrofit一起使用,了解哪个Retrofit版本适用于哪个OkHttp版本是很重要的。 - koceeng

3

注意@Anupam的回答 - 如果您正在使用Android Studio 4.0+,则force已被弃用。

https://docs.gradle.org/current/userguide/upgrading_version_5.html

强制依赖项 使用force = true强制第一级依赖项的依赖项版本已被弃用。

Force存在语义和排序问题,可以通过使用严格的版本约束来避免。

前进的道路是使用“strictly”关键字进行依赖项降级。 请参阅https://docs.gradle.org/current/userguide/dependency_downgrade_and_exclude.html#sec:enforcing_dependency_version

因此,您应该得到以下内容...

  implementation ('com.squareup.okhttp3:okhttp'){ 
            version {
                strictly '3.12.12'
            }
    }

2

Android 4.x?

谷歌的分发仪表板显示,2018年10月访问Play Store的设备中,约有11%运行着Android 4.x。我们创建了一个分支OkHttp 3.12.x来支持这些设备。如果遇到严重的错误或安全问题,我们将会回溯修复并发布补丁。我们计划维护该分支至2020年12月31日。

如果你真的需要在Android 4.x上使用TLSv1.2,那是可能的!Ankush Gupta编写了一份详细指南,解释了如何让Google Play服务实现这一功能。即使你按照此过程操作,你仍然应该使用OkHttp 3.12.x与Android 4.x设备一起使用。

因此,您可以使用以下代码解决问题。

  implementation ("com.squareup.okhttp3:okhttp:3.12.12"){
  force = true //API 19 support
  }
  implementation 'com.squareup.okhttp3:logging-interceptor:3.12.12'

2

安卓4.4(适用于我)

def ok_http_version = "3.11.0"
implementation "com.squareup.okhttp3:okhttp:$ok_http_version"
implementation "com.squareup.okhttp3:logging-interceptor:$ok_http_version"

2

当我在build.gradle文件中添加以下内容时,我在API 19级别上遇到了相同的问题。

implementation 'com.squareup.okhttp3:okhttp:3.12.2'
implementation 'com.squareup.okhttp3:logging-interceptor:3.13.1'

最终,以下代码帮助我解决了这个问题:

  implementation 'com.squareup.okhttp3:okhttp:3.11.0'
  implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'

希望这个解决方案对大家都有帮助。

1

在API级别低于21的情况下,请使用版本3.11.0

 implementation 'com.squareup.okhttp3:okhttp:3.11.0'
 implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接