HarmonyOS 鸿蒙Next 我用flutter开发鸿蒙化的flutter如何调用系统的铃声和震动 以及一个计时功能的组件在app在后台工作时 还可实时动态的显示在屏幕最上面

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 我用flutter开发鸿蒙化的flutter如何调用系统的铃声和震动 以及一个计时功能的组件在app在后台工作时 还可实时动态的显示在屏幕最上面

我用flutter开发。鸿蒙化的flutter如何调用系统的铃声和震动,以及一个计时功能的组件在app在后台工作时,还可实时动态的显示在屏幕最上面

26 回复

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后台运行),可以参考下文档:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agent-powered-reminder-V5?catalogVersion=V5

当前没有直接调用系统铃声的api,可以使用其他api例如soundpool播放自定义音频

如果是代理提醒,有参数可以指定自定义音频,customRingUri 

参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-reminderagentmanager-V5#reminderrequest

有个问题就是我这么写为啥不行呢cke_135.png

期待HarmonyOS能在未来带来更多创新的技术和理念。

我之前上面不是有个201报错吗,我搜了一下他说是权限的问题,可是我得权限明明都给了,咋还是这个问题,然后我想下滑动,发现还有个cke_10564.png

你用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(() =&gt; {
            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 看一下

我用相同的代码,在flutter项目里面的ohos文件写,和新建的项目写同样的震动代码却出现不同的结果cke_4849.pngcke_5047.png

这是我的部分代码还是不行

cke_633.pngcke_1088.pngcke_1351.pngcke_4423.png

在HarmonyOS鸿蒙Next中,使用Flutter开发时,你可以通过以下方式实现调用系统铃声、震动以及后台计时功能并在屏幕最上方实时动态显示:

  1. 调用系统铃声: 使用media包中的相关API,例如AudioPlayer来播放铃声。Flutter的插件机制允许你调用系统音频服务。

  2. 调用系统震动: 使用haptic_feedback插件,它提供对系统震动功能的访问。可以在需要时调用震动功能。

  3. 后台计时功能: 利用Flutter的WorkManager插件或原生代码(通过Platform Channels)来管理后台任务。这样可以确保应用即使在后台也能执行计时功能。

  4. 实时动态显示在屏幕最上方: 使用Flutter的overlaysystem_overlay_window插件(如果支持)来创建系统级悬浮窗。这允许你在屏幕最上方显示动态内容。不过,请注意,此类功能可能受到系统权限和策略的限制,确保在manifest中申请相关权限。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部