Skip to content

Commit

Permalink
Initial work
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexios80 committed May 4, 2021
1 parent 3daacb5 commit f290d24
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 25 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,7 @@ app.*.symbols
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock
!/dev/ci/**/Gemfile.lock

# CMake
cmake-build-*/
5 changes: 5 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

// These are so android libraries can be referenced without seeing red everywhere
// implementation 'androidx.core:core-ktx:1.3.2'
// implementation 'androidx.appcompat:appcompat:1.2.0'
// implementation fileTree(dir: 'libs', include: ['*.jar'])
}
Binary file added android/libs/flutter.jar
Binary file not shown.
92 changes: 69 additions & 23 deletions android/src/main/kotlin/com/example/workout/WorkoutPlugin.kt
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) {}
}
5 changes: 4 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ flutter:
platforms:
android:
package: com.example.workout
pluginClass: WorkoutPlugin
pluginClass: WorkoutPlugin
tizen:
pluginClass: HealthTizenPlugin
fileName: health_tizen_plugin.h
5 changes: 5 additions & 0 deletions tizen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.cproject
.sign
crash-info/
Debug/
Release/
16 changes: 16 additions & 0 deletions tizen/CMakeLists.txt
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)
23 changes: 23 additions & 0 deletions tizen/inc/health_tizen_plugin.h
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_
34 changes: 34 additions & 0 deletions tizen/project_def.prop
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 =
172 changes: 172 additions & 0 deletions tizen/src/health_tizen_plugin.cc
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));
}
Loading

0 comments on commit f290d24

Please sign in to comment.