android screenshare example and touch ups (#31)

This commit is contained in:
davidliu
2021-11-17 17:11:46 +09:00
committed by GitHub
parent 1835675650
commit 4a59a1e6d5
6 changed files with 88 additions and 14 deletions
@@ -1,13 +1,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.livekit.example">
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application
android:label="LiveKit Example"
android:icon="@mipmap/livekit_ic_launcher">
@@ -40,6 +44,11 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="de.julianassmann.flutter_background.IsolateHolderService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="mediaProjection" />
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
+40 -7
View File
@@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background/flutter_background.dart';
import 'package:livekit_client/livekit_client.dart';
import '../exts.dart';
@@ -114,7 +115,6 @@ class _ControlsWidgetState extends State<ControlsWidget> {
}
void _shareScreen() async {
//
final lp = widget.room.localParticipant;
for (final track in lp.videoTracks) {
@@ -122,6 +122,17 @@ class _ControlsWidgetState extends State<ControlsWidget> {
}
try {
// Required for android screenshare.
const androidConfig = FlutterBackgroundAndroidConfig(
notificationTitle: 'Screen Sharing',
notificationText: 'LiveKit Example is sharing the screen.',
notificationImportance: AndroidNotificationImportance.Default,
notificationIcon:
AndroidResource(name: 'livekit_ic_launcher', defType: 'mipmap'),
);
await FlutterBackground.initialize(androidConfig: androidConfig);
await FlutterBackground.enableBackgroundExecution();
final screenTrack =
await LocalVideoTrack.createScreenTrack(); // Defaults to camera
await widget.room.localParticipant.publishVideoTrack(
@@ -132,6 +143,17 @@ class _ControlsWidgetState extends State<ControlsWidget> {
}
}
void _unshareScreen() async {
final lp = widget.room.localParticipant;
try {
await lp.setScreenShareEnabled(false);
await FlutterBackground.disableBackgroundExecution();
} catch (e) {
print('error disabling screen share: $e');
}
}
void _onTapDisconnect() async {
final result = await context.showDisconnectDialog();
if (result == true) await widget.room.disconnect();
@@ -156,8 +178,12 @@ class _ControlsWidgetState extends State<ControlsWidget> {
// mute audio
final canMute = participant.hasAudio && !participant.isMuted;
final videoPub = participant.videoTracks.firstOrNull;
final videoPub =
participant.getTrackPublicationBySource(TrackSource.camera);
final videoEnabled = videoPub != null && !videoPub.muted;
final screenSharePub =
participant.getTrackPublicationBySource(TrackSource.screenShareVideo);
final screenShareEnabled = screenSharePub != null && !screenSharePub.muted;
return Padding(
padding: const EdgeInsets.symmetric(
@@ -205,11 +231,18 @@ class _ControlsWidgetState extends State<ControlsWidget> {
onPressed: () => _toggleCamera(),
tooltip: 'toggle camera',
),
IconButton(
icon: const Icon(EvaIcons.monitor),
onPressed: () => _shareScreen(),
tooltip: 'share screen (experimental)',
),
if (screenShareEnabled)
IconButton(
icon: const Icon(EvaIcons.monitorOutline),
onPressed: () => _unshareScreen(),
tooltip: 'unshare screen (experimental)',
)
else
IconButton(
icon: const Icon(EvaIcons.monitor),
onPressed: () => _shareScreen(),
tooltip: 'share screen (experimental)',
),
IconButton(
onPressed: _onTapDisconnect,
icon: const Icon(EvaIcons.closeCircle),
+26 -5
View File
@@ -90,6 +90,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_background:
dependency: "direct main"
description:
name: flutter_background
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2+2"
flutter_lints:
dependency: "direct dev"
description:
@@ -218,6 +225,20 @@ packages:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
path_provider_linux:
dependency: transitive
@@ -225,7 +246,7 @@ packages:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
path_provider_macos:
dependency: transitive
description:
@@ -246,7 +267,7 @@ packages:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.4"
petitparser:
dependency: transitive
description:
@@ -302,7 +323,7 @@ packages:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.0.3"
shared_preferences_macos:
dependency: transitive
description:
@@ -330,7 +351,7 @@ packages:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.0.3"
sky_engine:
dependency: transitive
description: flutter
@@ -419,7 +440,7 @@ packages:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.10"
version: "2.3.0"
xdg_directories:
dependency: transitive
description:
+1
View File
@@ -11,6 +11,7 @@ dependencies:
flutter:
sdk: flutter
flutter_background: 1.0.2+2
provider: ^6.0.1
logging: ^1.0.1
shared_preferences: ^2.0.7
+7 -1
View File
@@ -242,6 +242,10 @@ extension LocalParticipantTrackSourceExt on LocalParticipant {
return setSourceEnabled(TrackSource.microphone, enabled);
}
Future<void> setScreenShareEnabled(bool enabled) async {
return setSourceEnabled(TrackSource.screenShareVideo, enabled);
}
Future<void> setSourceEnabled(TrackSource source, bool enabled) async {
final pub = getTrackPublicationBySource(source);
if (pub != null) {
@@ -261,8 +265,10 @@ extension LocalParticipantTrackSourceExt on LocalParticipant {
} else if (source == TrackSource.microphone) {
final track = await LocalAudioTrack.create();
await publishAudioTrack(track);
} else if (source == TrackSource.screenShareVideo) {
final track = await LocalVideoTrack.createScreenTrack();
await publishVideoTrack(track);
}
// TODO: Screen share
}
}
}
+4
View File
@@ -71,6 +71,10 @@ class LocalVideoTrack extends VideoTrack {
);
}
/// Creates a LocalVideoTrack from the display.
///
/// Note: Android requires a foreground service to be started prior to
/// creating a screen track. Refer to the example app for an implementation.
static Future<LocalVideoTrack> createScreenTrack([
ScreenTrackOptions? options,
]) async {