-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
352 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
92 changes: 69 additions & 23 deletions
92
android/src/main/kotlin/com/example/workout/WorkoutPlugin.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,82 @@ | ||
package com.example.workout | ||
|
||
import android.content.Context | ||
import android.hardware.Sensor | ||
import android.hardware.SensorEvent | ||
import android.hardware.SensorEventListener | ||
import android.hardware.SensorManager | ||
import android.hardware.SensorManager.SENSOR_DELAY_FASTEST | ||
import androidx.annotation.NonNull | ||
|
||
import androidx.core.content.ContextCompat.getSystemService | ||
import io.flutter.embedding.engine.plugins.FlutterPlugin | ||
import io.flutter.plugin.common.MethodCall | ||
import io.flutter.plugin.common.MethodChannel | ||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler | ||
import io.flutter.plugin.common.MethodChannel.Result | ||
import io.flutter.plugin.common.PluginRegistry.Registrar | ||
|
||
/** WorkoutPlugin */ | ||
class WorkoutPlugin: FlutterPlugin, MethodCallHandler { | ||
/// The MethodChannel that will the communication between Flutter and native Android | ||
/// | ||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it | ||
/// when the Flutter Engine is detached from the Activity | ||
private lateinit var channel : MethodChannel | ||
|
||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { | ||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "workout") | ||
channel.setMethodCallHandler(this) | ||
} | ||
|
||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { | ||
if (call.method == "getPlatformVersion") { | ||
result.success("Android ${android.os.Build.VERSION.RELEASE}") | ||
} else { | ||
result.notImplemented() | ||
class WorkoutPlugin : FlutterPlugin, MethodCallHandler, SensorEventListener { | ||
private lateinit var channel: MethodChannel | ||
private lateinit var context: Context | ||
private lateinit var sensorManager: SensorManager | ||
|
||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { | ||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "workout") | ||
channel.setMethodCallHandler(this) | ||
|
||
context = flutterPluginBinding.applicationContext | ||
} | ||
|
||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { | ||
if (call.method == "start") { | ||
val error = start(call.arguments) | ||
if (error.isEmpty()) { | ||
result.success("Sensors started") | ||
} else { | ||
result.error(error, null, null) | ||
} | ||
} else { | ||
result.notImplemented() | ||
} | ||
} | ||
|
||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { | ||
channel.setMethodCallHandler(null) | ||
} | ||
|
||
private fun start(arguments: Any): String { | ||
try { | ||
val argumentList = arguments as List<String> | ||
argumentList.forEach { | ||
if (it == "heartRate") { | ||
startHeartRate() | ||
} | ||
} | ||
} catch (e: Error) { | ||
return e.localizedMessage ?: "Error starting sensors" | ||
} | ||
|
||
return "" | ||
} | ||
|
||
private fun startHeartRate() { | ||
sensorManager = getSystemService(context, SensorManager::class.java) as SensorManager | ||
val hrSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE) | ||
sensorManager.registerListener(this, hrSensor, SensorManager.SENSOR_DELAY_NORMAL) | ||
|
||
|
||
sensorManager.registerListener(this, hrSensor, SENSOR_DELAY_FASTEST); | ||
} | ||
|
||
private fun stopHeartRate() { | ||
sensorManager.unregisterListener(this) | ||
} | ||
|
||
override fun onSensorChanged(event: SensorEvent?) { | ||
if (event == null) return; | ||
channel.invokeMethod("dataReceived", listOf(event.sensor?.name | ||
?: "Unknown", event.values[0].toString())) | ||
} | ||
} | ||
|
||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { | ||
channel.setMethodCallHandler(null) | ||
} | ||
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.cproject | ||
.sign | ||
crash-info/ | ||
Debug/ | ||
Release/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
cmake_minimum_required(VERSION 3.19) | ||
project(tizen) | ||
|
||
set(CMAKE_CXX_STANDARD 14) | ||
|
||
include_directories(inc) | ||
include_directories(src) | ||
include_directories(../../../../engine_tizen/shell/platform/common/cpp/client_wrapper/include) | ||
include_directories(../../../../engine_tizen/shell/platform/common/cpp/public) | ||
include_directories(../../../../../tizen-studio/platforms/tizen-4.0/wearable/rootstraps/wearable-4.0-device.core/usr/include/sensor) | ||
include_directories(../../../../../tizen-studio/platforms/tizen-4.0/wearable/rootstraps/wearable-4.0-device.core/usr/include/dlog) | ||
|
||
add_executable(tizen | ||
inc/health_tizen_plugin.h | ||
src/health_tizen_plugin.cc | ||
src/log.h) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#ifndef FLUTTER_PLUGIN_HEALTH_TIZEN_PLUGIN_H_ | ||
#define FLUTTER_PLUGIN_HEALTH_TIZEN_PLUGIN_H_ | ||
|
||
#include <flutter_plugin_registrar.h> | ||
|
||
#ifdef FLUTTER_PLUGIN_IMPL | ||
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) | ||
#else | ||
#define FLUTTER_PLUGIN_EXPORT | ||
#endif | ||
|
||
#if defined(__cplusplus) | ||
extern "C" { | ||
#endif | ||
|
||
FLUTTER_PLUGIN_EXPORT void HealthTizenPluginRegisterWithRegistrar( | ||
FlutterDesktopPluginRegistrarRef registrar); | ||
|
||
#if defined(__cplusplus) | ||
} // extern "C" | ||
#endif | ||
|
||
#endif // FLUTTER_PLUGIN_HEALTH_TIZEN_PLUGIN_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# See https://docs.tizen.org/application/tizen-studio/native-tools/project-conversion | ||
# for details. | ||
|
||
APPNAME = health_tizen_plugin | ||
type = sharedLib | ||
profile = common-4.0 | ||
|
||
# Source files | ||
USER_SRCS += src/health_tizen_plugin.cc | ||
|
||
# User defines | ||
USER_DEFS = | ||
USER_UNDEFS = | ||
USER_CPP_DEFS = TIZEN_DEPRECATION DEPRECATION_WARNING FLUTTER_PLUGIN_IMPL | ||
USER_CPP_UNDEFS = | ||
|
||
# Compiler/linker flags | ||
USER_CFLAGS_MISC = | ||
USER_CPPFLAGS_MISC = -c -fmessage-length=0 | ||
USER_LFLAGS = | ||
|
||
# Libraries and objects | ||
# To provide libraries for your plugin, you must put them in specific | ||
# directories that match their supporting cpu architecture type. | ||
# Due to compatibility issue with Tizen CLI, directory names must be armel for arm | ||
# and i586 for x86. | ||
USER_LIB_DIRS = lib/${BUILD_ARCH} | ||
USER_LIBS = | ||
USER_OBJS = | ||
|
||
# User includes | ||
USER_INC_DIRS = inc src | ||
USER_INC_FILES = | ||
USER_CPP_INC_FILES = |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#include "health_tizen_plugin.h" | ||
|
||
#include <flutter/method_channel.h> | ||
#include <flutter/plugin_registrar.h> | ||
#include <flutter/standard_method_codec.h> | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <sstream> | ||
#include <string> | ||
#include <sensor.h> | ||
#include <variant> | ||
|
||
#include "log.h" | ||
|
||
using namespace std; | ||
using namespace flutter; | ||
|
||
class HealthTizenPlugin : public Plugin { | ||
public: | ||
static void RegisterWithRegistrar(PluginRegistrar *registrar) { | ||
auto plugin = make_unique<HealthTizenPlugin>(registrar); | ||
registrar->AddPlugin(move(plugin)); | ||
} | ||
|
||
explicit HealthTizenPlugin(PluginRegistrar *registrar) { | ||
auto channel = | ||
make_unique<MethodChannel<EncodableValue> >( | ||
registrar->messenger(), "health_tizen", | ||
&StandardMethodCodec::GetInstance()); | ||
|
||
channel->SetMethodCallHandler( | ||
[plugin_pointer = this](const auto &call, auto result) { | ||
plugin_pointer->HandleMethodCall(call, move(result)); | ||
}); | ||
|
||
channel_ = std::move(channel); | ||
} | ||
|
||
~HealthTizenPlugin() override = default; | ||
|
||
private: | ||
void HandleMethodCall( | ||
const MethodCall<EncodableValue> &method_call, | ||
unique_ptr<MethodResult<EncodableValue> > result) { | ||
const auto &arguments = *method_call.arguments(); | ||
|
||
if (method_call.method_name() == "start") { | ||
string error = start(arguments); | ||
if (error.empty()) { | ||
result->Success(); | ||
} else { | ||
result->Error("1", error); | ||
} | ||
} else if (method_call.method_name() == "stop") { | ||
stop(); | ||
result->Success(); | ||
} else { | ||
result->NotImplemented(); | ||
} | ||
} | ||
|
||
string start(const EncodableValue arguments) { | ||
string error = ""; | ||
if (holds_alternative<EncodableList>(arguments)) { | ||
const EncodableList argumentList = get<EncodableList>(arguments); | ||
for (int i = 0; i < argumentList.size(); i++) { | ||
string stringArgument = get<string>(argumentList[i]); | ||
if (stringArgument == "hrm") { | ||
error += "" + startHrm(); | ||
} else if (stringArgument == "pedometer") { | ||
error += "" + startPedometer(); | ||
} | ||
} | ||
} | ||
|
||
return error; | ||
} | ||
|
||
|
||
sensor_listener_h hrListener; | ||
|
||
string startHrm() { | ||
sensor_h sensor; | ||
|
||
bool supported; | ||
int error = sensor_is_supported(SENSOR_HRM, &supported); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_is_supported error: " + to_string(error); | ||
} | ||
|
||
if (!supported) { | ||
return "SENSOR_HRM not supported"; | ||
} | ||
|
||
int count; | ||
sensor_h *list; | ||
|
||
error = sensor_get_sensor_list(SENSOR_HRM, &list, &count); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_get_sensor_list error: " + to_string(error); | ||
} else { | ||
free(list); | ||
} | ||
|
||
error = sensor_get_default_sensor(SENSOR_HRM, &sensor); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_get_default_sensor error: " + to_string(error); | ||
} | ||
|
||
// creating an event listener | ||
error = sensor_create_listener(sensor, &hrListener); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_create_listener error: " + to_string(error); | ||
} | ||
|
||
string userData = "Why do I need this?"; | ||
// Callback for sensor value change | ||
error = sensor_listener_set_event_cb(hrListener, 1000, on_sensor_event, &userData); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_listener_set_event_cb error: " + to_string(error); | ||
} | ||
|
||
error = sensor_listener_start(hrListener); | ||
if (error != SENSOR_ERROR_NONE) { | ||
return "sensor_listener_start error: " + to_string(error); | ||
} | ||
|
||
return ""; | ||
} | ||
|
||
string startPedometer() { | ||
return ""; | ||
} | ||
|
||
static void on_sensor_event(sensor_h sensor, sensor_event_s *event, void *user_data) { | ||
// Select a specific sensor with a sensor handle | ||
sensor_type_e type; | ||
sensor_get_type(sensor, &type); | ||
|
||
switch (type) { | ||
case SENSOR_HRM: { | ||
EncodableList wrapped = {EncodableValue("hrm"), EncodableValue(event->values[0])}; | ||
auto arguments = std::make_unique<EncodableValue>(wrapped); | ||
channel_->InvokeMethod("dataReceived", move(arguments)); | ||
break; | ||
} | ||
case SENSOR_HUMAN_PEDOMETER: { | ||
break; | ||
} | ||
default: { | ||
dlog_print(DLOG_ERROR, LOG_TAG, "Unknown event"); | ||
} | ||
} | ||
} | ||
|
||
void stop() { | ||
sensor_listener_stop(hrListener); | ||
sensor_destroy_listener(hrListener); | ||
} | ||
|
||
static unique_ptr<MethodChannel<EncodableValue>> channel_; | ||
}; | ||
|
||
unique_ptr<MethodChannel<EncodableValue>> HealthTizenPlugin::channel_; | ||
|
||
void HealthTizenPluginRegisterWithRegistrar( | ||
FlutterDesktopPluginRegistrarRef registrar) { | ||
HealthTizenPlugin::RegisterWithRegistrar( | ||
PluginRegistrarManager::GetInstance() | ||
->GetRegistrar<PluginRegistrar>(registrar)); | ||
} |
Oops, something went wrong.