HarmonyOS 鸿蒙Next 我用flutter开发鸿蒙化的flutter如何调用系统的铃声和震动 以及一个计时功能的组件在app在后台工作时 还可实时动态的显示在屏幕最上面
HarmonyOS 鸿蒙Next 我用flutter开发鸿蒙化的flutter如何调用系统的铃声和震动 以及一个计时功能的组件在app在后台工作时 还可实时动态的显示在屏幕最上面
1.鸿蒙化的flutter如何调用系统的铃声和震动
——这个需要使用 Flutter Channel 能力,通过Channel机制,从flutter调用到原生,原生ets代码里实现调用系统铃声和震动的能力;Flutter Channel的文档可以参考 如何使用Flutter与鸿蒙通信 FlutterChannel
2.一个计时功能的组件
—— 这个可以参考下系统提供的 实况胶囊 能力,通过CapsuleType指定计时器类型,实现倒计时的功能,看看能否满足需求
更多关于HarmonyOS 鸿蒙Next 我用flutter开发鸿蒙化的flutter如何调用系统的铃声和震动 以及一个计时功能的组件在app在后台工作时 还可实时动态的显示在屏幕最上面的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
我已经这样用了,可是还是不行呢?
确认下,你的场景是否需要代理提醒?(是否需要APP后台运行),可以参考下文档:
当前没有直接调用系统铃声的api,可以使用其他api例如soundpool播放自定义音频
如果是代理提醒,有参数可以指定自定义音频,customRingUri
期待HarmonyOS能在未来带来更多创新的技术和理念。
你用deveco工具打开的话,会有warning信息 对象包含重复的键:requestPermissions,vscode没有任何提示。
找HarmonyOS工作还需要会Flutter技术的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
我是真的无法理解了,我本地都可以正常震动。你手机版本是最新的了吗?flutter sdk也升级下再试试呢。
把你的demo放到gitee或者github上吧,我下载下来试试。
成功了,成功了,谢谢你 我成功了,
你这个flutter的版本太低了,更新下再试试,有问题再沟通
不会吧,我是1个多月前才从git clone https://gitee.com/openharmony-sig/flutter_flutter.git这里下的
是的 git pull一下 最新的呢。我这边运行没有问题,先升级到最新试试。
你看一下你的手机振动打开了吗?
该开的都开启了
本地整了个demo可以震动,你的plugin有注册上去吗?(demo中EntryAbility步骤中注释部分)
参考下我的demo:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Channel Demo’,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Scaffold(
body: PluginPage(),
),
);
}
}
class PluginPage extends StatefulWidget {
const PluginPage({super.key});
@override
State<PluginPage> createState() => _PluginPageState();
}
class _PluginPageState extends State<PluginPage> {
String message = “”;
final _platform = const MethodChannel(‘samples.flutter.dev/vibrator’);
int count = 0;
@override
void initState() {
super.initState();
_initListener();
}
_initListener() {}
Future<void> _testVibrator() async {
try {
// 调用需要在平台中实现的方法
await _platform.invokeMethod<int>(‘vibrator’);
} on PlatformException catch (e) {}
<span class="hljs-title function_">setState</span>(() {
message = <span class="hljs-string">''</span>;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(message),
ElevatedButton(
onPressed: () => _testVibrator(),
child: const Text(“testVibrator”),
),
],
),
);
}
}
EntryAbility:
import { FlutterAbility, FlutterEngine } from ‘@ohos/flutter_ohos’;
import { GeneratedPluginRegistrant } from ‘…/plugins/GeneratedPluginRegistrant’;
import VibratorPlugin from ‘./VibratorPlugin’;
export default class EntryAbility extends FlutterAbility {
configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
// 注册插件
this.addPlugin(new VibratorPlugin());
}
}
VibratorPlugin.ets
import {
FlutterPlugin,
Log,
MethodCall,
MethodChannel,
} from ‘@ohos/flutter_ohos’;
import { FlutterPluginBinding } from ‘@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin’;
import { MethodResult } from ‘@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel’;
import { vibrator } from ‘@kit.SensorServiceKit’;
export default class VibratorPlugin implements FlutterPlugin {
private channel?: MethodChannel;
onAttachedToEngine(binding: FlutterPluginBinding): void {
this.channel = new MethodChannel(binding.getBinaryMessenger(), “samples.flutter.dev/vibrator”);
this.channel.setMethodCallHandler({
onMethodCall(call: MethodCall, result: MethodResult) {
switch (call.method) {
case “vibrator”:
vibrator.startVibration({
type:‘time’,
duration:5000
},{
id:0,
usage:‘alarm’
}).then(() => {
console.log(‘振动成功’)
result.success(null)
})
break;
default:
result.notImplemented();
break;
}
}
})
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
Log.i(TAG, “onDetachedFromEngine”);
this.channel?.setMethodCallHandler(null);
}
getUniqueClassName(): string {
return “VibratorPlugin”;
}
}
index.ets 不需要修改,使用flutter创建工程默认的即可。
权限配置跟你的一样。
Index页面: // 引入必要的模块 import common from ‘@ohos.app.ability.common’; // 引入鸿蒙的应用能力模块,用于访问应用上下文等功能 import { FlutterPage } from ‘@ohos/flutter_ohos’; // 引入用于在鸿蒙原生应用中嵌入 Flutter 页面的组件
// 获取共享的本地存储实例 let storage = LocalStorage.getShared();
// 定义后退键事件常量 const EVENT_BACK_PRESS = ‘EVENT_BACK_PRESS’;
// 使用 @Entry 注解标记此结构体为应用入口组件
// 使用 @Component 注解,表示这是一个 UI 组件,能够在鸿蒙应用中展示界面
@Entry(storage)
@Component
struct Index {
// 定义应用的上下文对象,允许访问应用的各类能力
private context = getContext(this) as common.UIAbilityContext;
// 从本地存储中获取或保存 viewId
,用于标识嵌入的 Flutter 页面
@LocalStorageLink(‘viewId’) viewId: string = “”;
// 构建页面 UI 的方法
build() {
Column() {
// 使用 FlutterPage 来嵌入 Flutter 页面,并通过 viewId
来唯一标识该页面
FlutterPage({ viewId: this.viewId })
}
}
// 处理后退按键事件的逻辑
onBackPress(): boolean {
// 在按下返回键时,向事件总线发送一个 EVENT_BACK_PRESS
事件,表示已经捕捉到返回键事件
this.context.eventHub.emit(EVENT_BACK_PRESS);
// 返回 true 表示事件已经被处理,系统不再进行默认的返回操作
return true;
}
}
EntryAbility页面:
import { FlutterAbility, FlutterEngine } from ‘@ohos/flutter_ohos’;
import VibratorPlugin from ‘…/pages/VibratorPlugin’;
import { GeneratedPluginRegistrant } from ‘…/plugins/GeneratedPluginRegistrant’;
export default class EntryAbility extends FlutterAbility { configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) GeneratedPluginRegistrant.registerWith(flutterEngine) // 注册插件 this.addPlugin(new VibratorPlugin()); } }
VibratorPlugin页面: // 导入必要的模块 import { FlutterPlugin, Log, MethodCall, MethodChannel } from ‘@ohos/flutter_ohos’; // 引入 Flutter 插件相关类 import { FlutterPluginBinding } from ‘@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin’; // 引入插件绑定 import { MethodResult } from ‘@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel’; // 引入方法结果类 import { vibrator } from ‘@kit.SensorServiceKit’; // 引入震动 API
// 定义一个名为 VibratorPlugin 的类,它实现了 FlutterPlugin 接口 export default class VibratorPlugin implements FlutterPlugin { private channel?: MethodChannel; // 定义日志标签,用于标识日志的来源 private static readonly TAG = “VibratorPlugin”;
// TAG 用于在日志中标识该插件的日志 // 用于与 Flutter 进行通信的 MethodChannel 对象 // 插件初始化方法,Flutter 与原生端连接时会调用此方法 onAttachedToEngine(binding: FlutterPluginBinding): void { // 创建一个 MethodChannel 实例,通道名称为 ‘samples.flutter.dev/vibrator’ this.channel = new MethodChannel(binding.getBinaryMessenger(), “samples.flutter.dev/vibrator”);
// 设置 MethodCallHandler,处理 Flutter 端传来的方法调用
this.channel.setMethodCallHandler({
// 当 Flutter 端调用某个方法时触发此回调
onMethodCall(call: MethodCall, result: MethodResult) {
// 通过 `call.method` 获取调用的方法名
switch (call.method) {
// 如果方法名是 'vibrator',则执行震动操作
case "vibrator":
// 调用振动 API,震动时间为 5 秒,使用类型为 'alarm'
try {
console.warn("正在执行震动...");
vibrator.startVibration({
type: 'time',
duration: 5000, // 设置震动持续时间为 5 秒
}, {
id: 0,
usage: 'alarm',
}).then(() => {
console.warn('震动成功');
result.success(null); // 震动成功后返回结果
})
} catch (err) {
console.warn("异常发生:", err);
result.error('VibrationError', err.message, null);
}
break;
// 如果方法名不是 'vibrator',则返回未实现的状态
default:
result.notImplemented(); // 返回未实现的错误
break;
}
}
});
}
// 插件销毁时调用的方法,Flutter 与原生端断开时会调用此方法 onDetachedFromEngine(binding: FlutterPluginBinding): void { // 打印日志,表示插件已从引擎中卸载 Log.i(VibratorPlugin.TAG, “onDetachedFromEngine”);
// 清除 MethodCallHandler,以便在插件销毁时释放资源
this.channel?.setMethodCallHandler(null);
}
// 获取插件的唯一类名 getUniqueClassName(): string { return “VibratorPlugin”; // 返回插件的唯一标识名 } flutter: import ‘package:flutter/material.dart’; import ‘package:flutter/services.dart’;
void main() { runApp(const MyApp()); }
class MyApp extends StatelessWidget { const MyApp({super.key});
@override Widget build(BuildContext context) { return MaterialApp( title: ‘Flutter Channel Demo’, theme: ThemeData( primarySwatch: Colors.blue, ), home: const Scaffold( body: PluginPage(), ), ); } }
class PluginPage extends StatefulWidget { const PluginPage({super.key});
@override State<PluginPage> createState() => _PluginPageState(); }
class _PluginPageState extends State<PluginPage> { String message = “”; final _platform = const MethodChannel(‘samples.flutter.dev/vibrator’); int count = 0;
@override void initState() { super.initState(); _initListener(); }
_initListener() {}
Future<void> _testVibrator() async { try { // 调用需要在平台中实现的方法 await _platform.invokeMethod<int>(‘vibrator’); } on PlatformException catch (e) {}
setState(() {
message = '';
});
}
@override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text(message), ElevatedButton( onPressed: () => _testVibrator(), child: const Text(“testVibrator”), ), ], ), ); } } 我所有的代码,都和你的一样了,为啥还是不行啊。
你是用的真机还是模拟器?
flutter doctor -v 看一下
这是我的部分代码还是不行