Flutter屏幕投射插件castscreen的使用
Flutter屏幕投射插件castscreen的使用
dart_castscreen
是一个Dart包,可以将视频流投射到UPnP和DLNA设备上。以下是该插件的主要功能和示例代码。
功能
- 发现UPnP客户端/设备
- 客户端/设备/服务/操作的规范
- 调用泛型或映射的操作
- 提供了丰富的扩展
示例
发现客户端
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final clients = await CastScreen.discoverClient();
for (var client in clients) {
print(client);
}
}
带选项发现客户端
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final clients = await CastScreen.discoverClient(
ipv4: true,
ipv6: false,
port: 1900,
ST: 'upnp:rootdevice',
timeout: const Duration(seconds: 3),
onError: (Exception e) => print('error: $e'),
);
for (var client in clients) {
print(client);
}
}
发现设备
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice();
for (var device in devices) {
print(device);
}
}
带选项发现设备
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice(
ipv4: true,
ipv6: false,
port: 1900,
ST: 'upnp:rootdevice',
timeout: const Duration(seconds: 3),
onError: (Exception e) => print('error: $e'),
);
for (var device in devices) {
print(device);
}
}
调用泛型操作
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice();
final dev = devices.first;
final alive = await dev.alive();
if (!alive) {
print('Device is not alive.');
return;
}
final output = await dev.avTransportService!
.invoke<CustomActionInput, CustomActionOutput>(
'Custom',
CustomActionInput(),
CustomActionInput.toMap,
CustomActionOutput.fromMap,
);
print(output);
}
final class CustomActionInput {
const CustomActionInput();
static Map<String, String> toMap(CustomActionInput input) {
return {};
}
}
final class CustomActionOutput {
const CustomActionOutput();
factory CustomActionOutput.fromMap(Map<String, String> m) {
return const CustomActionOutput();
}
}
调用映射操作
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice();
final dev = devices.first;
final alive = await dev.alive();
if (!alive) {
print('Device is not alive.');
return;
}
final output = await dev.avTransportService!.invokeMap('Custom', {});
print(output);
}
设置AVTransportURI
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice();
final dev = devices.first;
final alive = await dev.alive();
if (!alive) {
print('Device is not alive.');
return;
}
final output = await dev
.setAVTransportURI(SetAVTransportURIInput('http://example.com/v.mp4'));
print(output);
}
停止播放
import 'package:castscreen/castscreen.dart';
void main(List<String> args) async {
final devices = await CastScreen.discoverDevice();
final dev = devices.first;
final alive = await dev.alive();
if (!alive) {
print('Device is not alive.');
return;
}
final output = await dev.stop(StopInput());
print(output);
}
Flutter示例应用
以下是一个完整的Flutter示例应用,展示了如何使用 dart_castscreen
插件来发现设备、播放和停止视频流。
import 'package:castscreen/castscreen.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CastScreen Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'CastScreen Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Device> devices = [];
Device? curDev;
final String playUrl = 'https://leshiyuncdn.ahjunqin.top/20240109/BWCSLaI6/index.m3u8';
Future<void> search() async {
devices = await CastScreen.discoverDevice(timeout: const Duration(seconds: 3));
curDev = null;
setState(() {});
}
Future<void> play() async {
if (curDev == null) {
return;
}
final alive = await curDev!.alive();
if (!alive) {
return;
}
await curDev!.setAVTransportURI(SetAVTransportURIInput(playUrl));
}
Future<void> stop() async {
if (curDev == null) {
return;
}
final alive = await curDev!.alive();
if (!alive) {
return;
}
await curDev!.stop(const StopInput());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('选择设备:'),
devices.isNotEmpty
? DropdownButton<Device>(
value: curDev,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (Device? value) {
curDev = value;
setState(() {});
},
items: devices.map<DropdownMenuItem<Device>>((dev) {
return DropdownMenuItem<Device>(
value: dev,
child: Text(dev.spec.friendlyName),
);
}).toList(),
)
: const Text('无设备'),
TextButton(onPressed: search, child: const Text('Search')),
TextButton(onPressed: play, child: const Text('Play')),
TextButton(onPressed: stop, child: const Text('Stop')),
],
),
),
);
}
}
这个示例应用展示了如何:
- 发现可用的UPnP/DLNA设备。
- 选择一个设备进行投射。
- 播放和停止视频流。
希望这些示例能帮助你更好地理解和使用 dart_castscreen
插件。如果你有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter屏幕投射插件castscreen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter屏幕投射插件castscreen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用cast_screen
插件来实现屏幕投射功能的代码示例。请注意,cast_screen
插件可能不是官方的Flutter插件,因此在实际项目中,你可能需要找到类似功能的插件或自行实现。不过,这里我会基于一个假设的插件接口来提供一个示例。
首先,你需要在pubspec.yaml
文件中添加cast_screen
插件的依赖(假设它存在):
dependencies:
flutter:
sdk: flutter
cast_screen: ^x.y.z # 替换为实际的版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你可以按照以下步骤来实现屏幕投射功能:
- 导入必要的包:
import 'package:flutter/material.dart';
import 'package:cast_screen/cast_screen.dart'; // 假设这是插件的包名
- 初始化并启动屏幕投射:
在你的主页面或者需要投射屏幕的地方,你可以初始化并启动屏幕投射。下面是一个简单的示例:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CastScreenPage(),
);
}
}
class CastScreenPage extends StatefulWidget {
@override
_CastScreenPageState createState() => _CastScreenPageState();
}
class _CastScreenPageState extends State<CastScreenPage> {
CastScreen? _castScreen;
bool _isCasting = false;
@override
void initState() {
super.initState();
_initCastScreen();
}
Future<void> _initCastScreen() async {
// 初始化CastScreen插件
_castScreen = await CastScreen.init();
// 监听设备发现事件
_castScreen?.deviceDiscovered?.listen((CastDevice device) {
// 在这里处理发现的设备,比如显示设备列表
print("Device discovered: ${device.name}");
});
// 监听连接状态变化事件
_castScreen?.castingStateChanged?.listen((CastingState state) {
setState(() {
_isCasting = state == CastingState.connected;
});
});
}
Future<void> _startCasting(CastDevice device) async {
if (!_isCasting) {
try {
await _castScreen?.startCasting(device);
} catch (e) {
print("Failed to start casting: $e");
}
} else {
print("Already casting...");
}
}
Future<void> _stopCasting() async {
if (_isCasting) {
try {
await _castScreen?.stopCasting();
} catch (e) {
print("Failed to stop casting: $e");
}
} else {
print("Not casting...");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cast Screen Example"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Casting: $_isCasting"),
ElevatedButton(
onPressed: () async {
// 这里应该有一个设备选择逻辑,这里简化为直接调用_startCasting
// 假设我们已经有了一个CastDevice对象叫做selectedDevice
CastDevice selectedDevice = /* 获取或选择一个CastDevice */;
await _startCasting(selectedDevice);
},
child: Text("Start Casting"),
),
ElevatedButton(
onPressed: () async {
await _stopCasting();
},
child: Text("Stop Casting"),
),
],
),
),
);
}
}
注意:
- 上面的代码是一个简化的示例,实际上你需要处理设备的发现、选择以及错误处理等。
CastDevice
和CastingState
是假设的类,你需要根据实际的插件API进行调整。- 插件的API可能会变化,因此请参考你使用的
cast_screen
插件的官方文档。
由于cast_screen
插件可能不是一个真实存在的官方插件,因此在实际项目中,你可能需要寻找一个功能相似的插件,比如flutter_cast
或者其他支持DLNA/Chromecast等协议的插件,并根据其文档进行相应的实现。