Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ad60ff4
Add Ktor HTTP data source module
k88936 Feb 14, 2026
b4a3e1b
Add timeouts to speed up KtorDataSourceContractTest 'not found' tests
icbaker Feb 24, 2026
acfc387
Reformat with ktfmt
icbaker Feb 24, 2026
fd7d188
Move tests from Robolectric to instrumentation
icbaker Feb 24, 2026
03a1dad
Add copyright headers
icbaker Feb 24, 2026
e8059b2
Remove parts of README that duplicate Ktor docs about customization
icbaker Feb 24, 2026
70a5143
remove ktor specific Proguard rules. they should be left to the user …
k88936 Feb 24, 2026
3954a78
Remove KtorDataSource from the stable API for now
icbaker Feb 24, 2026
e8efd2a
remove resolve case-insensitive step
k88936 Feb 24, 2026
3ab6985
remove Redundant 'requireNotNull' call
k88936 Feb 24, 2026
aa0fe71
Revert "remove resolve case-insensitive step"
k88936 Feb 25, 2026
7d9cc25
change to use ktor engine -android impl in test.
k88936 Feb 25, 2026
3679598
refactor: instead of providing configurable CoroutineScope, simplify …
k88936 Feb 25, 2026
269919e
dep: add dependency 'io.ktor:ktor-client-android:' as default choice
k88936 Feb 25, 2026
fb797ba
Various small doc, case-sensitibity & nullability fixes
icbaker Mar 3, 2026
10bc0e2
Remove manual setting of zero-length body
icbaker Mar 19, 2026
95c16f6
Remove setCacheControl, add some ignore-return annotations
icbaker Mar 19, 2026
04605fc
Assert result of open in tests to resolve lint error
icbaker Mar 19, 2026
b99f502
Increase timeouts to deflake KtorDataSourceContractTest
icbaker Mar 19, 2026
1183c92
test: add unit tests for `KtorDataSource.Factory` methods - `setUserA…
k88936 Mar 20, 2026
1ca74f3
fix flaky race condition in KtorDataSource when processing error mess…
k88936 Mar 20, 2026
e65d07b
replace kotlinx.io dependency from KtorDataSource
k88936 Mar 31, 2026
19e22fe
Add ktor to JARs list
icbaker Mar 31, 2026
6bae1c6
Remove unneeded proguard rules file
icbaker Mar 31, 2026
5bd6ee8
Move nested classes to bottom of outer class
icbaker Apr 1, 2026
d76a7d0
Add release note
icbaker Apr 1, 2026
deeba22
Resolve lint error by using result of open() in test
icbaker Apr 1, 2026
ccbfc6e
Fix some lint warnings
icbaker Apr 1, 2026
cc78baa
Resolve some feedback from internal review
icbaker Apr 7, 2026
8c77927
Resolve internal review feedback
icbaker Apr 14, 2026
82472f9
Fix lint error by using result of open() in tests
icbaker Apr 16, 2026
f9dd205
Configure timeout to make tests pass with OkHttp internally
icbaker Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
* Downloads:
* OkHttp extension:
* Cronet extension:
* Ktor extension:
* Add a new `media3-datasource-ktor` extension module providing a
`KtorDataSource` backed by the [Ktor](https://ktor.io/) HTTP stack.
* RTMP extension:
* HLS extension:
* Fix a bug where an `ArrayIndexOutOfBoundsException` is thrown during
Expand Down
4 changes: 4 additions & 0 deletions core_settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ include("${modulePrefix}lib-datasource-cronet")

project("${modulePrefix}lib-datasource-cronet").projectDir = file("libraries/datasource_cronet")

include("${modulePrefix}lib-datasource-ktor")

project("${modulePrefix}lib-datasource-ktor").projectDir = file("libraries/datasource_ktor")

include("${modulePrefix}lib-datasource-rtmp")

project("${modulePrefix}lib-datasource-rtmp").projectDir = file("libraries/datasource_rtmp")
Expand Down
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ kotlinAnnotationsVersion = "1.9.0"
kotlinBomVersion = "1.8.0"
# Not the same as kotlin version, https://github.com/Kotlin/kotlinx.coroutines/releases
kotlinxCoroutinesVersion = "1.9.0"
ktorVersion = "3.0.3"
leakCanaryVersion = "2.10"
lottieVersion = "6.6.0"
mockitoVersion = "3.12.4"
Expand Down Expand Up @@ -143,6 +144,9 @@ kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-
kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesVersion" }
kotlinx-coroutines-guava = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesVersion" }
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesVersion" }
ktor-client-android = { group = "io.ktor", name = "ktor-client-android", version.ref="ktorVersion" }
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref="ktorVersion" }
ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref="ktorVersion" }
leakcanary-android = { group = "com.squareup.leakcanary", name = "leakcanary-android", version.ref = "leakCanaryVersion" }
lottie = { group = "com.airbnb.android", name = "lottie", version.ref = "lottieVersion" }
material = { group = "com.google.android.material", name = "material", version.ref = "androidxMaterialVersion" }
Expand Down
47 changes: 47 additions & 0 deletions libraries/datasource_ktor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Ktor DataSource module

This module provides an [HttpDataSource] implementation that uses [Ktor].

Ktor is a multiplatform HTTP client developed by JetBrains. It supports HTTP/2,
WebSocket, and Kotlin coroutines for asynchronous operations.

[HttpDataSource]: ../datasource/src/main/java/androidx/media3/datasource/HttpDataSource.java
[Ktor]: https://ktor.io/

## Getting the module

The easiest way to get the module is to add it as a gradle dependency:
Comment thread
k88936 marked this conversation as resolved.

```groovy
implementation 'androidx.media3:media3-datasource-ktor:1.X.X'
```

where `1.X.X` is the version, which must match the version of the other media
modules being used.

Alternatively, you can clone this GitHub project and depend on the module
locally. Instructions for doing this can be found in the [top level README].

[top level README]: ../../README.md

## Using the module

Media components request data through `DataSource` instances. These instances
are obtained from instances of `DataSource.Factory`, which are instantiated and
injected from application code.

If your application only needs to play http(s) content, using the Ktor
extension is as simple as updating any `DataSource.Factory` instantiations in
your application code to use `KtorDataSource.Factory`. If your application
also needs to play non-http(s) content such as local files, use:
```
new DefaultDataSourceFactory(
...
/* baseDataSourceFactory= */ new KtorDataSource.Factory(...));
```

## Links

* [Javadoc][]

[Javadoc]: https://developer.android.com/reference/androidx/media3/datasource/ktor/package-summary
52 changes: 52 additions & 0 deletions libraries/datasource_ktor/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2026 The Android Open Source Project
//
// 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
//
// https://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.
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}

apply(from = "${gradle.extra["androidxMediaSettingsDir"]}/common_config.gradle")

android {
namespace = "androidx.media3.datasource.ktor"

publishing { singleVariant("release") { withSourcesJar() } }
kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_1_8) } }
}

dependencies {
api(libs.ktor.client.android)
api(libs.ktor.client.core)
api(project(modulePrefix + "lib-common"))
api(project(modulePrefix + "lib-datasource"))
implementation(libs.androidx.annotation)
compileOnly(libs.errorprone.annotations)
compileOnly(libs.checkerframework.qual)
compileOnly(libs.kotlin.annotations.jvm)
implementation(libs.kotlinx.coroutines.core)
androidTestImplementation(project(modulePrefix + "test-utils"))
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.dexmaker.mockito)
androidTestImplementation(libs.ktor.client.okhttp)
androidTestImplementation(libs.okhttp.mockwebserver)
androidTestImplementation(libs.test.parameter.injector)
}

extra["releaseArtifactId"] = "media3-datasource-ktor"

extra["releaseName"] = "Media3 Ktor DataSource module"

apply(from = "../../publish.gradle")
28 changes: 28 additions & 0 deletions libraries/datasource_ktor/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2026 The Android Open Source Project

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

https://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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="androidx.media3.datasource.ktor.test">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-sdk/>

<application
android:usesCleartextTraffic="true" />

<instrumentation
android:targetPackage="androidx.media3.datasource.ktor.test"
android:name="androidx.test.runner.AndroidJUnitRunner"/>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2026 The Android Open Source Project
*
* 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
*
* https://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 androidx.media3.datasource.ktor

import androidx.media3.datasource.DataSource
import androidx.media3.test.utils.DataSourceContractTest
import androidx.media3.test.utils.HttpDataSourceTestEnv
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.collect.ImmutableList
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.HttpTimeout
import org.junit.Rule
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class KtorDataSourceContractTest : DataSourceContractTest() {

@JvmField @Rule var httpDataSourceTestEnv = HttpDataSourceTestEnv()

override fun createDataSources(): List<DataSource> {
return listOf(
KtorDataSource.Factory(
HttpClient(Android) {
install(HttpTimeout) {
requestTimeoutMillis = 800
connectTimeoutMillis = 800
socketTimeoutMillis = 800
}
}
)
.createDataSource(),
KtorDataSource.Factory(
HttpClient(OkHttp) {
install(HttpTimeout) {
requestTimeoutMillis = 800
connectTimeoutMillis = 800
socketTimeoutMillis = 800
}
}
)
.createDataSource(),
)
}

override fun getTestResources(): ImmutableList<TestResource> {
return httpDataSourceTestEnv.servedResources
}

override fun getNotFoundResources(): MutableList<TestResource> {
return httpDataSourceTestEnv.notFoundResources
}
}
Loading