diff --git a/packages/sensors_plus/sensors_plus/ohos/.gitignore b/packages/sensors_plus/sensors_plus/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..651bac51aa99dfae6c9d58ad4e9d114ed868ed91
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/.gitignore
@@ -0,0 +1,36 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
+.hvigor
+dependencies
+oh_modules
+local.properties
+.metadata
+oh-package-lock.json5
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/CHANGELOG.md b/packages/sensors_plus/sensors_plus/ohos/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..f1819e5ad6667feecf7e469d99ce751985ddc3d5
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/CHANGELOG.md
@@ -0,0 +1,12 @@
+## 0.0.3
+
+* Update plugin structure
+
+## 0.0.2
+
+* flutter: ">=3.7.0"
+
+## 0.0.1
+
+* Support OpenHarmony
+
diff --git a/packages/sensors_plus/sensors_plus/ohos/LICENSE b/packages/sensors_plus/sensors_plus/ohos/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..dca36b55e2bf683f02c9beb611b1cb87e01f493b
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 zmtzawqlp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/README.md b/packages/sensors_plus/sensors_plus/ohos/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0f20ce599108d6e4e2487ac92771c4c6456cad5f
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/README.md
@@ -0,0 +1,31 @@
+# sensors_plus_ohos
+
+[](https://pub.dartlang.org/packages/sensors_plus_ohos) [](https://github.com/harmonycandies/sensors_plus_ohos/stargazers) [](https://github.com/harmonycandies/sensors_plus_ohos/network) [](https://github.com/harmonycandies/sensors_plus_ohos/blob/master/LICENSE) [](https://github.com/harmonycandies/sensors_plus_ohos/issues)
+
+Flutter plugin for accessing accelerometer, gyroscope, and magnetometer sensors On OpenHarmony.
+
+The OpenHarmony implementation of [`sensors_plus`][1].
+
+[`sensors_plus`][1] 在 OpenHarmony 平台的实现。
+
+
+# 使用
+
+```yaml
+dependencies:
+ sensors_plus: 4.0.2
+ sensors_plus_ohos: any
+```
+
+在你的项目的 `module.json5` 文件中增加以下权限设置。
+
+```json
+ requestPermissions: [
+ {"name" : "ohos.permission.ACCELEROMETER"},
+ {"name" : "ohos.permission.GYROSCOPE"},
+ ],
+```
+
+
+ [1]: https://pub.dev/packages/sensors_plus
+
diff --git a/packages/sensors_plus/sensors_plus/ohos/analysis_options.yaml b/packages/sensors_plus/sensors_plus/ohos/analysis_options.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a5744c1cfbe77ae2daba29c74156c617b5f09b77
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/.gitignore b/packages/sensors_plus/sensors_plus/ohos/example/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..575b0bf88a9bfd2bbf85f4a6edd102daa6771ab9
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+**/Podfile.lock
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+.metadata
+pubspec.lock
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/README.md b/packages/sensors_plus/sensors_plus/ohos/example/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..82c5c2bd9b364116b934ba5ee8be895477a55f26
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/README.md
@@ -0,0 +1,16 @@
+# sensors_plus_ohos_example
+
+Demonstrates how to use the sensors_plus_ohos plugin.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/analysis_options.yaml b/packages/sensors_plus/sensors_plus/ohos/example/analysis_options.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..61b6c4de17c96863d24279f06b85e01b6ebbdb34
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/lib/main.dart b/packages/sensors_plus/sensors_plus/ohos/example/lib/main.dart
new file mode 100644
index 0000000000000000000000000000000000000000..81d4778785785586c9d06d0034ab7ff6bb642554
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/lib/main.dart
@@ -0,0 +1,413 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ignore_for_file: public_member_api_docs
+
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:sensors_plus_ohos/sensors_plus.dart';
+
+import 'snake.dart';
+
+void main() {
+ WidgetsFlutterBinding.ensureInitialized();
+ SystemChrome.setPreferredOrientations(
+ [
+ DeviceOrientation.portraitUp,
+ DeviceOrientation.portraitDown,
+ ],
+ );
+
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Sensors Demo',
+ theme: ThemeData(
+ useMaterial3: true,
+ colorSchemeSeed: const Color(0x9f4376f8),
+ ),
+ home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({super.key, this.title});
+
+ final String? title;
+
+ @override
+ State createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ static const Duration _ignoreDuration = Duration(milliseconds: 20);
+
+ static const int _snakeRows = 20;
+ static const int _snakeColumns = 20;
+ static const double _snakeCellSize = 10.0;
+
+ UserAccelerometerEvent? _userAccelerometerEvent;
+ AccelerometerEvent? _accelerometerEvent;
+ GyroscopeEvent? _gyroscopeEvent;
+ MagnetometerEvent? _magnetometerEvent;
+ BarometerEvent? _barometerEvent;
+
+ DateTime? _userAccelerometerUpdateTime;
+ DateTime? _accelerometerUpdateTime;
+ DateTime? _gyroscopeUpdateTime;
+ DateTime? _magnetometerUpdateTime;
+ DateTime? _barometerUpdateTime;
+
+ int? _userAccelerometerLastInterval;
+ int? _accelerometerLastInterval;
+ int? _gyroscopeLastInterval;
+ int? _magnetometerLastInterval;
+ int? _barometerLastInterval;
+ final _streamSubscriptions = >[];
+
+ Duration sensorInterval = SensorInterval.normalInterval;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Sensors Plus Example'),
+ elevation: 4,
+ ),
+ body: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Center(
+ child: DecoratedBox(
+ decoration: BoxDecoration(
+ border: Border.all(width: 1.0, color: Colors.black38),
+ ),
+ child: SizedBox(
+ height: _snakeRows * _snakeCellSize,
+ width: _snakeColumns * _snakeCellSize,
+ child: Snake(
+ rows: _snakeRows,
+ columns: _snakeColumns,
+ cellSize: _snakeCellSize,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0),
+ child: Table(
+ columnWidths: const {
+ 0: FlexColumnWidth(4),
+ 4: FlexColumnWidth(2),
+ },
+ children: [
+ const TableRow(
+ children: [
+ SizedBox.shrink(),
+ Text('X'),
+ Text('Y'),
+ Text('Z'),
+ Text('Interval'),
+ ],
+ ),
+ TableRow(
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 8.0),
+ child: Text('UserAccelerometer'),
+ ),
+ Text(_userAccelerometerEvent?.x.toStringAsFixed(1) ?? '?'),
+ Text(_userAccelerometerEvent?.y.toStringAsFixed(1) ?? '?'),
+ Text(_userAccelerometerEvent?.z.toStringAsFixed(1) ?? '?'),
+ Text(
+ '${_userAccelerometerLastInterval?.toString() ?? '?'} ms'),
+ ],
+ ),
+ TableRow(
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 8.0),
+ child: Text('Accelerometer'),
+ ),
+ Text(_accelerometerEvent?.x.toStringAsFixed(1) ?? '?'),
+ Text(_accelerometerEvent?.y.toStringAsFixed(1) ?? '?'),
+ Text(_accelerometerEvent?.z.toStringAsFixed(1) ?? '?'),
+ Text('${_accelerometerLastInterval?.toString() ?? '?'} ms'),
+ ],
+ ),
+ TableRow(
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 8.0),
+ child: Text('Gyroscope'),
+ ),
+ Text(_gyroscopeEvent?.x.toStringAsFixed(1) ?? '?'),
+ Text(_gyroscopeEvent?.y.toStringAsFixed(1) ?? '?'),
+ Text(_gyroscopeEvent?.z.toStringAsFixed(1) ?? '?'),
+ Text('${_gyroscopeLastInterval?.toString() ?? '?'} ms'),
+ ],
+ ),
+ TableRow(
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 8.0),
+ child: Text('Magnetometer'),
+ ),
+ Text(_magnetometerEvent?.x.toStringAsFixed(1) ?? '?'),
+ Text(_magnetometerEvent?.y.toStringAsFixed(1) ?? '?'),
+ Text(_magnetometerEvent?.z.toStringAsFixed(1) ?? '?'),
+ Text('${_magnetometerLastInterval?.toString() ?? '?'} ms'),
+ ],
+ ),
+ ],
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 20.0),
+ child: Table(
+ columnWidths: const {
+ 0: FlexColumnWidth(4),
+ 1: FlexColumnWidth(3),
+ 2: FlexColumnWidth(2),
+ },
+ children: [
+ const TableRow(
+ children: [
+ SizedBox.shrink(),
+ Text('Pressure'),
+ Text('Interval'),
+ ],
+ ),
+ TableRow(
+ children: [
+ const Padding(
+ padding: EdgeInsets.symmetric(vertical: 8.0),
+ child: Text('Barometer'),
+ ),
+ Text(
+ '${_barometerEvent?.pressure.toStringAsFixed(1) ?? '?'} hPa'),
+ Text('${_barometerLastInterval?.toString() ?? '?'} ms'),
+ ],
+ ),
+ ],
+ ),
+ ),
+ Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ const Text('Update Interval:'),
+ SegmentedButton(
+ segments: [
+ ButtonSegment(
+ value: SensorInterval.gameInterval,
+ label: Text('Game\n'
+ '(${SensorInterval.gameInterval.inMilliseconds}ms)'),
+ ),
+ ButtonSegment(
+ value: SensorInterval.uiInterval,
+ label: Text('UI\n'
+ '(${SensorInterval.uiInterval.inMilliseconds}ms)'),
+ ),
+ ButtonSegment(
+ value: SensorInterval.normalInterval,
+ label: Text('Normal\n'
+ '(${SensorInterval.normalInterval.inMilliseconds}ms)'),
+ ),
+ const ButtonSegment(
+ value: Duration(milliseconds: 500),
+ label: Text('500ms'),
+ ),
+ const ButtonSegment(
+ value: Duration(seconds: 1),
+ label: Text('1s'),
+ ),
+ ],
+ selected: {sensorInterval},
+ showSelectedIcon: false,
+ onSelectionChanged: (value) {
+ setState(() {
+ sensorInterval = value.first;
+ userAccelerometerEventStream(
+ samplingPeriod: sensorInterval);
+ accelerometerEventStream(samplingPeriod: sensorInterval);
+ gyroscopeEventStream(samplingPeriod: sensorInterval);
+ magnetometerEventStream(samplingPeriod: sensorInterval);
+ barometerEventStream(samplingPeriod: sensorInterval);
+ });
+ },
+ ),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ for (final subscription in _streamSubscriptions) {
+ subscription.cancel();
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _streamSubscriptions.add(
+ userAccelerometerEventStream(samplingPeriod: sensorInterval).listen(
+ (UserAccelerometerEvent event) {
+ final now = event.timestamp;
+ setState(() {
+ _userAccelerometerEvent = event;
+ if (_userAccelerometerUpdateTime != null) {
+ final interval = now.difference(_userAccelerometerUpdateTime!);
+ if (interval > _ignoreDuration) {
+ _userAccelerometerLastInterval = interval.inMilliseconds;
+ }
+ }
+ });
+ _userAccelerometerUpdateTime = now;
+ },
+ onError: (e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return const AlertDialog(
+ title: Text("Sensor Not Found"),
+ content: Text(
+ "It seems that your device doesn't support User Accelerometer Sensor"),
+ );
+ });
+ },
+ cancelOnError: true,
+ ),
+ );
+ _streamSubscriptions.add(
+ accelerometerEventStream(samplingPeriod: sensorInterval).listen(
+ (AccelerometerEvent event) {
+ final now = event.timestamp;
+ setState(() {
+ _accelerometerEvent = event;
+ if (_accelerometerUpdateTime != null) {
+ final interval = now.difference(_accelerometerUpdateTime!);
+ if (interval > _ignoreDuration) {
+ _accelerometerLastInterval = interval.inMilliseconds;
+ }
+ }
+ });
+ _accelerometerUpdateTime = now;
+ },
+ onError: (e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return const AlertDialog(
+ title: Text("Sensor Not Found"),
+ content: Text(
+ "It seems that your device doesn't support Accelerometer Sensor"),
+ );
+ });
+ },
+ cancelOnError: true,
+ ),
+ );
+ _streamSubscriptions.add(
+ gyroscopeEventStream(samplingPeriod: sensorInterval).listen(
+ (GyroscopeEvent event) {
+ final now = event.timestamp;
+ setState(() {
+ _gyroscopeEvent = event;
+ if (_gyroscopeUpdateTime != null) {
+ final interval = now.difference(_gyroscopeUpdateTime!);
+ if (interval > _ignoreDuration) {
+ _gyroscopeLastInterval = interval.inMilliseconds;
+ }
+ }
+ });
+ _gyroscopeUpdateTime = now;
+ },
+ onError: (e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return const AlertDialog(
+ title: Text("Sensor Not Found"),
+ content: Text(
+ "It seems that your device doesn't support Gyroscope Sensor"),
+ );
+ });
+ },
+ cancelOnError: true,
+ ),
+ );
+ _streamSubscriptions.add(
+ magnetometerEventStream(samplingPeriod: sensorInterval).listen(
+ (MagnetometerEvent event) {
+ final now = event.timestamp;
+ setState(() {
+ _magnetometerEvent = event;
+ if (_magnetometerUpdateTime != null) {
+ final interval = now.difference(_magnetometerUpdateTime!);
+ if (interval > _ignoreDuration) {
+ _magnetometerLastInterval = interval.inMilliseconds;
+ }
+ }
+ });
+ _magnetometerUpdateTime = now;
+ },
+ onError: (e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return const AlertDialog(
+ title: Text("Sensor Not Found"),
+ content: Text(
+ "It seems that your device doesn't support Magnetometer Sensor"),
+ );
+ });
+ },
+ cancelOnError: true,
+ ),
+ );
+ _streamSubscriptions.add(
+ barometerEventStream(samplingPeriod: sensorInterval).listen(
+ (BarometerEvent event) {
+ final now = event.timestamp;
+ setState(() {
+ _barometerEvent = event;
+ if (_barometerUpdateTime != null) {
+ final interval = now.difference(_barometerUpdateTime!);
+ if (interval > _ignoreDuration) {
+ _barometerLastInterval = interval.inMilliseconds;
+ }
+ }
+ });
+ _barometerUpdateTime = now;
+ },
+ onError: (e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return const AlertDialog(
+ title: Text("Sensor Not Found"),
+ content: Text(
+ "It seems that your device doesn't support Barometer Sensor"),
+ );
+ });
+ },
+ cancelOnError: true,
+ ),
+ );
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/lib/snake.dart b/packages/sensors_plus/sensors_plus/ohos/example/lib/snake.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f3c91db9a7ed4df0b2d6745fa87904cd987d0838
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/lib/snake.dart
@@ -0,0 +1,131 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ignore_for_file: public_member_api_docs
+
+import 'dart:async';
+import 'dart:math' as math;
+
+import 'package:flutter/material.dart';
+import 'package:sensors_plus_ohos/sensors_plus.dart';
+
+class Snake extends StatefulWidget {
+ Snake({super.key, this.rows = 20, this.columns = 20, this.cellSize = 10.0}) {
+ assert(10 <= rows);
+ assert(10 <= columns);
+ assert(5.0 <= cellSize);
+ }
+
+ final int rows;
+ final int columns;
+ final double cellSize;
+
+ @override
+ // ignore: no_logic_in_create_state
+ State createState() => SnakeState(rows, columns, cellSize);
+}
+
+class SnakeBoardPainter extends CustomPainter {
+ SnakeBoardPainter(this.state, this.cellSize);
+
+ GameState? state;
+ double cellSize;
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ final blackLine = Paint()..color = Colors.black;
+ final blackFilled = Paint()
+ ..color = Colors.black
+ ..style = PaintingStyle.fill;
+ canvas.drawRect(
+ Rect.fromPoints(Offset.zero, size.bottomLeft(Offset.zero)),
+ blackLine,
+ );
+ for (final p in state!.body) {
+ final a = Offset(cellSize * p.x, cellSize * p.y);
+ final b = Offset(cellSize * (p.x + 1), cellSize * (p.y + 1));
+
+ canvas.drawRect(Rect.fromPoints(a, b), blackFilled);
+ }
+ }
+
+ @override
+ bool shouldRepaint(CustomPainter oldDelegate) {
+ return true;
+ }
+}
+
+class SnakeState extends State {
+ SnakeState(int rows, int columns, this.cellSize) {
+ state = GameState(rows, columns);
+ }
+
+ double cellSize;
+ GameState? state;
+ AccelerometerEvent? acceleration;
+ late StreamSubscription _streamSubscription;
+ late Timer _timer;
+
+ @override
+ Widget build(BuildContext context) {
+ return CustomPaint(painter: SnakeBoardPainter(state, cellSize));
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _streamSubscription.cancel();
+ _timer.cancel();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _streamSubscription =
+ accelerometerEventStream().listen((AccelerometerEvent event) {
+ setState(() {
+ acceleration = event;
+ });
+ });
+
+ _timer = Timer.periodic(const Duration(milliseconds: 200), (_) {
+ setState(() {
+ _step();
+ });
+ });
+ }
+
+ void _step() {
+ final newDirection = acceleration == null
+ ? null
+ : acceleration!.x.abs() < 1.0 && acceleration!.y.abs() < 1.0
+ ? null
+ : (acceleration!.x.abs() < acceleration!.y.abs())
+ ? math.Point(0, acceleration!.y.sign.toInt())
+ : math.Point(-acceleration!.x.sign.toInt(), 0);
+ state!.step(newDirection);
+ }
+}
+
+class GameState {
+ GameState(this.rows, this.columns) {
+ snakeLength = math.min(rows, columns) - 5;
+ }
+
+ int rows;
+ int columns;
+ late int snakeLength;
+
+ List> body = >[const math.Point(0, 0)];
+ math.Point direction = const math.Point(1, 0);
+
+ void step(math.Point? newDirection) {
+ var next = body.last + direction;
+ next = math.Point(next.x % columns, next.y % rows);
+
+ body.add(next);
+ if (body.length > snakeLength) body.removeAt(0);
+ direction = newDirection ?? direction;
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/.gitignore b/packages/sensors_plus/sensors_plus/ohos/example/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..940b8265564d187f21566b25654fb8608808c6a4
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/.gitignore
@@ -0,0 +1,18 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+entry/libs/arm64-v8a/libapp.so
+entry/libs/arm64-v8a/libflutter.so
+entry/libs/arm64-v8a/libvmservice_snapshot.so
+entry/src/main/resources/rawfile/flutter_assets/
+har/*.har
+oh-package-lock.json5
+dta
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/app.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..78727fad7d72f06f20be246bd423fa129d05ca2e
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.fluttercandies.sensors_plus_ohos_example",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/element/string.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..3717fad8df8bd3f8bf77245617a6309c201db973
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "sensors_plus_ohos_example"
+ }
+ ]
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/media/app_icon.png b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/packages/sensors_plus/sensors_plus/ohos/example/ohos/AppScope/resources/base/media/app_icon.png differ
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/build-profile.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..1d12140d202702d7c73d64f1b291fe5c45a660ce
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/build-profile.json5
@@ -0,0 +1,27 @@
+{
+ "app": {
+ "signingConfigs": [],
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compatibleSdkVersion": "5.0.0(12)",
+ "runtimeOS": "HarmonyOS"
+ }
+ ]
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/.gitignore b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..91f7d8e4f9dc4864ded3eb8d12bab119a5d082ab
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/.gitignore
@@ -0,0 +1,10 @@
+
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
+/har
+/libs
+oh-package-lock.json5
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/build-profile.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/build-profile.json5
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+{
+ "apiType": 'stageMode',
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default",
+ "runtimeOS": "HarmonyOS"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/hvigorfile.ts b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/hvigorfile.ts
@@ -0,0 +1,17 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { hapTasks } from '@ohos/hvigor-ohos-plugin';
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/oh-package.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..307db85eb6e206b1bea5afc1c6d5fedd646c064e
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/oh-package.json5
@@ -0,0 +1,11 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "sensors_plus_ohos": "file:../har/sensors_plus_ohos.har"
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..a00049282e93c69f1b3dcd987538024f47e40ace
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { FlutterAbility } from '@ohos/flutter_ohos'
+import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
+import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine';
+
+export default class EntryAbility extends FlutterAbility {
+ configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+ GeneratedPluginRegistrant.registerWith(flutterEngine)
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/pages/Index.ets b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1125f9fdd95f4310a182c1c9e3680f37f73686c9
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import common from '@ohos.app.ability.common';
+import { FlutterPage } from '@ohos/flutter_ohos'
+
+let storage = LocalStorage.getShared()
+const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'
+
+@Entry(storage)
+@Component
+struct Index {
+ private context = getContext(this) as common.UIAbilityContext
+ @LocalStorageLink('viewId') viewId: string = "";
+
+ build() {
+ Column() {
+ FlutterPage({ viewId: this.viewId })
+ }
+ }
+
+ onBackPress(): boolean {
+ this.context.eventHub.emit(EVENT_BACK_PRESS)
+ return true
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d212a6d274b8910e95aabb29911756a88467aa8a
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { FlutterEngine, Log } from '@ohos/flutter_ohos';
+import SensorsPlusOhosPlugin from 'sensors_plus_ohos';
+
+/**
+ * Generated file. Do not edit.
+ * This file is generated by the Flutter tool based on the
+ * plugins that support the Ohos platform.
+ */
+
+const TAG = "GeneratedPluginRegistrant";
+
+export class GeneratedPluginRegistrant {
+
+ static registerWith(flutterEngine: FlutterEngine) {
+ try {
+ flutterEngine.getPlugins()?.add(new SensorsPlusOhosPlugin());
+ } catch (e) {
+ Log.e(
+ TAG,
+ "Tried to register plugins with FlutterEngine ("
+ + flutterEngine
+ + ") failed.");
+ Log.e(TAG, "Received exception while registering", e);
+ }
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/module.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..70a33576da23eb8a54d31f82398113ee4ba2f67a
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/module.json5
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "phone"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:icon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "requestPermissions": [
+ {"name" : "ohos.permission.INTERNET"},
+ {"name" : "ohos.permission.ACCELEROMETER"},
+ {"name" : "ohos.permission.GYROSCOPE"},
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/color.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/string.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..cfc0c13b4083eda3710f3817e2135051e2175286
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "sensors_plus_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/media/icon.png b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/media/icon.png differ
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..cfc0c13b4083eda3710f3817e2135051e2175286
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/en_US/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "sensors_plus_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..3b48c4baec8d4275d15e1f5ad1f2f8455fb19e60
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "模块描述"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "sensors_plus_ohos_example"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigor/hvigor-config.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..ba720309263e55532a56354c49cdbc813c391ff6
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigor/hvigor-config.json5
@@ -0,0 +1,8 @@
+{
+ "modelVersion": "5.0.0",
+ "dependencies": {
+ },
+ "properties": {
+ "ohos.nativeResolver": false
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigorfile.ts b/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f2d2aafe6d6a3a71a9944ebd0c91fbc308ac9d1
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/hvigorfile.ts
@@ -0,0 +1,21 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/ohos/oh-package.json5 b/packages/sensors_plus/sensors_plus/ohos/example/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..59a21e15188e49cceae5a582a82b988463e575f5
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/ohos/oh-package.json5
@@ -0,0 +1,20 @@
+{
+ "modelVersion": "5.0.0",
+ "name": "sensors_plus_ohos_example",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.6"
+ },
+ "overrides": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har",
+ "sensors_plus_ohos": "file:./har/sensors_plus_ohos.har",
+ "@ohos/flutter_module": "file:./entry"
+ }
+}
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/example/pubspec.yaml b/packages/sensors_plus/sensors_plus/ohos/example/pubspec.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ffda5ccfedf8e615e2ea386f1ab76d850ed6a909
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/example/pubspec.yaml
@@ -0,0 +1,83 @@
+name: sensors_plus_ohos_example
+description: Demonstrates how to use the sensors_plus_ohos plugin.
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+environment:
+ sdk: '>=2.19.6 <3.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+ sensors_plus: ^6.1.0
+ sensors_plus_ohos:
+ # When depending on this package from a real application you should use:
+ # sensors_plus_ohos: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/packages/sensors_plus/sensors_plus/ohos/lib/sensors_plus.dart b/packages/sensors_plus/sensors_plus/ohos/lib/sensors_plus.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5739bb8f8b6ef7fb0d9ec6426ea9a6fac5bcaf25
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/lib/sensors_plus.dart
@@ -0,0 +1,79 @@
+import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+import 'src/sensors.dart';
+
+export 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+export 'src/sensors.dart'
+ if (dart.library.js_interop) 'src/sensors_plus_web.dart';
+
+final _sensors = Sensors();
+
+/// A broadcast stream of events from the device accelerometer.
+@Deprecated('Use accelerometerEventStream() instead.')
+Stream get accelerometerEvents {
+ return _sensors.accelerometerEvents;
+}
+
+/// A broadcast stream of events from the device gyroscope.
+@Deprecated('Use gyroscopeEventStream() instead.')
+Stream get gyroscopeEvents {
+ return _sensors.gyroscopeEvents;
+}
+
+/// Events from the device accelerometer with gravity removed.
+@Deprecated('Use userAccelerometerEventStream() instead.')
+Stream get userAccelerometerEvents {
+ return _sensors.userAccelerometerEvents;
+}
+
+/// A broadcast stream of events from the device magnetometer.
+@Deprecated('Use magnetometerEventStream() instead.')
+Stream get magnetometerEvents {
+ return _sensors.magnetometerEvents;
+}
+
+/// Returns a broadcast stream of events from the device accelerometer at the
+/// given sampling frequency.
+@override
+Stream accelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.accelerometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device gyroscope at the
+/// given sampling frequency.
+@override
+Stream gyroscopeEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.gyroscopeEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device accelerometer with
+/// gravity removed at the given sampling frequency.
+@override
+Stream userAccelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.userAccelerometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device magnetometer at the
+/// given sampling frequency.
+@override
+Stream magnetometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.magnetometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device barometer at the
+/// given sampling frequency.
+@override
+Stream barometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.barometerEventStream(samplingPeriod: samplingPeriod);
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors.dart b/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors.dart
new file mode 100644
index 0000000000000000000000000000000000000000..2caf36b3daf19e1c3f469ae24487dd1048be1c0b
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors.dart
@@ -0,0 +1,81 @@
+import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+/// The Sensors implementation.
+class Sensors extends SensorsPlatform {
+ /// Constructs a singleton instance of [Sensors].
+ ///
+ /// [Sensors] is designed to work as a singleton.
+ factory Sensors() => _singleton ??= Sensors._();
+
+ Sensors._();
+
+ static Sensors? _singleton;
+
+ static SensorsPlatform get _platform => SensorsPlatform.instance;
+
+ /// Returns a broadcast stream of events from the device accelerometer at the
+ /// given sampling frequency.
+ ///
+ /// This method always returning the same stream. If this method is called
+ /// again, the sampling period of the stream will be update. All previous
+ /// listener will also be affected.
+ @override
+ Stream accelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ return _platform.accelerometerEventStream(samplingPeriod: samplingPeriod);
+ }
+
+ /// Returns a broadcast stream of events from the device gyroscope at the
+ /// given sampling frequency.
+ ///
+ /// This method always returning the same stream. If this method is called
+ /// again, the sampling period of the stream will be update. All previous
+ /// listener will also be affected.
+ @override
+ Stream gyroscopeEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ return _platform.gyroscopeEventStream(samplingPeriod: samplingPeriod);
+ }
+
+ /// Returns a broadcast stream of events from the device accelerometer with
+ /// gravity removed at the given sampling frequency.
+ ///
+ /// This method always returning the same stream. If this method is called
+ /// again, the sampling period of the stream will be update. All previous
+ /// listener will also be affected.
+ @override
+ Stream userAccelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ return _platform.userAccelerometerEventStream(
+ samplingPeriod: samplingPeriod);
+ }
+
+ /// Returns a broadcast stream of events from the device magnetometer at the
+ /// given sampling frequency.
+ ///
+ /// This method always returning the same stream. If this method is called
+ /// again, the sampling period of the stream will be update. All previous
+ /// listener will also be affected.
+ @override
+ Stream magnetometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ return _platform.magnetometerEventStream(samplingPeriod: samplingPeriod);
+ }
+
+ /// Returns a broadcast stream of events from the device barometer at the
+ /// given sampling frequency.
+ ///
+ /// This method always returning the same stream. If this method is called
+ /// again, the sampling period of the stream will be update. All previous
+ /// listener will also be affected.
+ @override
+ Stream barometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ return _platform.barometerEventStream(samplingPeriod: samplingPeriod);
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors_plus_web.dart b/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors_plus_web.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4dbc8e872375638692e2939b80bdeb9e1c328929
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/lib/src/sensors_plus_web.dart
@@ -0,0 +1,78 @@
+import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+import 'web_sensors.dart';
+
+export 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+export 'web_sensors.dart';
+
+final _sensors = WebSensorsPlugin();
+
+/// A broadcast stream of events from the device accelerometer.
+@Deprecated('Use accelerometerEventStream() instead.')
+Stream get accelerometerEvents {
+ return _sensors.accelerometerEvents;
+}
+
+/// A broadcast stream of events from the device gyroscope.
+@Deprecated('Use gyroscopeEventStream() instead.')
+Stream get gyroscopeEvents {
+ return _sensors.gyroscopeEvents;
+}
+
+/// Events from the device accelerometer with gravity removed.
+@Deprecated('Use userAccelerometerEventStream() instead.')
+Stream get userAccelerometerEvents {
+ return _sensors.userAccelerometerEvents;
+}
+
+/// A broadcast stream of events from the device magnetometer.
+@Deprecated('Use magnetometerEventStream() instead.')
+Stream get magnetometerEvents {
+ return _sensors.magnetometerEvents;
+}
+
+/// Returns a broadcast stream of events from the device accelerometer at the
+/// given sampling frequency.
+@override
+Stream accelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.accelerometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device gyroscope at the
+/// given sampling frequency.
+@override
+Stream gyroscopeEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.gyroscopeEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device accelerometer with
+/// gravity removed at the given sampling frequency.
+@override
+Stream userAccelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.userAccelerometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device magnetometer at the
+/// given sampling frequency.
+@override
+Stream magnetometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.magnetometerEventStream(samplingPeriod: samplingPeriod);
+}
+
+/// Returns a broadcast stream of events from the device barometer at the
+/// given sampling frequency.
+@override
+Stream barometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+}) {
+ return _sensors.barometerEventStream(samplingPeriod: samplingPeriod);
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors.dart b/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors.dart
new file mode 100644
index 0000000000000000000000000000000000000000..00cbd56b4b80d80ffa1e27cd5aa081f13f217c48
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors.dart
@@ -0,0 +1,304 @@
+import 'dart:async';
+import 'dart:developer' as developer;
+import 'dart:js_interop';
+
+import 'package:flutter_web_plugins/flutter_web_plugins.dart';
+import 'package:sensors_plus/src/web_sensors_interop.dart';
+import 'package:sensors_plus_platform_interface/sensors_plus_platform_interface.dart';
+
+/// The sensors plugin.
+class WebSensorsPlugin extends SensorsPlatform {
+ /// Factory method that initializes the Sensors plugin platform with an instance
+ /// of the plugin for the web.
+ static void registerWith(Registrar registrar) {
+ SensorsPlatform.instance = WebSensorsPlugin();
+ }
+
+ void _featureDetected(
+ Function initSensor, {
+ String? apiName,
+ String? permissionName,
+ Function? onError,
+ }) {
+ try {
+ initSensor();
+ } on DOMException catch (e) {
+ if (onError != null) {
+ onError();
+ }
+
+ // Handle construction errors.
+ //
+ // If a feature policy blocks use of a feature it is because your code
+ // is inconsistent with the policies set on your server.
+ // This is not something that would ever be shown to a user.
+ // See Feature-Policy for implementation instructions in the browsers.
+ switch (e.name) {
+ case 'TypeError':
+ // if this feature is not supported or Flag is not enabled yet!
+ developer.log(
+ '$apiName is not supported by the User Agent.',
+ error: '${e.name}: ${e.message}',
+ );
+ case 'SecurityError':
+ // See the note above about feature policy.
+ developer.log(
+ '$apiName construction was blocked by a feature policy.',
+ error: '${e.name}: ${e.message}',
+ );
+ default:
+ // if this is unknown error, convert DOMException to Exception
+ developer.log('Unknown error happened, rethrowing.');
+ throw Exception('${e.name}: ${e.message}');
+ }
+ } on Error catch (_) {
+ // DOMException is not caught as in release build
+ // so we need to catch it as Error
+ if (onError != null) {
+ onError();
+ }
+ }
+ }
+
+ StreamController? _accelerometerStreamController;
+ late Stream _accelerometerResultStream;
+
+ @override
+ Stream accelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ if (_accelerometerStreamController == null) {
+ _accelerometerStreamController = StreamController();
+ _featureDetected(
+ () {
+ final accelerometer = Accelerometer(
+ SensorOptions(
+ frequency: samplingPeriod.frequency,
+ ),
+ );
+
+ accelerometer.start();
+
+ accelerometer.onreading = (Event _) {
+ _accelerometerStreamController!.add(
+ AccelerometerEvent(
+ accelerometer.x,
+ accelerometer.y,
+ accelerometer.z,
+ DateTime.now(),
+ ),
+ );
+ }.toJS;
+
+ accelerometer.onerror = (SensorErrorEvent e) {
+ developer.log(
+ 'The accelerometer API is supported but something is wrong!',
+ error: e.error.message,
+ );
+ }.toJS;
+ },
+ apiName: 'Accelerometer()',
+ permissionName: 'accelerometer',
+ onError: () {
+ _accelerometerStreamController!
+ .add(AccelerometerEvent(0, 0, 0, DateTime.now()));
+ },
+ );
+ _accelerometerResultStream =
+ _accelerometerStreamController!.stream.asBroadcastStream();
+
+ _accelerometerStreamController!.onCancel = () {
+ _accelerometerStreamController!.close();
+ };
+ }
+
+ return _accelerometerResultStream;
+ }
+
+ StreamController? _gyroscopeEventStreamController;
+ late Stream _gyroscopeEventResultStream;
+
+ @override
+ Stream gyroscopeEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ if (_gyroscopeEventStreamController == null) {
+ _gyroscopeEventStreamController = StreamController();
+ _featureDetected(
+ () {
+ final gyroscope = Gyroscope(
+ SensorOptions(
+ frequency: samplingPeriod.frequency,
+ ),
+ );
+
+ gyroscope.start();
+
+ gyroscope.onreading = (Event _) {
+ _gyroscopeEventStreamController!.add(
+ GyroscopeEvent(
+ gyroscope.x,
+ gyroscope.y,
+ gyroscope.z,
+ DateTime.now(),
+ ),
+ );
+ }.toJS;
+
+ gyroscope.onerror = (SensorErrorEvent e) {
+ developer.log(
+ 'The gyroscope API is supported but something is wrong!',
+ error: e.error.message,
+ );
+ }.toJS;
+ },
+ apiName: 'Gyroscope()',
+ permissionName: 'gyroscope',
+ onError: () {
+ _gyroscopeEventStreamController!
+ .add(GyroscopeEvent(0, 0, 0, DateTime.now()));
+ },
+ );
+ _gyroscopeEventResultStream =
+ _gyroscopeEventStreamController!.stream.asBroadcastStream();
+
+ _gyroscopeEventStreamController!.onCancel = () {
+ _gyroscopeEventStreamController!.close();
+ };
+ }
+
+ return _gyroscopeEventResultStream;
+ }
+
+ StreamController? _userAccelerometerStreamController;
+ late Stream _userAccelerometerResultStream;
+
+ @override
+ Stream userAccelerometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ if (_userAccelerometerStreamController == null) {
+ _userAccelerometerStreamController =
+ StreamController();
+ _featureDetected(
+ () {
+ final linearAccelerationSensor = LinearAccelerationSensor(
+ SensorOptions(
+ frequency: samplingPeriod.frequency,
+ ),
+ );
+
+ linearAccelerationSensor.start();
+
+ linearAccelerationSensor.onreading = (Event _) {
+ _gyroscopeEventStreamController!.add(
+ GyroscopeEvent(
+ linearAccelerationSensor.x,
+ linearAccelerationSensor.y,
+ linearAccelerationSensor.z,
+ DateTime.now(),
+ ),
+ );
+ }.toJS;
+
+ linearAccelerationSensor.onerror = (SensorErrorEvent e) {
+ developer.log(
+ 'The linear acceleration API is supported but something is wrong!',
+ error: e.error.message,
+ );
+ }.toJS;
+ },
+ apiName: 'LinearAccelerationSensor()',
+ permissionName: 'accelerometer',
+ onError: () {
+ _userAccelerometerStreamController!
+ .add(UserAccelerometerEvent(0, 0, 0, DateTime.now()));
+ },
+ );
+ _userAccelerometerResultStream =
+ _userAccelerometerStreamController!.stream.asBroadcastStream();
+
+ _userAccelerometerStreamController!.onCancel = () {
+ _userAccelerometerStreamController!.close();
+ };
+ }
+
+ return _userAccelerometerResultStream;
+ }
+
+ StreamController? _magnetometerStreamController;
+ late Stream _magnetometerResultStream;
+
+ @override
+ Stream magnetometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ // The Magnetometer API is not supported by any modern browser.
+ if (_magnetometerStreamController == null) {
+ _magnetometerStreamController = StreamController();
+ _featureDetected(
+ () {
+ final magnetometerSensor = Magnetometer(
+ SensorOptions(
+ frequency: samplingPeriod.frequency,
+ ),
+ );
+
+ magnetometerSensor.start();
+
+ magnetometerSensor.onreading = (Event _) {
+ _gyroscopeEventStreamController!.add(
+ GyroscopeEvent(
+ magnetometerSensor.x,
+ magnetometerSensor.y,
+ magnetometerSensor.z,
+ DateTime.now(),
+ ),
+ );
+ }.toJS;
+
+ magnetometerSensor.onerror = (SensorErrorEvent e) {
+ developer.log(
+ 'The magnetometer API is supported but something is wrong!',
+ error: e,
+ );
+ }.toJS;
+ },
+ apiName: 'Magnetometer()',
+ permissionName: 'magnetometer',
+ onError: () {
+ _magnetometerStreamController!
+ .add(MagnetometerEvent(0, 0, 0, DateTime.now()));
+ },
+ );
+ _magnetometerResultStream =
+ _magnetometerStreamController!.stream.asBroadcastStream();
+
+ _magnetometerStreamController!.onCancel = () {
+ _magnetometerStreamController!.close();
+ };
+ }
+
+ return _magnetometerResultStream;
+ }
+
+ @override
+ Stream barometerEventStream({
+ Duration samplingPeriod = SensorInterval.normalInterval,
+ }) {
+ // The Barometer API does not exist and so is not supported by any modern browser.
+ // Therefore, we simply return an empty stream.
+ return const Stream.empty();
+ }
+}
+
+extension on Duration {
+ /// Converts the duration to a frequency in Hz.
+ int get frequency {
+ if (inMicroseconds <= 10) {
+ return 100;
+ }
+
+ return 1000 ~/ inMilliseconds;
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors_interop.dart b/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors_interop.dart
new file mode 100644
index 0000000000000000000000000000000000000000..73fad6d8970dc6ef79419cf27707ce7098c3b4ed
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/lib/src/web_sensors_interop.dart
@@ -0,0 +1,96 @@
+import 'dart:js_interop';
+
+/// Accelerometer API
+/// https://developer.mozilla.org/en-US/docs/Web/API/Accelerometer
+@JS('Accelerometer')
+extension type Accelerometer._(JSObject _) implements JSObject {
+ external factory Accelerometer([
+ SensorOptions options,
+ ]);
+
+ external double get x;
+ external double get y;
+ external double get z;
+
+ external set onreading(JSFunction callback);
+ external set onerror(JSFunction callback);
+
+ external void start();
+}
+
+/// Gyroscope API
+/// https://developer.mozilla.org/en-US/docs/Web/API/Gyroscope
+@JS('Gyroscope')
+extension type Gyroscope._(JSObject _) implements JSObject {
+ external factory Gyroscope([
+ SensorOptions options,
+ ]);
+
+ external double get x;
+ external double get y;
+ external double get z;
+
+ external set onreading(JSFunction callback);
+ external set onerror(JSFunction callback);
+
+ external void start();
+}
+
+/// LinearAccelerationSensor API
+/// https://developer.mozilla.org/en-US/docs/Web/API/LinearAccelerationSensor
+@JS('LinearAccelerationSensor')
+extension type LinearAccelerationSensor._(JSObject _) implements JSObject {
+ external factory LinearAccelerationSensor([
+ SensorOptions options,
+ ]);
+
+ external double get x;
+ external double get y;
+ external double get z;
+
+ external set onreading(JSFunction callback);
+ external set onerror(JSFunction callback);
+
+ external void start();
+}
+
+/// Magnetometer API
+/// https://developer.mozilla.org/en-US/docs/Web/API/Magnetometer
+@JS('Magnetometer')
+extension type Magnetometer._(JSObject _) implements JSObject {
+ external factory Magnetometer([
+ SensorOptions options,
+ ]);
+
+ external double get x;
+ external double get y;
+ external double get z;
+
+ external set onreading(JSFunction callback);
+ external set onerror(JSFunction callback);
+
+ external void start();
+}
+
+extension type SensorOptions._(JSObject _) implements JSObject {
+ external factory SensorOptions({
+ int frequency,
+ });
+}
+
+/// Event
+/// https://developer.mozilla.org/en-US/docs/Web/API/Event
+extension type Event(JSObject _) implements JSObject {}
+
+/// SensorErrorEvent
+/// https://developer.mozilla.org/en-US/docs/Web/API/SensorErrorEvent
+extension type SensorErrorEvent(JSObject _) implements JSObject {
+ external DOMException get error;
+}
+
+/// DOMException
+/// https://developer.mozilla.org/en-US/docs/Web/API/DOMException
+extension type DOMException(JSObject _) implements JSObject {
+ external String? get name;
+ external String? get message;
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/.gitignore b/packages/sensors_plus/sensors_plus/ohos/ohos/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c0f9ca4c47ca2d6aea523c5e0cf3331566bbf88a
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/.gitignore
@@ -0,0 +1,9 @@
+/node_modules
+/oh_modules
+/.preview
+/.idea
+/build
+/.cxx
+/.test
+/BuildProfile.ets
+/oh-package-lock.json5
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/build-profile.json5 b/packages/sensors_plus/sensors_plus/ohos/ohos/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..79961f96a6fe0507354b7952a378c3be2ae4bfab
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/build-profile.json5
@@ -0,0 +1,10 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default"
+ }
+ ]
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/hvigorfile.ts b/packages/sensors_plus/sensors_plus/ohos/ohos/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..47e6e1f81d365872f101585f5dbf816bcad65864
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/hvigorfile.ts
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { harTasks } from '@ohos/hvigor-ohos-plugin';
\ No newline at end of file
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/index.ets b/packages/sensors_plus/sensors_plus/ohos/ohos/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..067d05042443beeaf44dd5d2380d89c9fdfc8005
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/index.ets
@@ -0,0 +1,17 @@
+/*
+* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import SensorsPlusOhosPlugin from './src/main/ets/components/plugin/SensorsPlusOhosPlugin';
+export default SensorsPlusOhosPlugin;
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/oh-package.json5 b/packages/sensors_plus/sensors_plus/ohos/ohos/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..25ed6809aae3e16d07e8c085f9158f57a17edc2b
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/oh-package.json5
@@ -0,0 +1,11 @@
+{
+ "name": "sensors_plus_ohos",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "index.ets",
+ "author": "",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@ohos/flutter_ohos": "file:./har/flutter.har"
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/ets/components/plugin/SensorsPlusOhosPlugin.ets b/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/ets/components/plugin/SensorsPlusOhosPlugin.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8fc0cb924ef9d5bf2dab7edf6fe5242c3f60a88c
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/ets/components/plugin/SensorsPlusOhosPlugin.ets
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2024 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ FlutterPlugin,
+ FlutterPluginBinding
+} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
+import MethodChannel, {
+ MethodCallHandler,
+ MethodResult
+} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
+import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall';
+import EventChannel, { StreamHandler, EventSink } from '@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel';
+import { BinaryMessenger } from '@ohos/flutter_ohos';
+import sensor from '@ohos.sensor';
+import { BusinessError } from '@kit.BasicServicesKit';
+import systemDateTime from '@ohos.systemDateTime';
+
+class StreamHandlerImpl implements StreamHandler {
+ private event: EventSink | null = null;
+ private sensorId?: sensor.SensorId;
+ private currentInterval: number = 200000000;
+
+ constructor(sensorId: sensor.SensorId) {
+ this.sensorId = sensorId;
+ this.initSensorData(this.currentInterval);
+ }
+
+ private initSensorData(interval: number): void {
+ switch (this.sensorId) {
+ case sensor.SensorId.LINEAR_ACCELEROMETER:
+ this.listenLinearAccelerometer(interval);
+ break;
+ case sensor.SensorId.ACCELEROMETER:
+ this.listenAccelerometer(interval);
+ break;
+ case sensor.SensorId.GYROSCOPE:
+ this.listenGyroscope(interval);
+ break;
+ case sensor.SensorId.MAGNETIC_FIELD:
+ this.listenMagnetic(interval);
+ break;
+ case sensor.SensorId.BAROMETER:
+ this.listenBarometer(interval);
+ break;
+ }
+ }
+
+ // user加速度计传感器
+ private listenLinearAccelerometer(interval: number): void {
+ try {
+ if(this.currentInterval !== interval){
+ sensor.off(sensor.SensorId.LINEAR_ACCELEROMETER);
+ this.currentInterval = interval;
+ }
+ let timestampMicroAtBoot = (systemDateTime.getTime(true) / 1000) - (systemDateTime.getUptime(systemDateTime.TimeType.ACTIVE, true) / 1000);
+ sensor.on(sensor.SensorId.LINEAR_ACCELEROMETER, (data: sensor.LinearAccelerometerResponse) => {
+ if (this.event) {
+ let arr: Array = [4];
+ let timestampMicro = (timestampMicroAtBoot + (data.timestamp * 1000)) / 1000000;
+ arr[0] = data.x;
+ arr[1] = data.y;
+ arr[2] = data.z;
+ arr[3] = timestampMicro;
+ if (Number.isInteger(data.x)) {
+ arr[0] = data.x + 0.00000000001;
+ }
+ if (Number.isInteger(data.y)) {
+ arr[1] = data.y + 0.00000000001;
+ }
+ if (Number.isInteger(data.z)) {
+ arr[2] = data.z + 0.00000000001;
+ }
+ if (Number.isInteger(timestampMicro)) {
+ arr[3] = timestampMicro + 0.00000000001;
+ }
+ this.event.success(arr);
+ }
+ }, { interval: interval });
+ } catch (error) {
+ let e: BusinessError = error as BusinessError;
+ console.error(`Failed to invoke on. Code: ${e.code}, message: ${e.message}`);
+ }
+ }
+
+ // 加速度计传感器
+ private listenAccelerometer(interval: number): void {
+ try {
+ if(this.currentInterval !== interval){
+ sensor.off(sensor.SensorId.ACCELEROMETER);
+ this.currentInterval = interval;
+ }
+ let timestampMicroAtBoot = (systemDateTime.getTime(true) / 1000) - systemDateTime.getUptime(systemDateTime.TimeType.ACTIVE, true) / 1000;
+ sensor.on(sensor.SensorId.ACCELEROMETER, (data: sensor.AccelerometerResponse) => {
+ if (this.event) {
+ let arr: Array = [4];
+ let timestampMicro = (timestampMicroAtBoot + (data.timestamp * 1000)) / 1000000;
+ arr[0] = data.x;
+ arr[1] = data.y;
+ arr[2] = data.z;
+ arr[3] = timestampMicro;
+ if (Number.isInteger(data.x)) {
+ arr[0] = data.x + 0.00000000001;
+ }
+ if (Number.isInteger(data.y)) {
+ arr[1] = data.y + 0.00000000001;
+ }
+ if (Number.isInteger(data.z)) {
+ arr[2] = data.z + 0.00000000001;
+ }
+ if (Number.isInteger(timestampMicro)) {
+ arr[3] = timestampMicro + 0.00000000001;
+ }
+ this.event.success(arr);
+ }
+ }, { interval: interval });
+ } catch (error) {
+ let e: BusinessError = error as BusinessError;
+ console.error(`Failed to invoke on. Code: ${e.code}, message: ${e.message}`);
+ }
+ }
+
+ // 陀螺仪传感器
+ private listenGyroscope(interval: number): void {
+ try {
+ if(this.currentInterval !== interval){
+ sensor.off(sensor.SensorId.GYROSCOPE);
+ this.currentInterval = interval;
+ }
+ let timestampMicroAtBoot = (systemDateTime.getTime(true) / 1000) - systemDateTime.getUptime(systemDateTime.TimeType.ACTIVE, true) / 1000;
+ sensor.on(sensor.SensorId.GYROSCOPE, (data: sensor.GyroscopeResponse) => {
+ let timestampMicro = (timestampMicroAtBoot + (data.timestamp * 1000)) / 1000000;
+ if (this.event) {
+ let arr: Array = [4];
+ arr[0] = data.x;
+ arr[1] = data.y;
+ arr[2] = data.z;
+ arr[3] = timestampMicro;
+ if (Number.isInteger(data.x)) {
+ arr[0] = data.x + 0.00000000001;
+ }
+ if (Number.isInteger(data.y)) {
+ arr[1] = data.y + 0.00000000001;
+ }
+ if (Number.isInteger(data.z)) {
+ arr[2] = data.z + 0.00000000001;
+ }
+ if (Number.isInteger(timestampMicro)) {
+ arr[3] = timestampMicro + 0.00000000001;
+ }
+ this.event.success(arr);
+ }
+ }, { interval: interval });
+ } catch (error) {
+ let e: BusinessError = error as BusinessError;
+ console.error(`Failed to invoke on. Code: ${e.code}, message: ${e.message}`);
+ }
+ }
+
+ // 磁力计传感器
+ private listenMagnetic(interval: number): void {
+ try {
+ if(this.currentInterval !== interval){
+ sensor.off(sensor.SensorId.MAGNETIC_FIELD);
+ this.currentInterval = interval;
+ }
+ let timestampMicroAtBoot = (systemDateTime.getTime(true) / 1000) - systemDateTime.getUptime(systemDateTime.TimeType.ACTIVE, true) / 1000;
+ sensor.on(sensor.SensorId.MAGNETIC_FIELD, (data: sensor.MagneticFieldResponse) => {
+ if (this.event) {
+ let arr: Array = [4];
+ let timestampMicro = (timestampMicroAtBoot + (data.timestamp * 1000)) / 1000000;
+ arr[0] = data.x;
+ arr[1] = data.y;
+ arr[2] = data.z;
+ arr[3] = timestampMicro;
+ if (Number.isInteger(data.x)) {
+ arr[0] = data.x + 0.00000000001;
+ }
+ if (Number.isInteger(data.y)) {
+ arr[1] = data.y + 0.00000000001;
+ }
+ if (Number.isInteger(data.z)) {
+ arr[2] = data.z + 0.00000000001;
+ }
+ if (Number.isInteger(timestampMicro)) {
+ arr[3] = timestampMicro + 0.00000000001;
+ }
+ this.event.success(arr);
+ }
+ }, { interval: interval });
+ } catch (error) {
+ let e: BusinessError = error as BusinessError;
+ console.error(`Failed to invoke on. Code: ${e.code}, message: ${e.message}`);
+ }
+ }
+
+ // 气压传感器
+ private listenBarometer(interval: number): void {
+ try {
+ if(this.currentInterval !== interval){
+ sensor.off(sensor.SensorId.BAROMETER);
+ this.currentInterval = interval;
+ }
+ let timestampMicroAtBoot = (systemDateTime.getTime(true) / 1000) - systemDateTime.getUptime(systemDateTime.TimeType.ACTIVE, true) / 1000;
+ sensor.on(sensor.SensorId.BAROMETER, (data: sensor.BarometerResponse) => {
+ if (this.event) {
+ let arr: Array = [2];
+ let timestampMicro = (timestampMicroAtBoot + (data.timestamp * 1000)) / 1000000;
+ arr[0] = data.pressure;
+ arr[1] = timestampMicro;
+ if (Number.isInteger(data.pressure)) {
+ arr[0] = data.pressure + 0.00000000001;
+ }
+ if (Number.isInteger(timestampMicro)) {
+ arr[1] = timestampMicro + 0.00000000001;
+ }
+ this.event.success(arr);
+ }
+ }, { interval: interval });
+ } catch (error) {
+ let e: BusinessError = error as BusinessError;
+ console.error(`Failed to invoke on. Code: ${e.code}, message: ${e.message}`);
+ }
+ }
+
+ setUpdateInterval(interval: number) {
+ switch (interval) {
+ case 20000:
+ this.initSensorData(20000000);
+ break;
+ case 66667 :
+ this.initSensorData(66667000);
+ break;
+ case 200000:
+ this.initSensorData(200000000);
+ break;
+ case 500000:
+ this.initSensorData(500000000);
+ break;
+ case 1000000:
+ this.initSensorData(1000000000);
+ break;
+ }
+ }
+
+ onListen(args: ESObject, events: EventSink): void {
+ this.event = events;
+ }
+
+ onCancel(args: ESObject): void {
+ }
+}
+
+/** SensorsPlusOhosPlugin **/
+export default class SensorsPlusOhosPlugin implements FlutterPlugin, MethodCallHandler {
+ private channel: MethodChannel | null = null;
+
+ private ACCELEROMETER_CHANNEL_NAME = 'dev.fluttercommunity.plus/sensors/accelerometer';
+ private USER_ACCELEROMETER_CHANNEL_NAME = 'dev.fluttercommunity.plus/sensors/user_accel';
+ private GYROSCOPE_CHANNEL_NAME = 'dev.fluttercommunity.plus/sensors/gyroscope';
+ private MAGNETOMETER_CHANNEL_NAME = 'dev.fluttercommunity.plus/sensors/magnetometer';
+ private BAROMETER_CHANNEL_NAME = 'dev.fluttercommunity.plus/sensors/barometer';
+
+ private accelerometerChannel: EventChannel | null = null;
+ private gyroscopeChannel: EventChannel | null = null;
+ private magnetometerChannel: EventChannel | null = null;
+ private userAccelerometerChannel: EventChannel | null = null;
+ private barometerChannel: EventChannel | null = null;
+
+ private accelerationStreamHandler: StreamHandlerImpl | null = null;
+ private gyroScopeStreamHandler: StreamHandlerImpl | null = null;
+ private magnetometerStreamHandler: StreamHandlerImpl | null = null;
+ private userAccelerationStreamHandler: StreamHandlerImpl | null = null;
+ private barometerStreamHandler: StreamHandlerImpl | null = null;
+
+ constructor() {
+ }
+
+ getUniqueClassName(): string {
+ return "SensorsPlusOhosPlugin"
+ }
+
+ onAttachedToEngine(binding: FlutterPluginBinding): void {
+ this.channel = new MethodChannel(binding.getBinaryMessenger(), "dev.fluttercommunity.plus/sensors/method");
+ this.channel.setMethodCallHandler(this)
+ this.setupEventChannels(binding.getApplicationContext(), binding.getBinaryMessenger());
+ }
+
+ onDetachedFromEngine(binding: FlutterPluginBinding): void {
+ if (this.channel != null) {
+ this.channel.setMethodCallHandler(null)
+ }
+ }
+
+ onMethodCall(call: MethodCall, result: MethodResult): void {
+ switch (call.method) {
+ case 'setAccelerationSamplingPeriod':
+ this.accelerationStreamHandler?.setUpdateInterval(call.args as number);
+ break;
+ case 'setGyroscopeSamplingPeriod':
+ this.gyroScopeStreamHandler?.setUpdateInterval(call.args as number);
+ break;
+ case 'setUserAccelerometerSamplingPeriod':
+ this.userAccelerationStreamHandler?.setUpdateInterval(call.args as number);
+ break;
+ case 'setMagnetometerSamplingPeriod':
+ this.magnetometerStreamHandler?.setUpdateInterval(call.args as number);
+ break;
+ case 'setBarometerSamplingPeriod':
+ this.barometerStreamHandler?.setUpdateInterval(call.args as number);
+ break;
+ default:
+ result.notImplemented();
+ }
+ }
+
+ private setupEventChannels(context: Context, messenger: BinaryMessenger) {
+ // user加速度计
+ this.userAccelerometerChannel = new EventChannel(messenger, this.USER_ACCELEROMETER_CHANNEL_NAME);
+ this.userAccelerationStreamHandler = new StreamHandlerImpl(sensor.SensorId.LINEAR_ACCELEROMETER);
+ this.userAccelerometerChannel.setStreamHandler(this.userAccelerationStreamHandler);
+
+ // 加速度计
+ this.accelerometerChannel = new EventChannel(messenger, this.ACCELEROMETER_CHANNEL_NAME);
+ this.accelerationStreamHandler = new StreamHandlerImpl(sensor.SensorId.ACCELEROMETER);
+ this.accelerometerChannel.setStreamHandler(this.accelerationStreamHandler);
+
+ // 磁力计
+ this.magnetometerChannel = new EventChannel(messenger, this.MAGNETOMETER_CHANNEL_NAME);
+ this.magnetometerStreamHandler = new StreamHandlerImpl(sensor.SensorId.MAGNETIC_FIELD);
+ this.magnetometerChannel.setStreamHandler(this.magnetometerStreamHandler);
+
+ // 陀螺仪
+ this.gyroscopeChannel = new EventChannel(messenger, this.GYROSCOPE_CHANNEL_NAME);
+ this.gyroScopeStreamHandler = new StreamHandlerImpl(sensor.SensorId.GYROSCOPE);
+ this.gyroscopeChannel.setStreamHandler(this.gyroScopeStreamHandler);
+
+ // 气压计
+ this.barometerChannel = new EventChannel(messenger, this.BAROMETER_CHANNEL_NAME);
+ this.barometerStreamHandler = new StreamHandlerImpl(sensor.SensorId.BAROMETER);
+ this.barometerChannel.setStreamHandler(this.barometerStreamHandler);
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/module.json5 b/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..41a87d178d2b386a9abd3286aaadcc09c2eeaec8
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/ohos/src/main/module.json5
@@ -0,0 +1,10 @@
+{
+ "module": {
+ "name": "sensors_plus_ohos",
+ "type": "har",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ]
+ }
+}
diff --git a/packages/sensors_plus/sensors_plus/ohos/pubspec.yaml b/packages/sensors_plus/sensors_plus/ohos/pubspec.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..de84a300428ac958138eb2c052db6729cf3e4be5
--- /dev/null
+++ b/packages/sensors_plus/sensors_plus/ohos/pubspec.yaml
@@ -0,0 +1,76 @@
+name: sensors_plus_ohos
+description: Flutter plugin for accessing accelerometer, gyroscope, and magnetometer sensors On OpenHarmony
+repository: https://github.com/harmonycandies/sensors_plus_ohos
+version: 0.0.3
+topics:
+ - sensors
+ - sensors-plus
+ - ohos
+ - harmony-os
+ - openharmony
+
+
+environment:
+ sdk: '>=2.19.6 <3.0.0'
+ flutter: ">=3.7.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ sensors_plus_platform_interface: ^2.0.0
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ # This section identifies this Flutter project as a plugin project.
+ # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
+ # which should be registered in the plugin registry. This is required for
+ # using method channels.
+ # The Android 'package' specifies package in which the registered class is.
+ # This is required for using method channels on Android.
+ # The 'ffiPlugin' specifies that native code should be built and bundled.
+ # This is required for using `dart:ffi`.
+ # All these are used by the tooling to maintain consistency when
+ # adding or updating assets for this project.
+ plugin:
+ platforms:
+ ohos:
+ pluginClass: SensorsPlusOhosPlugin
+
+ # To add assets to your plugin package, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+ #
+ # For details regarding assets in packages, see
+ # https://flutter.dev/assets-and-images/#from-packages
+ #
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # To add custom fonts to your plugin package, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts in packages, see
+ # https://flutter.dev/custom-fonts/#from-packages