Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.8.0
2.9.0-dev.0
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# CHANGELOG

## 2.9.0-dev.0

* Added: AudioManager audio session options with engine-driven native lifecycle and platform routing controls
* Added: Runtime audio processing controls for local audio tracks
* Fixed: Apply Android media audio attributes during WebRTC initialization
* Fixed: Use initialization audio options as the default Android session policy
* Fixed: Avoid sticky Android speaker routing when updating route preference
* Fixed: Clean up local audio tracks when recording start fails
* Fixed: Throw platformUnavailable when runtime audio processing is unsupported
* Fixed: Apply create-time audio processing when local recording is prepared

## 2.8.1

* Added: Add agent deployment targeting to token source options
* Fixed: Android plugin compatibility with AGP 9 built-in Kotlin
* Fixed: Use maintain-resolution as the default video degradation preference for local video publishing

## 2.8.0

* Added: Session API support for simpler E2EE setup
Expand Down
35 changes: 15 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Include this package to your `pubspec.yaml`
```yaml
---
dependencies:
livekit_client: ^2.8.0
livekit_client: ^2.9.0-dev.0
```

### iOS
Expand Down Expand Up @@ -150,30 +150,18 @@ void main() async {

#### Audio Modes

By default, we use the `communication` audio mode on Android which works best for two-way voice communication.
By default LiveKit uses the `communication` audio mode on Android, which works best for two-way voice communication.

If your app is media playback oriented and does not need the use of the device's microphone, you can use the `media`
audio mode which will provide better audio quality.
If your app is media playback oriented and does not need the device's microphone, apply the `media` session yourself. This
switches `AudioManager` to manual mode, where your app owns the session.

```dart
import 'package:flutter_webrtc/flutter_webrtc.dart' as webrtc;

Future<void> _initializeAndroidAudioSettings() async {
await webrtc.WebRTC.initialize(options: {
'androidAudioConfiguration': webrtc.AndroidAudioConfiguration.media.toMap()
});
webrtc.Helper.setAndroidAudioConfiguration(
webrtc.AndroidAudioConfiguration.media);
}

void main() async {
await _initializeAudioSettings();
runApp(const MyApp());
}
await AudioManager.instance.setAudioSessionOptions(
const AudioSessionOptions.media(),
);
```

Note: the audio routing will become controlled by the system and cannot be manually changed with functions like
`Hardware.selectAudioOutput`.
See the [audio session guide](https://github.com/livekit/client-sdk-flutter/blob/main/doc/audio.md) for more.

### Desktop support

Expand Down Expand Up @@ -322,6 +310,13 @@ Widget build(BuildContext context) {

Audio tracks are played automatically as long as you are subscribed to them.

LiveKit owns the platform audio session through `AudioManager`. A call is managed automatically with no setup. Speaker routing and, when you need it, manual session control go through the same object. See the [audio session guide](https://github.com/livekit/client-sdk-flutter/blob/main/doc/audio.md) for examples covering the automatic and manual modes, speaker routing, per platform overrides, and migration from the older `Hardware` APIs.

```dart
// A call is managed automatically. Route to the speaker when you want.
await AudioManager.instance.setSpeakerOutputPreferred(true);
```

### Handling changes

LiveKit client makes it simple to build declarative UI that reacts to state changes. It notifies changes in two ways
Expand Down
41 changes: 34 additions & 7 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ group = "io.livekit.plugin"
version = "1.0-SNAPSHOT"

buildscript {
ext.kotlin_version = "1.8.22"
ext.kotlin_version = "2.1.0"
repositories {
google()
mavenCentral()
Expand All @@ -18,11 +18,23 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}

apply plugin: "com.android.library"
apply plugin: "kotlin-android"

// AGP 9's built-in Kotlin compiles Kotlin itself and rejects the Kotlin Gradle
// Plugin. Apply KGP only when built-in Kotlin is NOT active: that means AGP < 9,
// or AGP 9 with android.builtInKotlin=false (the configuration Flutter currently
// ships by default while the ecosystem migrates).
def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize(".")[0] as int
def builtInKotlinActive = agpMajor >= 9 &&
(!project.hasProperty("android.builtInKotlin") ||
Boolean.parseBoolean(project.property("android.builtInKotlin").toString()))
if (!builtInKotlinActive) {
apply plugin: "kotlin-android"
}

android {
if (project.android.hasProperty("namespace")) {
Expand All @@ -36,10 +48,6 @@ android {
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}

sourceSets {
main.java.srcDirs += "src/main/kotlin"
test.java.srcDirs += "src/test/kotlin"
Expand All @@ -52,8 +60,11 @@ android {
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.mockito:mockito-core:5.0.0")
implementation 'io.github.webrtc-sdk:android:144.7559.01'
implementation 'io.github.webrtc-sdk:android:144.7559.09'
implementation 'io.livekit:noise:2.0.0'
// Audio device/focus/mode routing. Pinned to the same revision used by
// the LiveKit Android SDK (AudioSwitchHandler).
implementation 'com.github.davidliu:audioswitch:039a35aefab7747c557242fa216c9ea11743b604'
}

testOptions {
Expand All @@ -68,3 +79,19 @@ android {
}
}
}

// Configure the Kotlin JVM target. The compilerOptions DSL requires KGP 1.9+ or
// AGP 9 built-in Kotlin; older Flutter app templates ship KGP 1.8.x, which only
// supports the legacy kotlinOptions DSL.
def kotlinExt = project.extensions.findByName("kotlin")
if (kotlinExt?.hasProperty("compilerOptions")) {
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
}
} else {
android.kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
Loading
Loading