diff --git a/android-test-app/build.gradle.kts b/android-test-app/build.gradle.kts index 901d70056735..c15e9d7c7530 100644 --- a/android-test-app/build.gradle.kts +++ b/android-test-app/build.gradle.kts @@ -6,25 +6,25 @@ plugins { } android { - compileSdk = 34 + compileSdk = 35 namespace = "okhttp.android.testapp" - testBuildType = "release" +// testBuildType = "release" defaultConfig { minSdk = 21 - targetSdk = 34 + targetSdk = 35 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } compileOptions { - targetCompatibility(JavaVersion.VERSION_11) - sourceCompatibility(JavaVersion.VERSION_11) + targetCompatibility(JavaVersion.VERSION_17) + sourceCompatibility(JavaVersion.VERSION_17) } kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() + jvmTarget = JavaVersion.VERSION_17.toString() } buildTypes { diff --git a/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/OkHttpClientFactoryTest.kt b/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/OkHttpClientFactoryTest.kt new file mode 100644 index 000000000000..4e314fee0d2c --- /dev/null +++ b/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/OkHttpClientFactoryTest.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 Block, Inc. + * + * 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 okhttp.android.testapp + +import androidx.test.core.app.ApplicationProvider +import assertk.assertThat +import assertk.assertions.isEqualTo +import okhttp3.android.OkHttpClientContext.okHttpClient +import org.junit.Test + +/** + * Run with "./gradlew :android-test-app:connectedCheck -PandroidBuild=true" and make sure ANDROID_SDK_ROOT is set. + */ +class OkHttpClientFactoryTest { + @Test + fun testUsesCorrectFactory() { + val application = ApplicationProvider.getApplicationContext() + + val client = application.okHttpClient + assertThat(client.cache?.maxSize()).isEqualTo(5_000_000) + assertThat(client.cache?.directory?.name).isEqualTo("test-app-cache") + } +} diff --git a/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt b/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt index 5580f5dd332a..9c0dde48b421 100644 --- a/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt +++ b/android-test-app/src/androidTest/kotlin/okhttp/android/testapp/PublicSuffixDatabaseTest.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package okhttp3.android +package okhttp.android.testapp import assertk.assertThat import assertk.assertions.isEqualTo diff --git a/android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt b/android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt index 481aa6f08488..a9c11f93754e 100644 --- a/android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt +++ b/android-test-app/src/main/kotlin/okhttp/android/testapp/TestApplication.kt @@ -16,5 +16,17 @@ package okhttp.android.testapp import android.app.Application +import okhttp3.OkHttpClient +import okhttp3.android.AndroidOkHttpClientBuilder.androidBuilder +import okhttp3.android.OkHttpClientFactory -class TestApplication : Application() +class TestApplication : Application(), OkHttpClientFactory { + override fun newOkHttpClient(): OkHttpClient { + return OkHttpClient.androidBuilder( + context = this, + cacheDir = { cacheDir.resolve("test-app-cache") }, + cacheSize = 5_000_000, + ) + .build() + } +} diff --git a/okhttp/src/androidMain/kotlin/okhttp3/android/AndroidOkHttpClientBuilder.kt b/okhttp/src/androidMain/kotlin/okhttp3/android/AndroidOkHttpClientBuilder.kt new file mode 100644 index 000000000000..02be1073457b --- /dev/null +++ b/okhttp/src/androidMain/kotlin/okhttp3/android/AndroidOkHttpClientBuilder.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Block, Inc. + * + * 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 okhttp3.android + +import android.content.Context +import android.os.StrictMode +import java.io.File +import okhttp3.Cache +import okhttp3.OkHttpClient + +/** + * [OkHttpClient.Builder] with opinionated defaults on Android. + */ +object AndroidOkHttpClientBuilder { + /** + * Create a [OkHttpClient.Builder] with opinionated defaults on Android. + * + * @param context The context for accessing resources such as file locations or android services. + * @param cacheDir lambda for providing a cache dir. Defaults to "okhttp" in [Context.getCacheDir]. + * @param cacheSize the cache size. Defaults to 10MB. + */ + fun OkHttpClient.Companion.androidBuilder( + context: Context, + cacheDir: (() -> File)? = { context.cacheDir.resolve("okhttp") }, + cacheSize: Long = 10_000_000L, + ): OkHttpClient.Builder { + return OkHttpClient.Builder().apply { + if (cacheDir != null) { + StrictMode.allowThreadDiskWrites().resetAfter { + cache(Cache(cacheDir(), cacheSize)) + } + } + } + } + + private fun StrictMode.ThreadPolicy.resetAfter(block: () -> R) = + try { + block() + } finally { + StrictMode.setThreadPolicy(this) + } +} diff --git a/okhttp/src/androidMain/kotlin/okhttp3/android/OkHttpClientContext.kt b/okhttp/src/androidMain/kotlin/okhttp3/android/OkHttpClientContext.kt index 24aa449f1160..ce3126e7daef 100644 --- a/okhttp/src/androidMain/kotlin/okhttp3/android/OkHttpClientContext.kt +++ b/okhttp/src/androidMain/kotlin/okhttp3/android/OkHttpClientContext.kt @@ -18,6 +18,7 @@ package okhttp3.android import android.content.Context import okhttp3.OkHttpClient +import okhttp3.android.AndroidOkHttpClientBuilder.androidBuilder import okhttp3.internal.platform.ContextAwarePlatform import okhttp3.internal.platform.Platform @@ -43,6 +44,10 @@ object OkHttpClientContext { get() = _okHttpClient private fun newOkHttpClient(context: Context): OkHttpClient { - return (context.applicationContext as? OkHttpClientFactory)?.newOkHttpClient() ?: OkHttpClient() + val okHttpClientFactory = context.applicationContext as? OkHttpClientFactory + return okHttpClientFactory?.newOkHttpClient() ?: OkHttpClient.androidBuilder( + context = context, + cacheDir = null, + ).build() } }