5
5
#include " image_picker_tizen_plugin.h"
6
6
7
7
#include < app_control.h>
8
- #include < assert.h>
9
8
#include < flutter/method_channel.h>
10
9
#include < flutter/plugin_registrar.h>
11
10
#include < flutter/standard_method_codec.h>
12
- #ifndef TV_PROFILE
13
- #include < privacy_privilege_manager.h>
14
- #endif
15
11
12
+ #include < cassert>
16
13
#include < memory>
17
14
#include < string>
15
+ #include < variant>
18
16
19
17
#include " image_resize.h"
20
- #include " log.h"
18
+ #include " permission_manager.h"
19
+
20
+ namespace {
21
21
22
22
enum class ImageSource {
23
23
// Opens up the device camera, letting the user to take a new picture.
@@ -26,6 +26,19 @@ enum class ImageSource {
26
26
kGallery ,
27
27
};
28
28
29
+ template <typename T>
30
+ static bool GetValueFromEncodableMap (const flutter::EncodableMap *map,
31
+ const char *key, T &out) {
32
+ auto iter = map->find (flutter::EncodableValue (key));
33
+ if (iter != map->end () && !iter->second .IsNull ()) {
34
+ if (auto *value = std::get_if<T>(&iter->second )) {
35
+ out = *value;
36
+ return true ;
37
+ }
38
+ }
39
+ return false ;
40
+ }
41
+
29
42
class ImagePickerTizenPlugin : public flutter ::Plugin {
30
43
public:
31
44
static void RegisterWithRegistrar (flutter::PluginRegistrar *registrar) {
@@ -53,176 +66,119 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
53
66
const flutter::MethodCall<flutter::EncodableValue> &method_call,
54
67
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
55
68
const auto &method_name = method_call.method_name ();
56
- const auto &arguments = *method_call.arguments ();
57
69
58
70
if (result_) {
59
- SendResultWithError (" Already active" , " Cancelled by a second request." );
71
+ SendErrorResult (" Already active" , " Cancelled by a second request." );
60
72
return ;
61
73
}
62
74
result_ = std::move (result);
63
- multi_image_ = method_name == " pickMultiImage" ;
64
75
65
- ImageSource source = ImageSource::kGallery ;
66
76
if (method_name == " pickImage" || method_name == " pickMultiImage" ) {
67
- double width = 0.0 , height = 0.0 ;
77
+ const auto *arguments =
78
+ std::get_if<flutter::EncodableMap>(method_call.arguments ());
79
+ assert (arguments);
80
+
81
+ int source_index = static_cast <int >(ImageSource::kGallery );
82
+ double max_width = 0.0 , max_height = 0.0 ;
68
83
int32_t quality = 0 ;
69
- if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
70
- flutter::EncodableMap values =
71
- std::get<flutter::EncodableMap>(arguments);
72
- auto s = values[flutter::EncodableValue (" source" )];
73
- if (std::holds_alternative<int32_t >(s)) {
74
- source = (ImageSource)std::get<int32_t >(s);
75
- }
76
- auto w = values[flutter::EncodableValue (" maxWidth" )];
77
- if (std::holds_alternative<double >(w)) {
78
- width = std::get<double >(w);
79
- }
80
- auto h = values[flutter::EncodableValue (" maxHeight" )];
81
- if (std::holds_alternative<double >(h)) {
82
- height = std::get<double >(h);
83
- }
84
- auto q = values[flutter::EncodableValue (" imageQuality" )];
85
- if (std::holds_alternative<int32_t >(q)) {
86
- quality = std::get<int32_t >(q);
87
- }
88
- image_resize_.SetSize ((unsigned int )width, (unsigned int )height,
89
- quality);
90
- } else {
91
- SendResultWithError (" Invalid arguments" );
92
- return ;
93
- }
84
+ GetValueFromEncodableMap (arguments, " source" , source_index);
85
+ GetValueFromEncodableMap (arguments, " maxWidth" , max_width);
86
+ GetValueFromEncodableMap (arguments, " maxHeight" , max_height);
87
+ GetValueFromEncodableMap (arguments, " imageQuality" , quality);
94
88
89
+ image_resize_.SetSize (static_cast <uint32_t >(max_width),
90
+ static_cast <uint32_t >(max_height), quality);
91
+
92
+ ImageSource source = ImageSource (source_index);
95
93
if (source == ImageSource::kCamera ) {
96
94
// TODO: we need to check this feature after webcam is prepared
97
- SendResultWithError (" Not supported on this device" );
95
+ SendErrorResult (" Not supported" , " Not supported on this device. " );
98
96
} else if (source == ImageSource::kGallery ) {
99
- SetContentMimeType ( " image " ) ;
100
- CheckPermissionAndPickContent ( );
97
+ multi_image_ = method_name == " pickMultiImage " ;
98
+ PickContent ( " image/* " );
101
99
} else {
102
- SendResultWithError (" Invalid image source" );
100
+ SendErrorResult (" Invalid arguments " , " Invalid image source. " );
103
101
}
104
102
} else if (method_name == " pickVideo" ) {
105
- if (std::holds_alternative<flutter::EncodableMap>(arguments)) {
106
- flutter::EncodableMap values =
107
- std::get<flutter::EncodableMap>(arguments);
108
- auto s = values[flutter::EncodableValue (" source" )];
109
- if (std::holds_alternative<int32_t >(s)) {
110
- source = (ImageSource)std::get<int32_t >(s);
111
- }
112
- } else {
113
- SendResultWithError (" Invalid arguments" );
114
- return ;
115
- }
103
+ const auto *arguments =
104
+ std::get_if<flutter::EncodableMap>(method_call.arguments ());
105
+ assert (arguments);
106
+
107
+ int source_index = static_cast <int >(ImageSource::kGallery );
108
+ GetValueFromEncodableMap (arguments, " source" , source_index);
116
109
110
+ ImageSource source = ImageSource (source_index);
117
111
if (source == ImageSource::kCamera ) {
118
112
// TODO: we need to check this feature after webcam is prepared
119
- SendResultWithError (" Not supported on this device" );
113
+ SendErrorResult (" Not supported" , " Not supported on this device. " );
120
114
} else if (source == ImageSource::kGallery ) {
121
- SetContentMimeType (" video" );
122
- CheckPermissionAndPickContent ();
115
+ PickContent (" video/*" );
123
116
} else {
124
- SendResultWithError (" Invalid video source" );
117
+ SendErrorResult (" Invalid arguments " , " Invalid video source. " );
125
118
}
126
119
} else {
127
120
result_->NotImplemented ();
128
121
result_ = nullptr ;
129
122
}
130
123
}
131
124
132
- void CheckPermissionAndPickContent () {
133
- #ifndef TV_PROFILE
134
- const char *privilege = " http://tizen.org/privilege/mediastorage" ;
135
-
136
- ppm_check_result_e permission;
137
- int ret = ppm_check_permission (privilege, &permission);
138
- if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
139
- LOG_ERROR (" ppm_check_permission fail! [%d]" , ret);
140
- } else {
141
- switch (permission) {
142
- case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW:
143
- LOG_INFO (" ppm_check_permission success!" );
144
- PickContent ();
145
- return ;
146
- case PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK:
147
- ret = ppm_request_permission (
148
- privilege,
149
- [](ppm_call_cause_e cause, ppm_request_result_e result,
150
- const char *privilege, void *data) -> void {
151
- auto *plugin = (ImagePickerTizenPlugin *)data;
152
- assert (plugin);
153
-
154
- if (cause == PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR) {
155
- LOG_ERROR (" ppm_request_permission error! [%d]" , result);
156
- plugin->SendResultWithError (" Permission denied" );
157
- return ;
158
- }
159
- if (result !=
160
- PRIVACY_PRIVILEGE_MANAGER_REQUEST_RESULT_ALLOW_FOREVER) {
161
- LOG_ERROR (" ppm_request_permission deny! [%d]" , result);
162
- plugin->SendResultWithError (" Permission denied" );
163
- return ;
164
- }
165
-
166
- plugin->PickContent ();
167
- },
168
- this );
169
- if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
170
- LOG_ERROR (" ppm_request_permission fail! [%d]" , ret);
171
- break ;
172
- }
173
- return ;
174
- default :
175
- LOG_ERROR (" ppm_check_permission deny!" );
176
- break ;
177
- }
125
+ bool CheckPermission () {
126
+ PermissionManager manager;
127
+ PermissionResult result =
128
+ manager.RequestPermssion (" http://tizen.org/privilege/mediastorage" );
129
+
130
+ if (result == PermissionResult::kDenyForever ||
131
+ result == PermissionResult::kDenyOnce ) {
132
+ SendErrorResult (" Permission denied" , " Permission denied by user." );
133
+ return false ;
134
+ } else if (result == PermissionResult::kError ) {
135
+ SendErrorResult (" Operation failed" , " Failed to request permission." );
136
+ return false ;
178
137
}
179
- SendResultWithError (" Permission denied" );
180
- #else
181
- PickContent ();
182
- #endif
138
+ return true ;
183
139
}
184
140
185
- void PickContent () {
141
+ void PickContent (std::string mime_type) {
142
+ if (!CheckPermission ()) {
143
+ return ;
144
+ }
145
+
186
146
app_control_h handle = nullptr ;
187
- #define RET_IF_ERROR (ret ) \
188
- if (ret != APP_CONTROL_ERROR_NONE) { \
189
- SendResultWithError (std::to_string (ret), get_error_message (ret)); \
190
- if (handle) { \
191
- app_control_destroy (handle); \
192
- } \
193
- return ; \
147
+ #define RETURN_IF_ERROR (ret ) \
148
+ if (ret != APP_CONTROL_ERROR_NONE) { \
149
+ SendErrorResult (std::to_string (ret), get_error_message (ret)); \
150
+ if (handle) { \
151
+ app_control_destroy (handle); \
152
+ } \
153
+ return ; \
194
154
}
195
155
int ret = app_control_create (&handle);
196
- RET_IF_ERROR (ret);
156
+ RETURN_IF_ERROR (ret);
197
157
198
158
ret = app_control_set_operation (handle, APP_CONTROL_OPERATION_PICK);
199
- RET_IF_ERROR (ret);
159
+ RETURN_IF_ERROR (ret);
200
160
201
161
ret = app_control_add_extra_data (handle, APP_CONTROL_DATA_SELECTION_MODE,
202
162
multi_image_ ? " multiple" : " single" );
203
- RET_IF_ERROR (ret);
163
+ RETURN_IF_ERROR (ret);
204
164
205
- ret = app_control_set_mime (handle, mime_type_ .c_str ());
206
- RET_IF_ERROR (ret);
165
+ ret = app_control_set_mime (handle, mime_type .c_str ());
166
+ RETURN_IF_ERROR (ret);
207
167
208
- ret = app_control_send_launch_request (handle, PickImageReplyCallback , this );
209
- RET_IF_ERROR (ret);
210
- #undef RET_IF_ERROR
168
+ ret = app_control_send_launch_request (handle, ReplyCallback , this );
169
+ RETURN_IF_ERROR (ret);
170
+ #undef RETURN_IF_ERROR
211
171
212
172
app_control_destroy (handle);
213
173
}
214
174
215
- static void PickImageReplyCallback (app_control_h request, app_control_h reply,
216
- app_control_result_e result,
217
- void *user_data) {
218
- LOG_INFO (" PickImageReplyCallback called: %d" , (int )result);
219
-
220
- auto *plugin = (ImagePickerTizenPlugin *)user_data;
221
- assert (plugin != nullptr );
222
- assert (plugin->result_ != nullptr );
175
+ static void ReplyCallback (app_control_h request, app_control_h reply,
176
+ app_control_result_e result, void *user_data) {
177
+ auto *self = static_cast <ImagePickerTizenPlugin *>(user_data);
178
+ assert (self->result_ );
223
179
224
180
if (result != APP_CONTROL_RESULT_SUCCEEDED) {
225
- plugin-> SendResultWithError (" Operation failed" );
181
+ self-> SendErrorResult (" Operation failed" , " Received an error response. " );
226
182
return ;
227
183
}
228
184
@@ -231,32 +187,32 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
231
187
int ret = app_control_get_extra_data_array (reply, APP_CONTROL_DATA_SELECTED,
232
188
&values, &count);
233
189
if (ret != APP_CONTROL_ERROR_NONE) {
234
- plugin-> SendResultWithError (std::to_string (ret), get_error_message (ret));
190
+ self-> SendErrorResult (std::to_string (ret), get_error_message (ret));
235
191
return ;
236
192
}
237
193
238
194
if (count == 0 ) {
239
- plugin-> SendResultWithError ( " No file selected" );
240
- } else if (plugin ->multi_image_ ) {
195
+ self-> SendErrorResult ( " Operation cancelled " , " No file selected. " );
196
+ } else if (self ->multi_image_ ) {
241
197
flutter::EncodableList paths;
242
198
for (int i = 0 ; i < count; i++) {
243
199
std::string source_path = values[i];
244
200
std::string dest_path;
245
- if (plugin ->image_resize_ .Resize (source_path, dest_path)) {
201
+ if (self ->image_resize_ .Resize (source_path, & dest_path)) {
246
202
paths.push_back (flutter::EncodableValue (dest_path));
247
203
} else {
248
204
paths.push_back (flutter::EncodableValue (source_path));
249
205
}
250
206
free (values[i]);
251
207
}
252
- plugin-> SendResultWithSuccess (flutter::EncodableValue (paths));
208
+ self-> SendResult (flutter::EncodableValue (paths));
253
209
} else {
254
210
std::string source_path = values[0 ];
255
211
std::string dest_path;
256
- if (plugin ->image_resize_ .Resize (source_path, dest_path)) {
257
- plugin-> SendResultWithSuccess (flutter::EncodableValue (dest_path));
212
+ if (self ->image_resize_ .Resize (source_path, & dest_path)) {
213
+ self-> SendResult (flutter::EncodableValue (dest_path));
258
214
} else {
259
- plugin-> SendResultWithSuccess (flutter::EncodableValue (source_path));
215
+ self-> SendResult (flutter::EncodableValue (source_path));
260
216
}
261
217
free (values[0 ]);
262
218
}
@@ -266,33 +222,30 @@ class ImagePickerTizenPlugin : public flutter::Plugin {
266
222
}
267
223
}
268
224
269
- void SendResultWithSuccess (const flutter::EncodableValue &result) {
270
- if (result_ == nullptr ) {
225
+ void SendResult (const flutter::EncodableValue &result) {
226
+ if (! result_) {
271
227
return ;
272
228
}
273
229
result_->Success (result);
274
230
result_ = nullptr ;
275
231
}
276
232
277
- void SendResultWithError (const std::string &error_code,
278
- const std::string &error_message = " " ) {
279
- if (result_ == nullptr ) {
233
+ void SendErrorResult (const std::string &error_code,
234
+ const std::string &error_message) {
235
+ if (! result_) {
280
236
return ;
281
237
}
282
238
result_->Error (error_code, error_message);
283
239
result_ = nullptr ;
284
240
}
285
241
286
- void SetContentMimeType (const std::string &mime_type) {
287
- mime_type_ = mime_type + " /*" ;
288
- }
289
-
290
- ImageResize image_resize_;
291
242
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result_;
292
- std::string mime_type_ ;
243
+ ImageResize image_resize_ ;
293
244
bool multi_image_ = false ;
294
245
};
295
246
247
+ } // namespace
248
+
296
249
void ImagePickerTizenPluginRegisterWithRegistrar (
297
250
FlutterDesktopPluginRegistrarRef registrar) {
298
251
ImagePickerTizenPlugin::RegisterWithRegistrar (
0 commit comments