5
5
#include " platform_channel.h"
6
6
7
7
#include < app.h>
8
+ #include < feedback.h>
8
9
9
10
#include < map>
10
11
@@ -28,6 +29,146 @@ PlatformChannel::PlatformChannel(flutter::BinaryMessenger* messenger,
28
29
29
30
PlatformChannel::~PlatformChannel () {}
30
31
32
+ namespace {
33
+
34
+ class FeedbackManager {
35
+ public:
36
+ enum class ResultCode {
37
+ kOk ,
38
+ kNotSupportedError ,
39
+ kPermissionDeniedError ,
40
+ kUnknownError
41
+ };
42
+
43
+ static std::string GetVibrateVariantName (const char * haptic_feedback_type) {
44
+ FT_LOGD (
45
+ " Enter FeedbackManager::GetVibrateVariantName(): haptic_feedback_type: "
46
+ " (%s)" ,
47
+ haptic_feedback_type);
48
+
49
+ if (!haptic_feedback_type) {
50
+ return " HapticFeedback.vibrate" ;
51
+ }
52
+
53
+ const size_t kPrefixToRemoveLen = strlen (" HapticFeedbackType." );
54
+
55
+ assert (strlen (haptic_feedback_type) >= kPrefixToRemoveLen );
56
+
57
+ const std::string kHapticFeedbackPrefix = " HapticFeedback." ;
58
+
59
+ return kHapticFeedbackPrefix +
60
+ std::string{haptic_feedback_type + kPrefixToRemoveLen };
61
+ }
62
+
63
+ static std::string GetErrorMessage (const std::string& method_name,
64
+ ResultCode result_code) {
65
+ FT_LOGD (
66
+ " Enter FeedbackManager::GetErrorMessage(): method_name: (%s), "
67
+ " result_code: [%d]" ,
68
+ method_name.c_str (), static_cast <int >(result_code));
69
+
70
+ switch (result_code) {
71
+ case ResultCode::kNotSupportedError :
72
+ return method_name + " () is not supported" ;
73
+ case ResultCode::kPermissionDeniedError :
74
+ return std::string{" No permission to run " } + method_name +
75
+ " (). Add "
76
+ " \" http://tizen.org/privilege/feedback\" privilege to "
77
+ " tizen-manifest.xml "
78
+ " to use this method" ;
79
+ case ResultCode::kUnknownError :
80
+ default :
81
+ return std::string{" An unknown error on " } + method_name + " () call" ;
82
+ }
83
+ }
84
+
85
+ #if defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
86
+
87
+ static FeedbackManager& GetInstance () {
88
+ FT_LOGD (" Enter FeedbackManager::GetInstance()" );
89
+
90
+ static FeedbackManager instance;
91
+ return instance;
92
+ }
93
+
94
+ FeedbackManager (const FeedbackManager&) = delete;
95
+ FeedbackManager& operator =(const FeedbackManager&) = delete ;
96
+
97
+ ResultCode Vibrate () {
98
+ FT_LOGD (" Enter FeedbackManager::Vibrate()" );
99
+
100
+ if (ResultCode::kOk != initialization_status_) {
101
+ FT_LOGE (" Cannot run Vibrate(): initialization_status_: [%d]" ,
102
+ static_cast <int >(initialization_status_));
103
+ return initialization_status_;
104
+ }
105
+
106
+ auto ret =
107
+ feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
108
+ if (FEEDBACK_ERROR_NONE == ret) {
109
+ FT_LOGD (" feedback_play_type() succeeded" );
110
+ return ResultCode::kOk ;
111
+ }
112
+ FT_LOGE (" feedback_play_type() failed with error: [%d] (%s)" , ret,
113
+ get_error_message (ret));
114
+
115
+ return NativeErrorToResultCode (ret);
116
+ }
117
+
118
+ private:
119
+ static ResultCode NativeErrorToResultCode (int native_error_code) {
120
+ FT_LOGD (" Enter NativeErrorToResultCode: native_error_code: [%d]" ,
121
+ native_error_code);
122
+
123
+ switch (native_error_code) {
124
+ case FEEDBACK_ERROR_NONE:
125
+ return ResultCode::kOk ;
126
+ case FEEDBACK_ERROR_NOT_SUPPORTED:
127
+ return ResultCode::kNotSupportedError ;
128
+ case FEEDBACK_ERROR_PERMISSION_DENIED:
129
+ return ResultCode::kPermissionDeniedError ;
130
+ case FEEDBACK_ERROR_OPERATION_FAILED:
131
+ case FEEDBACK_ERROR_INVALID_PARAMETER:
132
+ case FEEDBACK_ERROR_NOT_INITIALIZED:
133
+ default :
134
+ return ResultCode::kUnknownError ;
135
+ }
136
+ }
137
+
138
+ FeedbackManager () {
139
+ FT_LOGD (" Enter FeedbackManager::FeedbackManager()" );
140
+
141
+ auto ret = feedback_initialize ();
142
+ if (FEEDBACK_ERROR_NONE != ret) {
143
+ FT_LOGE (" feedback_initialize() failed with error: [%d] (%s)" , ret,
144
+ get_error_message (ret));
145
+ initialization_status_ = NativeErrorToResultCode (ret);
146
+ return ;
147
+ }
148
+ FT_LOGD (" feedback_initialize() succeeded" );
149
+
150
+ initialization_status_ = ResultCode::kOk ;
151
+ }
152
+
153
+ ~FeedbackManager () {
154
+ FT_LOGD (" Enter FeedbackManager::~FeedbackManager" );
155
+
156
+ auto ret = feedback_deinitialize ();
157
+ if (FEEDBACK_ERROR_NONE != ret) {
158
+ FT_LOGE (" feedback_deinitialize() failed with error: [%d] (%s)" , ret,
159
+ get_error_message (ret));
160
+ return ;
161
+ }
162
+ FT_LOGD (" feedback_deinitialize() succeeded" );
163
+ }
164
+
165
+ ResultCode initialization_status_ = ResultCode::kUnknownError ;
166
+
167
+ #endif // defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
168
+ };
169
+
170
+ } // namespace
171
+
31
172
void PlatformChannel::HandleMethodCall (
32
173
const flutter::MethodCall<rapidjson::Document>& call,
33
174
std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
@@ -39,7 +180,39 @@ void PlatformChannel::HandleMethodCall(
39
180
} else if (method == " SystemSound.play" ) {
40
181
result->NotImplemented ();
41
182
} else if (method == " HapticFeedback.vibrate" ) {
42
- result->NotImplemented ();
183
+ FT_LOGD (" HapticFeedback.vibrate() call received" );
184
+
185
+ const std::string error_message = " Could not vibrate" ;
186
+
187
+ #if defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
188
+ /*
189
+ * We use a single type of vibration (FEEDBACK_PATTERN_SIP) to implement
190
+ * HapticFeedback's vibrate, lightImpact, mediumImpact, heavyImpact
191
+ * and selectionClick methods, because Tizen's "feedback" module
192
+ * has no dedicated vibration types for them.
193
+ * Thus, we ignore the "arguments" contents for "HapticFeedback.vibrate"
194
+ * calls.
195
+ */
196
+
197
+ auto ret = FeedbackManager::GetInstance ().Vibrate ();
198
+ if (FeedbackManager::ResultCode::kOk == ret) {
199
+ result->Success ();
200
+ return ;
201
+ }
202
+
203
+ const auto vibrate_variant_name =
204
+ FeedbackManager::GetVibrateVariantName (call.arguments ()[0 ].GetString ());
205
+ const auto error_cause =
206
+ FeedbackManager::GetErrorMessage (vibrate_variant_name, ret);
207
+ FT_LOGE (" %s: %s" , error_cause.c_str (), error_message.c_str ());
208
+ #else
209
+ const auto vibrate_variant_name =
210
+ FeedbackManager::GetVibrateVariantName (call.arguments ()[0 ].GetString ());
211
+ const auto error_cause = FeedbackManager::GetErrorMessage (
212
+ vibrate_variant_name, FeedbackManager::ResultCode::kNotSupportedError );
213
+ #endif // defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
214
+
215
+ result->Error (error_cause, error_message);
43
216
} else if (method == " Clipboard.getData" ) {
44
217
result->NotImplemented ();
45
218
} else if (method == " Clipboard.setData" ) {
0 commit comments