4
4
import android .app .Activity ;
5
5
import android .content .ActivityNotFoundException ;
6
6
import android .content .Context ;
7
- import android .content .DialogInterface ;
8
7
import android .content .Intent ;
9
8
import android .graphics .Bitmap ;
10
9
import android .graphics .BitmapFactory ;
11
10
import android .graphics .BitmapFactory .Options ;
12
11
import android .graphics .Matrix ;
13
- import android .graphics .drawable .ColorDrawable ;
14
12
import android .media .ExifInterface ;
15
13
import android .net .Uri ;
16
14
import android .os .Build ;
19
17
import android .support .annotation .NonNull ;
20
18
import android .support .v4 .app .ActivityCompat ;
21
19
import android .support .v4 .content .FileProvider ;
22
- import android .app .AlertDialog ;
23
20
import android .util .Base64 ;
24
21
import android .util .Log ;
25
- import android .widget .ArrayAdapter ;
26
22
import android .webkit .MimeTypeMap ;
27
23
import android .content .pm .PackageManager ;
28
24
import android .media .MediaScannerConnection ;
34
30
import com .facebook .react .bridge .ReactContextBaseJavaModule ;
35
31
import com .facebook .react .bridge .ReactMethod ;
36
32
import com .facebook .react .bridge .ReadableMap ;
37
- import com .facebook .react .bridge .ReadableArray ;
38
33
import com .facebook .react .bridge .WritableMap ;
34
+ import com .imagepicker .utils .RealPathUtil ;
35
+ import com .imagepicker .utils .UI ;
39
36
40
37
import java .io .ByteArrayOutputStream ;
41
38
import java .io .File ;
50
47
import java .text .DateFormat ;
51
48
import java .text .ParsePosition ;
52
49
import java .text .SimpleDateFormat ;
53
- import java .util .ArrayList ;
54
50
import java .util .Date ;
55
- import java .util .List ;
56
51
import java .util .Locale ;
57
52
import java .util .TimeZone ;
58
53
import java .util .UUID ;
@@ -64,10 +59,10 @@ public class ImagePickerModule extends ReactContextBaseJavaModule implements Act
64
59
static final int REQUEST_LAUNCH_VIDEO_LIBRARY = 13003 ;
65
60
static final int REQUEST_LAUNCH_VIDEO_CAPTURE = 13004 ;
66
61
67
- private final ReactApplicationContext mReactContext ;
62
+ private final ReactApplicationContext reactContext ;
68
63
69
- private Uri mCameraCaptureURI ;
70
- private Callback mCallback ;
64
+ private Uri cameraCaptureURI ;
65
+ private Callback callback ;
71
66
private Boolean noData = false ;
72
67
private Boolean pickVideo = false ;
73
68
private int maxWidth = 0 ;
@@ -81,7 +76,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule implements Act
81
76
public ImagePickerModule (ReactApplicationContext reactContext ) {
82
77
super (reactContext );
83
78
84
- mReactContext = reactContext ;
79
+ this . reactContext = reactContext ;
85
80
86
81
reactContext .addActivityEventListener (this );
87
82
}
@@ -95,90 +90,52 @@ public String getName() {
95
90
public void showImagePicker (final ReadableMap options , final Callback callback ) {
96
91
Activity currentActivity = getCurrentActivity ();
97
92
98
- if (currentActivity == null ) {
99
- response = Arguments .createMap ();
93
+ if (currentActivity == null )
94
+ {
95
+ cleanResponse ();
100
96
response .putString ("error" , "can't find current Activity" );
101
97
callback .invoke (response );
102
98
return ;
103
99
}
104
100
105
- final List <String > titles = new ArrayList <String >();
106
- final List <String > actions = new ArrayList <String >();
107
-
108
- if (options .hasKey ("takePhotoButtonTitle" )
109
- && options .getString ("takePhotoButtonTitle" ) != null
110
- && !options .getString ("takePhotoButtonTitle" ).isEmpty ()
111
- && isCameraAvailable ()) {
112
- titles .add (options .getString ("takePhotoButtonTitle" ));
113
- actions .add ("photo" );
114
- }
115
- if (options .hasKey ("chooseFromLibraryButtonTitle" )
116
- && options .getString ("chooseFromLibraryButtonTitle" ) != null
117
- && !options .getString ("chooseFromLibraryButtonTitle" ).isEmpty ()) {
118
- titles .add (options .getString ("chooseFromLibraryButtonTitle" ));
119
- actions .add ("library" );
120
- }
121
- if (options .hasKey ("customButtons" )) {
122
- ReadableArray customButtons = options .getArray ("customButtons" );
123
- for (int i = 0 ; i < customButtons .size (); i ++) {
124
- ReadableMap button = customButtons .getMap (i );
125
- int currentIndex = titles .size ();
126
- titles .add (currentIndex , button .getString ("title" ));
127
- actions .add (currentIndex , button .getString ("name" ));
101
+ UI .showDialog (currentActivity , options , new UI .OnAction ()
102
+ {
103
+ @ Override
104
+ public void onTakePhoto ()
105
+ {
106
+ launchCamera (options , callback );
128
107
}
129
- }
130
- if (options .hasKey ("cancelButtonTitle" )
131
- && options .getString ("cancelButtonTitle" ) != null
132
- && !options .getString ("cancelButtonTitle" ).isEmpty ()) {
133
- titles .add (options .getString ("cancelButtonTitle" ));
134
- actions .add ("cancel" );
135
- }
136
-
137
- ArrayAdapter <String > adapter = new ArrayAdapter <String >(currentActivity , android .R .layout .select_dialog_item , titles );
138
- AlertDialog .Builder builder = new AlertDialog .Builder (currentActivity , android .R .style .Theme_Holo_Light_Dialog );
139
- if (options .hasKey ("title" ) && options .getString ("title" ) != null && !options .getString ("title" ).isEmpty ()) {
140
- builder .setTitle (options .getString ("title" ));
141
- }
142
-
143
- builder .setAdapter (adapter , new DialogInterface .OnClickListener () {
144
- public void onClick (DialogInterface dialog , int index ) {
145
- String action = actions .get (index );
146
- response = Arguments .createMap ();
147
-
148
- switch (action ) {
149
- case "photo" :
150
- launchCamera (options , callback );
151
- break ;
152
- case "library" :
153
- launchImageLibrary (options , callback );
154
- break ;
155
- case "cancel" :
156
- response .putBoolean ("didCancel" , true );
157
- callback .invoke (response );
158
- break ;
159
- default : // custom button
160
- response .putString ("customButton" , action );
161
- callback .invoke (response );
162
- }
108
+
109
+ @ Override
110
+ public void onUseLibrary ()
111
+ {
112
+ launchImageLibrary (options , callback );
163
113
}
164
- });
165
114
166
- final AlertDialog dialog = builder .create ();
167
- /**
168
- * override onCancel method to callback cancel in case of a touch outside of
169
- * the dialog or the BACK key pressed
170
- */
171
- dialog .setOnCancelListener (new DialogInterface .OnCancelListener () {
172
115
@ Override
173
- public void onCancel (DialogInterface dialog ) {
174
- response = Arguments . createMap ();
175
- dialog . dismiss ();
116
+ public void onCancel ()
117
+ {
118
+ cleanResponse ();
176
119
response .putBoolean ("didCancel" , true );
177
120
callback .invoke (response );
178
121
}
122
+
123
+ @ Override
124
+ public void onCustomButton (@ NonNull final String action )
125
+ {
126
+ cleanResponse ();
127
+ response .putString ("customButton" , action );
128
+ callback .invoke (response );
129
+ }
130
+
131
+ @ Override
132
+ public void onDialogWasCanceled (@ NonNull final String action )
133
+ {
134
+ cleanResponse ();
135
+ response .putBoolean (action , true );
136
+ callback .invoke (response );
137
+ }
179
138
});
180
- dialog .getWindow ().setBackgroundDrawable (new ColorDrawable (android .graphics .Color .TRANSPARENT ));
181
- dialog .show ();
182
139
}
183
140
184
141
// NOTE: Currently not reentrant / doesn't support concurrent requests
@@ -220,17 +177,17 @@ public void launchCamera(final ReadableMap options, final Callback callback) {
220
177
221
178
// we create a tmp file to save the result
222
179
File imageFile = createNewFile ();
223
- mCameraCaptureURI = compatUriFromFile (mReactContext , imageFile );
224
- cameraIntent .putExtra (MediaStore .EXTRA_OUTPUT , mCameraCaptureURI );
180
+ cameraCaptureURI = compatUriFromFile (reactContext , imageFile );
181
+ cameraIntent .putExtra (MediaStore .EXTRA_OUTPUT , cameraCaptureURI );
225
182
}
226
183
227
- if (cameraIntent .resolveActivity (mReactContext .getPackageManager ()) == null ) {
184
+ if (cameraIntent .resolveActivity (reactContext .getPackageManager ()) == null ) {
228
185
response .putString ("error" , "Cannot launch camera" );
229
186
callback .invoke (response );
230
187
return ;
231
188
}
232
189
233
- mCallback = callback ;
190
+ this . callback = callback ;
234
191
235
192
try {
236
193
currentActivity .startActivityForResult (cameraIntent , requestCode );
@@ -272,13 +229,13 @@ public void launchImageLibrary(final ReadableMap options, final Callback callbac
272
229
MediaStore .Images .Media .EXTERNAL_CONTENT_URI );
273
230
}
274
231
275
- if (libraryIntent .resolveActivity (mReactContext .getPackageManager ()) == null ) {
232
+ if (libraryIntent .resolveActivity (reactContext .getPackageManager ()) == null ) {
276
233
response .putString ("error" , "Cannot launch photo library" );
277
234
callback .invoke (response );
278
235
return ;
279
236
}
280
237
281
- mCallback = callback ;
238
+ this . callback = callback ;
282
239
283
240
try {
284
241
currentActivity .startActivityForResult (libraryIntent , requestCode );
@@ -291,7 +248,7 @@ public void launchImageLibrary(final ReadableMap options, final Callback callbac
291
248
292
249
public void onActivityResult (Activity activity , int requestCode , int resultCode , Intent data ) {
293
250
//robustness code
294
- if (mCallback == null || (mCameraCaptureURI == null && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE )
251
+ if (callback == null || (cameraCaptureURI == null && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE )
295
252
|| (requestCode != REQUEST_LAUNCH_IMAGE_CAPTURE && requestCode != REQUEST_LAUNCH_IMAGE_LIBRARY
296
253
&& requestCode != REQUEST_LAUNCH_VIDEO_LIBRARY && requestCode != REQUEST_LAUNCH_VIDEO_CAPTURE )) {
297
254
return ;
@@ -302,15 +259,15 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode,
302
259
// user cancel
303
260
if (resultCode != Activity .RESULT_OK ) {
304
261
response .putBoolean ("didCancel" , true );
305
- mCallback .invoke (response );
306
- mCallback = null ;
262
+ callback .invoke (response );
263
+ callback = null ;
307
264
return ;
308
265
}
309
266
310
267
Uri uri ;
311
268
switch (requestCode ) {
312
269
case REQUEST_LAUNCH_IMAGE_CAPTURE :
313
- uri = mCameraCaptureURI ;
270
+ uri = cameraCaptureURI ;
314
271
this .fileScan (uri .getPath ());
315
272
break ;
316
273
case REQUEST_LAUNCH_IMAGE_LIBRARY :
@@ -319,15 +276,15 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode,
319
276
case REQUEST_LAUNCH_VIDEO_LIBRARY :
320
277
response .putString ("uri" , data .getData ().toString ());
321
278
response .putString ("path" , getRealPathFromURI (data .getData ()));
322
- mCallback .invoke (response );
323
- mCallback = null ;
279
+ callback .invoke (response );
280
+ callback = null ;
324
281
return ;
325
282
case REQUEST_LAUNCH_VIDEO_CAPTURE :
326
283
response .putString ("uri" , data .getData ().toString ());
327
284
response .putString ("path" , getRealPathFromURI (data .getData ()));
328
285
this .fileScan (response .getString ("path" ));
329
- mCallback .invoke (response );
330
- mCallback = null ;
286
+ callback .invoke (response );
287
+ callback = null ;
331
288
return ;
332
289
default :
333
290
uri = null ;
@@ -355,8 +312,8 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode,
355
312
// image not in cache
356
313
response .putString ("error" , "Could not read photo" );
357
314
response .putString ("uri" , uri .toString ());
358
- mCallback .invoke (response );
359
- mCallback = null ;
315
+ callback .invoke (response );
316
+ callback = null ;
360
317
return ;
361
318
}
362
319
}
@@ -406,8 +363,8 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode,
406
363
} catch (IOException e ) {
407
364
e .printStackTrace ();
408
365
response .putString ("error" , e .getMessage ());
409
- mCallback .invoke (response );
410
- mCallback = null ;
366
+ callback .invoke (response );
367
+ callback = null ;
411
368
return ;
412
369
}
413
370
@@ -443,8 +400,8 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode,
443
400
444
401
putExtraFileInfo (realPath , response );
445
402
446
- mCallback .invoke (response );
447
- mCallback = null ;
403
+ callback .invoke (response );
404
+ callback = null ;
448
405
}
449
406
450
407
/**
@@ -498,12 +455,12 @@ private boolean permissionsCheck(Activity activity) {
498
455
}
499
456
500
457
private boolean isCameraAvailable () {
501
- return mReactContext .getPackageManager ().hasSystemFeature (PackageManager .FEATURE_CAMERA )
502
- || mReactContext .getPackageManager ().hasSystemFeature (PackageManager .FEATURE_CAMERA_ANY );
458
+ return reactContext .getPackageManager ().hasSystemFeature (PackageManager .FEATURE_CAMERA )
459
+ || reactContext .getPackageManager ().hasSystemFeature (PackageManager .FEATURE_CAMERA_ANY );
503
460
}
504
461
505
462
private @ NonNull String getRealPathFromURI (@ NonNull final Uri uri ) {
506
- return RealPathUtil .getRealPathFromURI (mReactContext , uri );
463
+ return RealPathUtil .getRealPathFromURI (reactContext , uri );
507
464
}
508
465
509
466
/**
@@ -518,8 +475,8 @@ private boolean isCameraAvailable() {
518
475
* @throws Exception
519
476
*/
520
477
private File createFileFromURI (Uri uri ) throws Exception {
521
- File file = new File (mReactContext .getExternalCacheDir (), "photo-" + uri .getLastPathSegment ());
522
- InputStream input = mReactContext .getContentResolver ().openInputStream (uri );
478
+ File file = new File (reactContext .getExternalCacheDir (), "photo-" + uri .getLastPathSegment ());
479
+ InputStream input = reactContext .getContentResolver ().openInputStream (uri );
523
480
OutputStream output = new FileOutputStream (file );
524
481
525
482
try {
@@ -649,7 +606,7 @@ private File createNewFile() {
649
606
.append (UUID .randomUUID ().toString ())
650
607
.append (".jpg" )
651
608
.toString ();
652
- File path = mReactContext .getExternalFilesDir (Environment .DIRECTORY_PICTURES );
609
+ File path = reactContext .getExternalFilesDir (Environment .DIRECTORY_PICTURES );
653
610
654
611
File f = new File (path , filename );
655
612
try {
@@ -715,7 +672,7 @@ private void parseOptions(final ReadableMap options) {
715
672
}
716
673
717
674
public void fileScan (String path ) {
718
- MediaScannerConnection .scanFile (mReactContext ,
675
+ MediaScannerConnection .scanFile (reactContext ,
719
676
new String [] { path }, null ,
720
677
new MediaScannerConnection .OnScanCompletedListener () {
721
678
@@ -731,6 +688,11 @@ public void onNewIntent(Intent intent) { }
731
688
// Some people need this for compilation
732
689
public void onActivityResult (int requestCode , int resultCode , Intent data ) { }
733
690
691
+ private void cleanResponse ()
692
+ {
693
+ response = Arguments .createMap ();
694
+ }
695
+
734
696
private static Uri compatUriFromFile (@ NonNull final Context context , @ NonNull final File file ) {
735
697
Uri result = null ;
736
698
if (Build .VERSION .SDK_INT < 19 )
0 commit comments