Flutter Tizen平台交互插件tizen_api的使用
Flutter Tizen平台交互插件tizen_api的使用
Tizen
TV Remote for all mobile devices
如何使用
搜索设备
Future<void> searchDevices() async {
final String? ip = await NetworkInfo().getWifiIP();
if (ip == null) {
return;
}
TizenHelperMethods.scanNetwork(ip).listen((tv) {
print('Found TV $tv');
});
}
设置选中的电视
TizenHelperMethods.selectedTv = tvVar;
控制电视
TizenHelperMethods.selectedTv!.addToSocket(KeyCodes.KEY_VOLDOWN);
TizenHelperMethods.selectedTv!.addToSocket(KeyCodes.KEY_VOLUP);
TizenHelperMethods.selectedTv!.addToSocket(KeyCodes.KEY_POWER);
测试示例应用
示例是一个智能电视遥控器应用,非常有趣且值得一试。
你可以尝试用你的电视测试一下。
感谢
感谢 @shaharhn 为这个包开发了基础功能。
完整示例Demo
以下是完整的示例代码:
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:network_info_plus/network_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tizen/logger.dart';
import 'package:tizen_api/tizen_api.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
late final SharedPreferences preferences;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
preferences = await SharedPreferences.getInstance();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) => MaterialApp(
title: 'Smart TV Controller',
theme: ThemeData(primarySwatch: Colors.purple),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.purple,
dividerColor: Colors.purple,
),
home: const MyHomePage(),
);
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
[@override](/user/override)
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
Tv? _connectedTv;
List<Tv> tvs = [];
Offset? _dragDelta;
String? _token;
bool isLoading = true;
bool get connectedToTv =>
_connectedTv != null && _connectedTv == TizenHelperMethods.selectedTv;
String? get token => _token ??= preferences.getString('token');
set token(String? token) {
_token = token;
if (token == null) {
preferences.remove('token');
} else {
preferences.setString('token', token);
}
}
[@override](/user/override)
void initState() {
super.initState();
WakelockPlus.enable();
searchDevices();
}
Future<void> searchDevices() async {
final String? ip = await NetworkInfo().getWifiIP();
if (ip == null) {
return;
}
TizenHelperMethods.scanNetwork(ip).listen((tv) {
setState(() {
tvs.add(tv);
});
}).onDone(() {
setState(() {
isLoading = false;
});
});
}
void _pressKey(KeyCodes key) {
if (TizenHelperMethods.selectedTv == null) {
return;
}
Logger.log('Sending key: $key');
HapticFeedback.mediumImpact();
TizenHelperMethods.selectedTv!.addToSocket(key);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: DropdownButton<String>(
hint: const Text('Select TV'),
value: TizenHelperMethods.selectedTv?.name,
onChanged: (String? tv) {
final Tv selectedTvTemp =
tvs.firstWhere((element) => element.name == tv);
setState(() {
TizenHelperMethods.selectedTv = selectedTvTemp;
});
setupStream();
},
items: tvs
.map<DropdownMenuItem<String>>(
(Tv tv) => DropdownMenuItem<String>(
value: tv.name,
child: Text(tv.name, style: const TextStyle(fontSize: 30)),
),
)
.toList(),
),
actions: connectedToTv
? [
IconButton(
icon: const Icon(Icons.power_settings_new),
onPressed: () => _pressKey(KeyCodes.keyPower),
),
]
: null,
),
body: connectedToTv
? buildConnectedTvUi
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (tvs.isNotEmpty)
Text(
_connectedTv != TizenHelperMethods.selectedTv
? 'Waiting for TV to connect'
: 'Select a TV',
),
const SizedBox(height: 20),
if (isLoading)
const CircularProgressIndicator()
else if (tvs.isEmpty) ...[
const Text('Could not find any TV, you retry'),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: searchDevices,
),
],
],
),
),
);
}
Widget get buildConnectedTvUi => Column(
children: [
buildTopRow,
const Divider(),
buildGestureControl,
const Divider(),
buildBottomRow,
],
);
Widget get buildTopRow => Row(
children: [
Expanded(
child: DropdownButton<String>(
hint: const Text('Select Application'),
onChanged: (String? application) {
if (TizenHelperMethods.selectedTv == null) return;
HapticFeedback.lightImpact();
TizenHelperMethods.selectedTv!
.forwardToApplication(application!);
},
items: Tv.applications.keys
.map<DropdownMenuItem<String>>(
(String value) => DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 30),
),
),
)
.toList(),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: InkWell(
child: const Text('HDMI', textAlign: TextAlign.center),
onTap: () => _pressKey(KeyCodes.keyHdmi),
),
),
],
);
Widget get buildGestureControl => Expanded(
child: Row(
children: [
buildVolumeControl,
const VerticalDivider(),
buildNavigationControl,
],
),
);
Widget get buildVolumeControl => Expanded(
child: GestureDetector(
onVerticalDragStart: (_) => _dragDelta = Offset.zero,
onVerticalDragUpdate: (d) => handleVolumeGesture(d),
onVerticalDragEnd: (_) => _dragDelta = null,
onVerticalDragCancel: () => _dragDelta = null,
onTap: () => _pressKey(KeyCodes.keyMute),
),
);
void handleVolumeGesture(DragUpdateDetails d) {
_dragDelta = _dragDelta! + d.delta;
const threshold = 30.0;
if (_dragDelta!.distance > threshold) {
final dir = (_dragDelta!.direction / pi * 2 + 0.5).floor();
switch (dir) {
case -1:
_pressKey(KeyCodes.keyVolUp);
_dragDelta = _dragDelta!.translate(0, threshold);
case 1:
_pressKey(KeyCodes.keyVolDown);
_dragDelta = _dragDelta!.translate(0, -threshold);
}
}
}
Widget get buildNavigationControl => Expanded(
flex: 3,
child: GestureDetector(
onPanStart: (_) => _dragDelta = Offset.zero,
onPanUpdate: (d) => handleNavigationGesture(d),
onPanEnd: (_) => _dragDelta = null,
onPanCancel: () => _dragDelta = null,
onTap: () => _pressKey(KeyCodes.keyEnter),
),
);
void handleNavigationGesture(DragUpdateDetails d) {
_dragDelta = _dragDelta! + d.delta;
const threshold = 60.0;
if (_dragDelta!.distance > threshold) {
final dir = (_dragDelta!.direction / pi * 2 + 0.5).floor();
switch (dir) {
case 2:
case -2:
_pressKey(KeyCodes.keyLeft);
_dragDelta = _dragDelta!.translate(threshold, -_dragDelta!.dy);
case -1:
_pressKey(KeyCodes.keyUp);
_dragDelta = _dragDelta!.translate(-_dragDelta!.dx, threshold);
case 0:
_pressKey(KeyCodes.keyRight);
_dragDelta = _dragDelta!.translate(-threshold, -_dragDelta!.dy);
case 1:
_pressKey(KeyCodes.keyDown);
_dragDelta = _dragDelta!.translate(-_dragDelta!.dx, -threshold);
}
}
}
Widget get buildBottomRow => SizedBox(
height: 120,
child: Row(
children: [
Expanded(
child: InkWell(
child: const Center(child: Icon(Icons.arrow_back)),
onTap: () => _pressKey(KeyCodes.keyReturn),
),
),
Expanded(
child: InkWell(
child: const Center(child: Icon(Icons.home_outlined)),
onTap: () => _pressKey(KeyCodes.keyHome),
),
),
Expanded(
child: InkWell(
child: const Center(child: Icon(Icons.pause)),
onTap: () => _pressKey(KeyCodes.keyEnter),
),
),
],
),
);
void setupStream() {
TizenHelperMethods.setupStream(token).listen((String? onData) {
if (TizenHelperMethods.selectedTv != _connectedTv) {
setState(() {
_connectedTv = TizenHelperMethods.selectedTv;
});
token = onData;
}
});
}
}
更多关于Flutter Tizen平台交互插件tizen_api的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Tizen平台交互插件tizen_api的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中开发针对Tizen平台的应用时,tizen_api
插件提供了一种与Tizen原生功能进行交互的方式。下面是一个使用tizen_api
插件的简单示例,展示了如何在Flutter应用中调用Tizen的系统通知功能。
首先,确保你已经在pubspec.yaml
文件中添加了tizen_api
依赖:
dependencies:
flutter:
sdk: flutter
tizen_api: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你可以使用以下代码来调用Tizen的系统通知API:
import 'package:flutter/material.dart';
import 'package:tizen_api/tizen_api.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Tizen API Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: _showNotification,
child: Text('Show Notification'),
),
),
),
);
}
void _showNotification() async {
// 检查平台是否为Tizen
if (TizenPlatform.isTizen) {
try {
// 初始化Tizen API
final tizenApi = TizenApi();
// 创建一个简单的通知
final notification = tizenApi.notification.createSimple(
title: 'Hello, Tizen!',
content: 'This is a notification from Flutter!',
appId: 'com.example.flutter_tizen_app', // 替换为你的应用ID
);
// 发布通知
await tizenApi.notification.post(notification);
} catch (e) {
print('Failed to post notification: $e');
}
} else {
print('This platform is not Tizen.');
}
}
}
在这个示例中,我们首先检查当前平台是否为Tizen。如果是,我们初始化TizenApi
实例,并创建一个简单的通知。然后,我们使用post
方法将通知发布到系统通知栏。
注意:
- 在实际开发中,你需要确保你的应用ID与Tizen Store中注册的应用ID一致,否则通知可能无法正确显示。
tizen_api
插件提供的API可能因版本而异,因此请参考官方文档以获取最新的API信息和用法示例。- 在部署到Tizen设备之前,请确保你的开发环境已经正确配置,包括Tizen SDK和Flutter Tizen工具链。
这个示例展示了如何在Flutter应用中调用Tizen的原生通知功能。根据你的需求,你可以探索tizen_api
插件提供的更多功能,如文件系统访问、硬件控制等。