cordova-plugin-mserviceinterface-2.0 1.0.102 → 1.0.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugin.xml +1 -1
- package/src/android/AttachmentFileIO.java +59 -0
- package/src/android/CameraActivity.java +111 -10
- package/src/android/GeofenceBroadcastReceiver.java +100 -20
- package/src/android/mInterface.java +360 -576
- package/src/android/mInterfaceReceiver.java +11 -53
- package/src/android/mInterfaceService.java +539 -315
- package/src/android/mInterfaceUtil.java +41 -71
|
@@ -9,7 +9,7 @@ import android.app.AlertDialog;
|
|
|
9
9
|
import android.app.PendingIntent;
|
|
10
10
|
import android.app.ProgressDialog;
|
|
11
11
|
import android.content.ContentResolver;
|
|
12
|
-
import android.content.
|
|
12
|
+
import android.content.ActivityNotFoundException;
|
|
13
13
|
import android.content.Context;
|
|
14
14
|
import android.content.DialogInterface;
|
|
15
15
|
import android.content.Intent;
|
|
@@ -35,7 +35,6 @@ import android.os.AsyncTask;
|
|
|
35
35
|
import android.os.Build;
|
|
36
36
|
import android.os.Bundle;
|
|
37
37
|
import android.os.Environment;
|
|
38
|
-
import android.provider.DocumentsContract;
|
|
39
38
|
import android.provider.MediaStore;
|
|
40
39
|
import android.provider.OpenableColumns;
|
|
41
40
|
import android.provider.Settings;
|
|
@@ -43,7 +42,6 @@ import android.text.TextUtils;
|
|
|
43
42
|
import android.util.Base64;
|
|
44
43
|
import android.util.Log;
|
|
45
44
|
import android.util.Patterns;
|
|
46
|
-
import android.view.KeyEvent;
|
|
47
45
|
import android.webkit.MimeTypeMap;
|
|
48
46
|
import android.widget.ProgressBar;
|
|
49
47
|
import android.widget.Toast;
|
|
@@ -102,6 +100,7 @@ import java.util.Arrays;
|
|
|
102
100
|
import java.util.Collections;
|
|
103
101
|
import java.util.Date;
|
|
104
102
|
import java.util.List;
|
|
103
|
+
import java.util.Locale;
|
|
105
104
|
import java.util.Stack;
|
|
106
105
|
import java.util.TimeZone;
|
|
107
106
|
import java.util.zip.ZipEntry;
|
|
@@ -118,6 +117,11 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
118
117
|
public Stack<ProgressDialog> spinnerDialogStack = new Stack<ProgressDialog>();
|
|
119
118
|
private static final int PICK_FILE_REQUEST = 1;
|
|
120
119
|
public CallbackContext callback;
|
|
120
|
+
private CallbackContext permissionCallback;
|
|
121
|
+
private int pendingPermissionRequest = -1;
|
|
122
|
+
private static final int REQUEST_PERMISSIONS = 4101;
|
|
123
|
+
private static final int REQUEST_LOCATION_PERMISSION = 4102;
|
|
124
|
+
private static final int REQUEST_MEDIA_PERMISSION = 4103;
|
|
121
125
|
private static JSONArray arguments = null;
|
|
122
126
|
private String pictureFilePath;
|
|
123
127
|
private String cameraAttachmentInd = "false";
|
|
@@ -155,15 +159,31 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
155
159
|
super.onResume(multitasking);
|
|
156
160
|
//To avoid starting service after getting permissions initially.
|
|
157
161
|
if (!mInterfaceUtil.deviceID.equalsIgnoreCase("")) {
|
|
158
|
-
|
|
159
|
-
cordova.getActivity().startService(new Intent(cordova.getActivity().getApplicationContext(), mInterfaceService.class));
|
|
160
|
-
}
|
|
162
|
+
mInterfaceService.start(cordova.getActivity());
|
|
161
163
|
}
|
|
162
164
|
} catch (Exception e) {
|
|
163
165
|
System.out.println("onResume: " + e.getMessage());
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
|
|
169
|
+
@Override
|
|
170
|
+
public void onPause(boolean multitasking) {
|
|
171
|
+
mInterfaceService.stopIfNotTracking(cordova.getActivity());
|
|
172
|
+
super.onPause(multitasking);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@Override
|
|
176
|
+
public void onDestroy() {
|
|
177
|
+
mInterfaceService.stopIfNotTracking(cordova.getActivity());
|
|
178
|
+
if (mGoogleApiClient1 != null) {
|
|
179
|
+
if (mGoogleApiClient1.isConnected()) {
|
|
180
|
+
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient1, this);
|
|
181
|
+
}
|
|
182
|
+
mGoogleApiClient1.disconnect();
|
|
183
|
+
}
|
|
184
|
+
super.onDestroy();
|
|
185
|
+
}
|
|
186
|
+
|
|
167
187
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
168
188
|
@Override
|
|
169
189
|
public boolean execute(final String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
|
|
@@ -199,13 +219,11 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
199
219
|
try {
|
|
200
220
|
boolean appInfoUpdated = new mInterfaceUtil().updateAppInfo(args);
|
|
201
221
|
System.out.println("appInfoUpdated: " + appInfoUpdated);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
cordova.getActivity().startService(new Intent(cordova.getActivity().getApplicationContext(), mInterfaceService.class));
|
|
222
|
+
if (mInterfaceService.start(cordova.getActivity())) {
|
|
223
|
+
callbackContext.success("Success");
|
|
205
224
|
} else {
|
|
206
|
-
|
|
225
|
+
callbackContext.error("Unable to start service while the app is in the background");
|
|
207
226
|
}
|
|
208
|
-
callbackContext.success("Success");
|
|
209
227
|
} catch (Exception e) {
|
|
210
228
|
System.out.println("Unable to StartService, Exception is: " + e.getMessage());
|
|
211
229
|
callbackContext.error("Unable to StartService, Exception is: " + e.getMessage());
|
|
@@ -826,25 +844,14 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
826
844
|
builder.setNegativeButton("Not Now", new DialogInterface.OnClickListener() {
|
|
827
845
|
@Override
|
|
828
846
|
public void onClick(DialogInterface dialog, int which) {
|
|
829
|
-
dialog.
|
|
847
|
+
dialog.dismiss();
|
|
830
848
|
callbackContext.success("Success");
|
|
831
849
|
}
|
|
832
850
|
});
|
|
833
851
|
alertDialog = builder.create();
|
|
834
852
|
alertDialog.setCanceledOnTouchOutside(false);
|
|
835
853
|
alertDialog.show();
|
|
836
|
-
alertDialog.
|
|
837
|
-
|
|
838
|
-
@Override
|
|
839
|
-
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
|
840
|
-
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
|
841
|
-
dialog.dismiss();
|
|
842
|
-
callbackContext.error("failure");
|
|
843
|
-
}
|
|
844
|
-
return true;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
});
|
|
854
|
+
alertDialog.setOnCancelListener(dialog -> callbackContext.error("failure"));
|
|
848
855
|
} else if (action.equals("UpdateConfirm")) {
|
|
849
856
|
/* OPEN THE PLAYSTORE MSERVICE APP */
|
|
850
857
|
String appVersion, softwareProductVersion, softwareProductSubVersion;
|
|
@@ -867,17 +874,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
867
874
|
alertDialog = builder.create();
|
|
868
875
|
alertDialog.setCanceledOnTouchOutside(false);
|
|
869
876
|
alertDialog.show();
|
|
870
|
-
alertDialog.
|
|
871
|
-
|
|
872
|
-
@Override
|
|
873
|
-
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
|
874
|
-
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
|
875
|
-
dialog.dismiss();
|
|
876
|
-
callbackContext.error("failure");
|
|
877
|
-
}
|
|
878
|
-
return true;
|
|
879
|
-
}
|
|
880
|
-
});
|
|
877
|
+
alertDialog.setOnCancelListener(dialog -> callbackContext.error("failure"));
|
|
881
878
|
} else if (action.equals("UpdateNew")) {
|
|
882
879
|
try {
|
|
883
880
|
cordova.getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + cordova.getActivity().getApplicationContext().getPackageName())));
|
|
@@ -907,6 +904,8 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
907
904
|
}
|
|
908
905
|
} else if (action.equals("CaptureImageFromCamera")) {
|
|
909
906
|
try {
|
|
907
|
+
attachmentDestPath = "";
|
|
908
|
+
cameraAttachmentInd = "false";
|
|
910
909
|
if (args.length() > 0) {
|
|
911
910
|
attachmentDestPath = args.optJSONObject(0).optString("destinationPath");
|
|
912
911
|
cameraAttachmentInd = args.getJSONObject(0).optString("attachmentInd");
|
|
@@ -918,6 +917,8 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
918
917
|
}
|
|
919
918
|
} else if (action.equals("PickImageFromGallery")) {
|
|
920
919
|
try {
|
|
920
|
+
attachmentDestPath = "";
|
|
921
|
+
galleryAttachmentInd = "false";
|
|
921
922
|
if (args.length() > 0) {
|
|
922
923
|
attachmentDestPath = args.optJSONObject(0).optString("destinationPath");
|
|
923
924
|
galleryAttachmentInd = args.getJSONObject(0).optString("attachmentInd");
|
|
@@ -1577,7 +1578,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1577
1578
|
boolean permissionGranted = true, checkPermission = true;
|
|
1578
1579
|
List<String> list;
|
|
1579
1580
|
try {
|
|
1580
|
-
callback = callbackContext;
|
|
1581
1581
|
Context context = cordova.getActivity().getApplicationContext();
|
|
1582
1582
|
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1583
1583
|
if (permissions[0].equalsIgnoreCase("android.permission.ACCESS_BACKGROUND_LOCATION")) {
|
|
@@ -1595,12 +1595,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1595
1595
|
}
|
|
1596
1596
|
}
|
|
1597
1597
|
if (!permissionGranted) {
|
|
1598
|
-
|
|
1598
|
+
callbackContext.error("failure");
|
|
1599
1599
|
} else {
|
|
1600
|
-
|
|
1600
|
+
callbackContext.success("success");
|
|
1601
1601
|
}
|
|
1602
1602
|
} else {
|
|
1603
|
-
|
|
1603
|
+
callbackContext.success("success");
|
|
1604
1604
|
}
|
|
1605
1605
|
} catch (Exception e) {
|
|
1606
1606
|
e.printStackTrace();
|
|
@@ -1615,69 +1615,106 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1615
1615
|
}
|
|
1616
1616
|
|
|
1617
1617
|
private void getLocationPermission(JSONArray args, CallbackContext callbackContext) {
|
|
1618
|
-
boolean permissionGranted = true;
|
|
1619
|
-
List<String> list;
|
|
1620
1618
|
try {
|
|
1621
|
-
|
|
1622
|
-
Context context = cordova.getActivity().getApplicationContext();
|
|
1623
|
-
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1624
|
-
list = new ArrayList<String>(Arrays.asList(permissions));
|
|
1625
|
-
permissions = list.toArray(new String[0]);
|
|
1626
|
-
|
|
1627
|
-
for (int i = 0; i < permissions.length; i++) {
|
|
1628
|
-
if (ActivityCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
|
|
1629
|
-
permissionGranted = false;
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
if (!permissionGranted) {
|
|
1633
|
-
PermissionHelper.requestPermissions(this, 111, permissions);
|
|
1634
|
-
} else {
|
|
1635
|
-
callback.success("success");
|
|
1636
|
-
}
|
|
1619
|
+
requestPermissionsIfNeeded(normalizePermissions(args, false), REQUEST_LOCATION_PERMISSION, callbackContext);
|
|
1637
1620
|
} catch (Exception e) {
|
|
1638
|
-
e.
|
|
1621
|
+
callbackContext.error("getLocationPermission failed: " + e.getMessage());
|
|
1639
1622
|
}
|
|
1640
1623
|
}
|
|
1641
1624
|
|
|
1642
1625
|
private void getPermissions(JSONArray args, CallbackContext callbackContext) {
|
|
1643
|
-
boolean permissionGranted = true;
|
|
1644
|
-
List<String> list;
|
|
1645
1626
|
try {
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1627
|
+
requestPermissionsIfNeeded(normalizePermissions(args, true), REQUEST_PERMISSIONS, callbackContext);
|
|
1628
|
+
} catch (Exception e) {
|
|
1629
|
+
callbackContext.error("getPermissions failed: " + e.getMessage());
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
private String[] normalizePermissions(JSONArray args, boolean initialRequest) throws JSONException {
|
|
1634
|
+
List<String> permissions = new ArrayList<>();
|
|
1635
|
+
for (String value : args.getJSONObject(0).getString("permissions").split(",")) {
|
|
1636
|
+
String permission = value.trim();
|
|
1637
|
+
if (permission.isEmpty()) continue;
|
|
1638
|
+
// Files and photos are selected through URI grants into app-private storage.
|
|
1639
|
+
if (Manifest.permission.READ_MEDIA_IMAGES.equals(permission)
|
|
1640
|
+
|| Manifest.permission.READ_MEDIA_VIDEO.equals(permission)
|
|
1641
|
+
|| Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED.equals(permission)
|
|
1642
|
+
|| Manifest.permission.READ_EXTERNAL_STORAGE.equals(permission)
|
|
1643
|
+
|| Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)) continue;
|
|
1644
|
+
if (Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)
|
|
1645
|
+
&& (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
|
|
1646
|
+
|| (initialRequest && Build.VERSION.SDK_INT != Build.VERSION_CODES.Q))) continue;
|
|
1647
|
+
if (Manifest.permission.POST_NOTIFICATIONS.equals(permission)
|
|
1648
|
+
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) continue;
|
|
1649
|
+
if ((Manifest.permission.READ_MEDIA_IMAGES.equals(permission)
|
|
1650
|
+
|| Manifest.permission.READ_MEDIA_VIDEO.equals(permission)
|
|
1651
|
+
|| Manifest.permission.READ_MEDIA_AUDIO.equals(permission))
|
|
1652
|
+
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
1653
|
+
permission = Manifest.permission.READ_EXTERNAL_STORAGE;
|
|
1654
|
+
}
|
|
1655
|
+
if (Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED.equals(permission)
|
|
1656
|
+
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) continue;
|
|
1657
|
+
if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permission)
|
|
1658
|
+
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) continue;
|
|
1659
|
+
if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permission)
|
|
1660
|
+
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) continue;
|
|
1661
|
+
if (!permissions.contains(permission)) permissions.add(permission);
|
|
1662
|
+
}
|
|
1663
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
|
|
1664
|
+
&& (permissions.contains(Manifest.permission.READ_MEDIA_IMAGES)
|
|
1665
|
+
|| permissions.contains(Manifest.permission.READ_MEDIA_VIDEO))
|
|
1666
|
+
&& !permissions.contains(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)) {
|
|
1667
|
+
permissions.add(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED);
|
|
1668
|
+
}
|
|
1669
|
+
return permissions.toArray(new String[0]);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
private boolean isPermissionSatisfied(String permission) {
|
|
1673
|
+
Context context = cordova.getActivity();
|
|
1674
|
+
if (ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) return true;
|
|
1675
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
|
1676
|
+
if (Manifest.permission.READ_MEDIA_IMAGES.equals(permission) || Manifest.permission.READ_MEDIA_VIDEO.equals(permission)) {
|
|
1677
|
+
return ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
|
|
1678
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
1679
|
+
}
|
|
1680
|
+
if (Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED.equals(permission)) {
|
|
1681
|
+
return ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED
|
|
1682
|
+
|| ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_MEDIA_VIDEO) == PackageManager.PERMISSION_GRANTED;
|
|
1673
1683
|
}
|
|
1684
|
+
}
|
|
1685
|
+
return false;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
private boolean hasRequestedPermissions(String[] permissions) {
|
|
1689
|
+
for (String permission : permissions) {
|
|
1690
|
+
if (!isPermissionSatisfied(permission)) return false;
|
|
1691
|
+
}
|
|
1692
|
+
return true;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
private void requestPermissionsIfNeeded(String[] permissions, int requestCode, CallbackContext callbackContext) {
|
|
1696
|
+
if (hasRequestedPermissions(permissions)) {
|
|
1697
|
+
callbackContext.success("success");
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
if (permissionCallback != null) {
|
|
1701
|
+
callbackContext.error("Another permission request is in progress");
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
permissionCallback = callbackContext;
|
|
1705
|
+
pendingPermissionRequest = requestCode;
|
|
1706
|
+
try {
|
|
1707
|
+
PermissionHelper.requestPermissions(this, requestCode, permissions);
|
|
1674
1708
|
} catch (Exception e) {
|
|
1675
|
-
|
|
1709
|
+
permissionCallback = null;
|
|
1710
|
+
pendingPermissionRequest = -1;
|
|
1711
|
+
callbackContext.error("Unable to request permission: " + e.getMessage());
|
|
1676
1712
|
}
|
|
1677
1713
|
}
|
|
1678
1714
|
|
|
1679
1715
|
public void captureImageLiveCamera(CallbackContext callbackContext) {
|
|
1680
1716
|
callback = callbackContext;
|
|
1717
|
+
pictureFilePath = null;
|
|
1681
1718
|
Context context = cordova.getActivity().getApplicationContext();
|
|
1682
1719
|
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
|
1683
1720
|
File photoFile = null;
|
|
@@ -1685,6 +1722,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1685
1722
|
photoFile = createImageFile();
|
|
1686
1723
|
} catch (IOException ex) {
|
|
1687
1724
|
callback.error("there is error in create image");
|
|
1725
|
+
return;
|
|
1688
1726
|
}
|
|
1689
1727
|
//Continue only if the File was successfully created
|
|
1690
1728
|
if (photoFile != null) {
|
|
@@ -1699,11 +1737,14 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1699
1737
|
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
1700
1738
|
pluginResult.setKeepCallback(true);
|
|
1701
1739
|
callbackContext.sendPluginResult(pluginResult);
|
|
1740
|
+
} else {
|
|
1741
|
+
callbackContext.error("Unable to create the camera output file");
|
|
1702
1742
|
}
|
|
1703
1743
|
}
|
|
1704
1744
|
|
|
1705
1745
|
public void captureImage(CallbackContext callbackContext) {
|
|
1706
1746
|
callback = callbackContext;
|
|
1747
|
+
pictureFilePath = null;
|
|
1707
1748
|
Intent intent = new Intent(cordova.getActivity(), CameraActivity.class);
|
|
1708
1749
|
cordova.startActivityForResult(this, intent, REQUEST_IMAGE_CAPTURE);
|
|
1709
1750
|
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
@@ -1713,26 +1754,32 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1713
1754
|
|
|
1714
1755
|
void pickImageFromGallery(CallbackContext callbackContext) {
|
|
1715
1756
|
try {
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1757
|
+
callback = callbackContext;
|
|
1758
|
+
Intent intent;
|
|
1759
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
1760
|
+
intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
|
|
1761
|
+
intent.setType("image/*");
|
|
1720
1762
|
} else {
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
1763
|
+
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
1764
|
+
intent.setType("image/*");
|
|
1765
|
+
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
1725
1766
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1767
|
+
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
1768
|
+
try {
|
|
1769
|
+
cordova.startActivityForResult(this, intent, PICK_IMAGE_FROM_GALLERY);
|
|
1770
|
+
} catch (ActivityNotFoundException unavailable) {
|
|
1771
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) throw unavailable;
|
|
1772
|
+
Intent fallback = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
1773
|
+
fallback.setType("image/*");
|
|
1774
|
+
fallback.addCategory(Intent.CATEGORY_OPENABLE);
|
|
1775
|
+
fallback.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
1776
|
+
cordova.startActivityForResult(this, fallback, PICK_IMAGE_FROM_GALLERY);
|
|
1777
|
+
}
|
|
1778
|
+
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
1779
|
+
result.setKeepCallback(true);
|
|
1780
|
+
callbackContext.sendPluginResult(result);
|
|
1734
1781
|
} catch (Exception e) {
|
|
1735
|
-
callbackContext.error("pickImageFromGallery failed
|
|
1782
|
+
callbackContext.error("pickImageFromGallery failed: " + e.getMessage());
|
|
1736
1783
|
}
|
|
1737
1784
|
}
|
|
1738
1785
|
|
|
@@ -1923,10 +1970,10 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1923
1970
|
fileProperities.put("fileExtension", fileExtension);
|
|
1924
1971
|
fileProperities.put("thumbnail", thumbnail);
|
|
1925
1972
|
attachmentDestPath = "";
|
|
1926
|
-
|
|
1973
|
+
callbackContext.success(fileProperities);
|
|
1927
1974
|
} catch (Exception e) {
|
|
1928
1975
|
attachmentDestPath = "";
|
|
1929
|
-
|
|
1976
|
+
callbackContext.error("convertImageTo64BaseString failed, exception is : " + e.getMessage());
|
|
1930
1977
|
}
|
|
1931
1978
|
}
|
|
1932
1979
|
} catch (Exception e) {
|
|
@@ -1935,7 +1982,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1935
1982
|
}
|
|
1936
1983
|
|
|
1937
1984
|
} catch (Exception e) {
|
|
1938
|
-
e.
|
|
1985
|
+
callbackContext.error("convertImageTo64BaseString failed: " + e.getMessage());
|
|
1939
1986
|
}
|
|
1940
1987
|
|
|
1941
1988
|
}
|
|
@@ -1970,23 +2017,11 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1970
2017
|
}
|
|
1971
2018
|
|
|
1972
2019
|
public Intent getPickImageChooserIntent() {
|
|
1973
|
-
Intent
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
} else {
|
|
1979
|
-
openFile = new Intent(Intent.ACTION_GET_CONTENT);
|
|
1980
|
-
openFile.setType("*/*");
|
|
1981
|
-
openFile.addCategory(Intent.CATEGORY_OPENABLE);
|
|
1982
|
-
openFile.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
1983
|
-
}
|
|
1984
|
-
selectFile = Intent.createChooser(openFile, "Select File");
|
|
1985
|
-
return selectFile;
|
|
1986
|
-
} catch (Exception e) {
|
|
1987
|
-
e.printStackTrace();
|
|
1988
|
-
}
|
|
1989
|
-
return null;
|
|
2020
|
+
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
2021
|
+
intent.setType("*/*");
|
|
2022
|
+
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
2023
|
+
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
2024
|
+
return Intent.createChooser(intent, "Select File");
|
|
1990
2025
|
}
|
|
1991
2026
|
|
|
1992
2027
|
//App version plugin
|
|
@@ -2004,35 +2039,31 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2004
2039
|
|
|
2005
2040
|
//Rotate Screen plugin
|
|
2006
2041
|
public void rotateScreen(JSONArray args, CallbackContext callbackContext) {
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
activity.setRequestedOrientation(
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
|
|
2042
|
+
final String orientation = args.optString(0);
|
|
2043
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
2044
|
+
try {
|
|
2045
|
+
Activity activity = cordova.getActivity();
|
|
2046
|
+
String currentOrientation = activity.getResources().getConfiguration().orientation
|
|
2047
|
+
== Configuration.ORIENTATION_LANDSCAPE ? "landscape" : "portrait";
|
|
2048
|
+
int requested;
|
|
2049
|
+
switch (orientation) {
|
|
2050
|
+
case ANY: requested = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; break;
|
|
2051
|
+
case LANDSCAPE_PRIMARY: requested = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; break;
|
|
2052
|
+
case PORTRAIT_PRIMARY: requested = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; break;
|
|
2053
|
+
case LANDSCAPE: requested = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; break;
|
|
2054
|
+
case PORTRAIT: requested = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; break;
|
|
2055
|
+
case LANDSCAPE_SECONDARY: requested = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; break;
|
|
2056
|
+
case PORTRAIT_SECONDARY: requested = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; break;
|
|
2057
|
+
default: callbackContext.error("Unsupported screen orientation"); return;
|
|
2058
|
+
}
|
|
2059
|
+
// A best-effort request: API 36 large screens can ignore fixed orientations.
|
|
2060
|
+
// Return the previous orientation as before, not a claim that a lock was applied.
|
|
2061
|
+
activity.setRequestedOrientation(requested);
|
|
2062
|
+
callbackContext.success(currentOrientation);
|
|
2063
|
+
} catch (Exception e) {
|
|
2064
|
+
callbackContext.error("rotateScreen failed: " + e.getMessage());
|
|
2031
2065
|
}
|
|
2032
|
-
|
|
2033
|
-
} catch (Exception e) {
|
|
2034
|
-
callbackContext.success("rotateScreen failed, exception is : " + e.getMessage());
|
|
2035
|
-
}
|
|
2066
|
+
});
|
|
2036
2067
|
}
|
|
2037
2068
|
|
|
2038
2069
|
public void deviceInfo(CallbackContext callbackContext) {
|
|
@@ -2130,12 +2161,20 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2130
2161
|
final String imageSourcePath,
|
|
2131
2162
|
final String imgSrcType,
|
|
2132
2163
|
final String destinationPath) {
|
|
2164
|
+
convertImageTo64BaseStringAsync(cb, imageSourcePath, imgSrcType, destinationPath, false);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
private void convertImageTo64BaseStringAsync(final CallbackContext cb,
|
|
2168
|
+
final String imageSourcePath,
|
|
2169
|
+
final String imgSrcType,
|
|
2170
|
+
final String destinationPath,
|
|
2171
|
+
final boolean deleteImported) {
|
|
2133
2172
|
cordova.getThreadPool().execute(new Runnable() {
|
|
2134
2173
|
@Override public void run() {
|
|
2135
|
-
|
|
2136
|
-
OutputStream desFileWriter = null;
|
|
2174
|
+
|
|
2137
2175
|
ByteArrayOutputStream baos = null;
|
|
2138
2176
|
Bitmap bitmap = null;
|
|
2177
|
+
File compressedTemp = null;
|
|
2139
2178
|
try {
|
|
2140
2179
|
// Common bits
|
|
2141
2180
|
final String[] parts = imageSourcePath.split("/");
|
|
@@ -2154,33 +2193,20 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2154
2193
|
.setCompressFormat(Bitmap.CompressFormat.JPEG)
|
|
2155
2194
|
.compressToFile(fileToCompress);
|
|
2156
2195
|
|
|
2196
|
+
compressedTemp = compressedImageFile;
|
|
2157
2197
|
String timeStamp = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
|
|
2158
2198
|
final String baseDir = (destinationPath != null && !destinationPath.isEmpty())
|
|
2159
2199
|
? (mInterfaceUtil.rootDirectory + "/" + destinationPath)
|
|
2160
2200
|
: (mInterfaceUtil.rootDirectory + "/" + mInterfaceUtil.packageName + "/images");
|
|
2161
2201
|
final String outName = baseName + "_" + timeStamp + ".jpg";
|
|
2162
|
-
final String outFullPath = baseDir + "/" + outName;
|
|
2163
|
-
|
|
2164
2202
|
File outDir = new File(baseDir);
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
if (compressedImageFile.exists()) {
|
|
2169
|
-
srcFileReader = new FileInputStream(compressedImageFile);
|
|
2170
|
-
desFileWriter = new FileOutputStream(new File(outFullPath));
|
|
2171
|
-
byte[] buf = new byte[64 * 1024];
|
|
2172
|
-
int n;
|
|
2173
|
-
while ((n = srcFileReader.read(buf)) > 0) {
|
|
2174
|
-
desFileWriter.write(buf, 0, n);
|
|
2175
|
-
}
|
|
2176
|
-
desFileWriter.flush();
|
|
2203
|
+
String rootPath = mInterfaceUtil.rootDirectory.getCanonicalPath() + File.separator;
|
|
2204
|
+
if (!outDir.getCanonicalPath().startsWith(rootPath)) {
|
|
2205
|
+
throw new IOException("Attachment destination must be inside app storage");
|
|
2177
2206
|
}
|
|
2207
|
+
File outFile = AttachmentFileIO.copy(
|
|
2208
|
+
new FileInputStream(compressedImageFile), outDir, outName);
|
|
2178
2209
|
|
|
2179
|
-
// (Optional) load to normalize EXIF rotation like the sync version did
|
|
2180
|
-
try { bitmap = handleImageRotation(outFullPath); } catch (Throwable ignore) {}
|
|
2181
|
-
|
|
2182
|
-
// Build properties
|
|
2183
|
-
File outFile = new File(outFullPath);
|
|
2184
2210
|
org.json.JSONObject fileProps = new org.json.JSONObject();
|
|
2185
2211
|
fileProps.put("filePath", outFile.getParent());
|
|
2186
2212
|
fileProps.put("fileName", outFile.getName());
|
|
@@ -2189,25 +2215,37 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2189
2215
|
fileProps.put("thumbnail", thumbnail);
|
|
2190
2216
|
|
|
2191
2217
|
// Match original behavior: clear attachmentDestPath if you rely on that global
|
|
2192
|
-
|
|
2218
|
+
|
|
2193
2219
|
|
|
2194
2220
|
postSuccess(cb, fileProps);
|
|
2195
2221
|
return;
|
|
2196
2222
|
}
|
|
2197
2223
|
|
|
2198
|
-
// === CAMERA / GALLERY
|
|
2224
|
+
// === CAMERA / GALLERY → return BASE64 string ===
|
|
2199
2225
|
// Decode with downsampling and fix rotation
|
|
2200
2226
|
BitmapFactory.Options o = new BitmapFactory.Options();
|
|
2201
2227
|
o.inJustDecodeBounds = true; BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2202
2228
|
o.inSampleSize = calcInSampleSize(o, 1920, 1920);
|
|
2203
2229
|
o.inJustDecodeBounds = false;
|
|
2204
2230
|
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2231
|
+
bitmap = BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2232
|
+
if (bitmap != null) {
|
|
2233
|
+
try {
|
|
2234
|
+
ExifInterface exif = new ExifInterface(imageSourcePath);
|
|
2235
|
+
Matrix matrix = new Matrix();
|
|
2236
|
+
switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
|
|
2237
|
+
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: matrix.setScale(-1, 1); break;
|
|
2238
|
+
case ExifInterface.ORIENTATION_ROTATE_180: matrix.setRotate(180); break;
|
|
2239
|
+
case ExifInterface.ORIENTATION_FLIP_VERTICAL: matrix.setScale(1, -1); break;
|
|
2240
|
+
case ExifInterface.ORIENTATION_TRANSPOSE: matrix.setRotate(90); matrix.postScale(-1, 1); break;
|
|
2241
|
+
case ExifInterface.ORIENTATION_ROTATE_90: matrix.setRotate(90); break;
|
|
2242
|
+
case ExifInterface.ORIENTATION_TRANSVERSE: matrix.setRotate(270); matrix.postScale(-1, 1); break;
|
|
2243
|
+
case ExifInterface.ORIENTATION_ROTATE_270: matrix.setRotate(270); break;
|
|
2244
|
+
}
|
|
2245
|
+
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
|
2246
|
+
if (rotated != bitmap) bitmap.recycle();
|
|
2247
|
+
bitmap = rotated;
|
|
2248
|
+
} catch (IOException ignored) { }
|
|
2211
2249
|
}
|
|
2212
2250
|
if (bitmap == null) {
|
|
2213
2251
|
postError(cb, "decode_failed");
|
|
@@ -2224,18 +2262,18 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2224
2262
|
File f = new File(imageSourcePath);
|
|
2225
2263
|
if (f.exists()) f.delete();
|
|
2226
2264
|
} catch (Throwable ignore) {}
|
|
2227
|
-
|
|
2265
|
+
|
|
2228
2266
|
} else if ("gallery".equalsIgnoreCase(imgSrcType)) {
|
|
2229
|
-
|
|
2267
|
+
|
|
2230
2268
|
}
|
|
2231
2269
|
|
|
2232
2270
|
postSuccess(cb, encodedImage);
|
|
2233
2271
|
} catch (Exception e) {
|
|
2234
|
-
|
|
2272
|
+
|
|
2235
2273
|
postError(cb, "convertImageTo64BaseStringAsync failed: " + e.getMessage());
|
|
2236
2274
|
} finally {
|
|
2237
|
-
|
|
2238
|
-
|
|
2275
|
+
if (compressedTemp != null && !compressedTemp.getAbsolutePath().equals(imageSourcePath)) compressedTemp.delete();
|
|
2276
|
+
if (deleteImported) new File(imageSourcePath).delete();
|
|
2239
2277
|
try { if (baos != null) baos.close(); } catch (Exception ignore) {}
|
|
2240
2278
|
try { if (bitmap != null) bitmap.recycle(); } catch (Exception ignore) {}
|
|
2241
2279
|
}
|
|
@@ -2245,19 +2283,9 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2245
2283
|
|
|
2246
2284
|
|
|
2247
2285
|
private String copyFileFromUriFast(Context ctx, Uri uri, String destName, String destDir) {
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
if (!dir.exists() && !dir.mkdirs()) return null;
|
|
2252
|
-
java.io.File out = new java.io.File(dir, destName);
|
|
2253
|
-
try (java.io.InputStream in = ctx.getContentResolver().openInputStream(uri);
|
|
2254
|
-
java.io.OutputStream os = new java.io.FileOutputStream(out)) {
|
|
2255
|
-
if (in == null) return null;
|
|
2256
|
-
byte[] buf = new byte[64 * 1024];
|
|
2257
|
-
int n; while ((n = in.read(buf)) != -1) os.write(buf, 0, n);
|
|
2258
|
-
os.flush();
|
|
2259
|
-
return out.getAbsolutePath();
|
|
2260
|
-
} catch (Exception e) {
|
|
2286
|
+
try {
|
|
2287
|
+
return copySelectedFile(ctx, uri, destName, destDir);
|
|
2288
|
+
} catch (IOException e) {
|
|
2261
2289
|
android.util.Log.e("mInterface", "copyFileFromUriFast", e);
|
|
2262
2290
|
return null;
|
|
2263
2291
|
}
|
|
@@ -2270,15 +2298,17 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2270
2298
|
case LOCATION_ACCURACY_REQUEST_NEW:
|
|
2271
2299
|
switch (resultCode) {
|
|
2272
2300
|
case Activity.RESULT_OK:
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2301
|
+
if (mInterfaceService.start(cordova.getActivity())) {
|
|
2302
|
+
callback.success();
|
|
2303
|
+
} else {
|
|
2304
|
+
callback.error("Unable to resume location service");
|
|
2305
|
+
}
|
|
2276
2306
|
break;
|
|
2277
2307
|
case Activity.RESULT_CANCELED:
|
|
2278
2308
|
callback.error("oops! you have cancelled...");
|
|
2279
2309
|
break;
|
|
2280
2310
|
}
|
|
2281
|
-
|
|
2311
|
+
return;
|
|
2282
2312
|
}
|
|
2283
2313
|
if (SCANCODEINT == 118 && callback != null) {
|
|
2284
2314
|
if (resultCode == RESULT_OK) {
|
|
@@ -2304,176 +2334,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2304
2334
|
SCANCODEINT = 0;
|
|
2305
2335
|
callback.error(resultCode);
|
|
2306
2336
|
}
|
|
2307
|
-
}else if (requestCode == PICK_IMAGE_FROM_GALLERY
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
if (cb == null) return;
|
|
2311
|
-
|
|
2312
|
-
try {
|
|
2313
|
-
if (resultCode != RESULT_OK || data == null) {
|
|
2314
|
-
cb.error("canceled");
|
|
2315
|
-
return;
|
|
2316
|
-
}
|
|
2317
|
-
|
|
2318
|
-
// Photo Picker may return via getData() or ClipData
|
|
2319
|
-
Uri uri = data.getData();
|
|
2320
|
-
if (uri == null && data.getClipData() != null && data.getClipData().getItemCount() > 0) {
|
|
2321
|
-
uri = data.getClipData().getItemAt(0).getUri();
|
|
2322
|
-
}
|
|
2323
|
-
if (uri == null) {
|
|
2324
|
-
cb.error("no_file_selected");
|
|
2325
|
-
return;
|
|
2326
|
-
}
|
|
2327
|
-
|
|
2328
|
-
final Uri selectedUri = uri;
|
|
2329
|
-
final String destPath = attachmentDestPath; // capture current dest
|
|
2330
|
-
final String galleryInd = String.valueOf(galleryAttachmentInd);
|
|
2331
|
-
|
|
2332
|
-
// Offload ALL heavy work (resolver, copy, bitmap/encode) to Cordova thread pool
|
|
2333
|
-
cordova.getThreadPool().execute(new Runnable() {
|
|
2334
|
-
@Override public void run() {
|
|
2335
|
-
try {
|
|
2336
|
-
ContentResolver cr = cordova.getActivity().getContentResolver();
|
|
2337
|
-
|
|
2338
|
-
String mime = null;
|
|
2339
|
-
try { mime = cr.getType(selectedUri); } catch (Throwable ignore) {}
|
|
2340
|
-
|
|
2341
|
-
String defExt = (mime != null && mime.contains("/"))
|
|
2342
|
-
? mime.substring(mime.indexOf('/') + 1).toLowerCase()
|
|
2343
|
-
: "jpg";
|
|
2344
|
-
|
|
2345
|
-
// Get a display name if provider allows; otherwise build a sane fallback
|
|
2346
|
-
String fileName = safeGetDisplayName(cr, selectedUri, defExt);
|
|
2347
|
-
String ext = fileName.contains(".")
|
|
2348
|
-
? fileName.substring(fileName.lastIndexOf('.')).toLowerCase()
|
|
2349
|
-
: ("." + defExt);
|
|
2350
|
-
|
|
2351
|
-
// Copy the user-selected URI into app-private storage (no READ_MEDIA_* needed)
|
|
2352
|
-
String localPath = copyFileFromUriFast(
|
|
2353
|
-
cordova.getActivity().getApplicationContext(),
|
|
2354
|
-
selectedUri, fileName, destPath);
|
|
2355
|
-
|
|
2356
|
-
if (localPath == null) {
|
|
2357
|
-
cb.error("copy_failed");
|
|
2358
|
-
return;
|
|
2359
|
-
}
|
|
2360
|
-
|
|
2361
|
-
// Accept only image-like picks (by MIME or extension)
|
|
2362
|
-
boolean imageLike =
|
|
2363
|
-
(mime != null && mime.startsWith("image/")) ||
|
|
2364
|
-
ext.equals(".jpg") || ext.equals(".jpeg") ||
|
|
2365
|
-
ext.equals(".png") || ext.equals(".heic");
|
|
2366
|
-
|
|
2367
|
-
if (!imageLike) {
|
|
2368
|
-
cb.error("Only JPEG/PNG/HEIC images are allowed.");
|
|
2369
|
-
return;
|
|
2370
|
-
}
|
|
2371
|
-
|
|
2372
|
-
// Run your existing conversion on a worker too (non-blocking)
|
|
2373
|
-
if ("true".equals(galleryInd)) {
|
|
2374
|
-
convertImageTo64BaseStringAsync(cb, localPath, "compress", destPath);
|
|
2375
|
-
} else {
|
|
2376
|
-
convertImageTo64BaseStringAsync(cb, localPath, "gallery", "");
|
|
2377
|
-
}
|
|
2378
|
-
} catch (Exception e) {
|
|
2379
|
-
cb.error("PICK_IMAGE_FROM_GALLERY: " + e.getMessage());
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
});
|
|
2383
|
-
return; // IMPORTANT: stop here so no other branch falls through
|
|
2384
|
-
} catch (Exception e) {
|
|
2385
|
-
cb.error("PICK_IMAGE_FROM_GALLERY dispatch failed: " + e.getMessage());
|
|
2386
|
-
return;
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
else if (requestCode == NEW_FILE_PICK_REQUEST && callback != null) {
|
|
2390
|
-
try {
|
|
2391
|
-
Uri uri = data.getData();
|
|
2392
|
-
String fileName, extension, filePath;
|
|
2393
|
-
JSONObject fileProperities;
|
|
2394
|
-
Cursor cursor = null;
|
|
2395
|
-
if (uri.getScheme().equals("file")) {
|
|
2396
|
-
fileName = uri.getLastPathSegment();
|
|
2397
|
-
if (fileName.indexOf(".") > 0) {
|
|
2398
|
-
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
|
2399
|
-
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
2400
|
-
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2401
|
-
fileName = fileName + "_" + timeStamp + extension;
|
|
2402
|
-
}
|
|
2403
|
-
} else {
|
|
2404
|
-
try {
|
|
2405
|
-
cursor = cordova.getActivity().getApplicationContext().getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DISPLAY_NAME}, null, null, null);
|
|
2406
|
-
if (cursor != null && cursor.moveToFirst()) {
|
|
2407
|
-
int displayNameIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME);
|
|
2408
|
-
if (displayNameIndex != -1) {
|
|
2409
|
-
fileName = cursor.getString(displayNameIndex);
|
|
2410
|
-
} else {
|
|
2411
|
-
fileName = "";
|
|
2412
|
-
}
|
|
2413
|
-
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2414
|
-
if (!extension.equals(".jpeg") && !extension.equals(".jpg") && !extension.equals(".png")) {
|
|
2415
|
-
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
2416
|
-
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
|
2417
|
-
fileName = fileName + "_" + timeStamp + extension;
|
|
2418
|
-
}
|
|
2419
|
-
|
|
2420
|
-
} else {
|
|
2421
|
-
fileName = uri.getLastPathSegment();
|
|
2422
|
-
}
|
|
2423
|
-
} finally {
|
|
2424
|
-
if (cursor != null) {
|
|
2425
|
-
cursor.close();
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
|
|
2430
|
-
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2431
|
-
|
|
2432
|
-
filePath = copyFileFromUri(cordova.getActivity().getApplicationContext(), uri, fileName, attachmentDestPath, callback);
|
|
2433
|
-
File file = new File(filePath);
|
|
2434
|
-
String mimeType = getMimeType(filePath, uri);
|
|
2435
|
-
System.out.println("Mime type is: " + mimeType);
|
|
2436
|
-
double fileSize = file.length();
|
|
2437
|
-
if (filePath != null) {
|
|
2438
|
-
try {
|
|
2439
|
-
if (requestCode == NEW_FILE_PICK_REQUEST) {
|
|
2440
|
-
if (extension.equals(".heic")) {
|
|
2441
|
-
convertImageTo64BaseString(callback, filePath, "compress", attachmentDestPath);
|
|
2442
|
-
} else if (mimeType != null) {
|
|
2443
|
-
if (mimeType.contains("image")) {
|
|
2444
|
-
convertImageTo64BaseString(callback, filePath, "compress", attachmentDestPath);
|
|
2445
|
-
} else {
|
|
2446
|
-
fileProperities = new JSONObject();
|
|
2447
|
-
fileProperities.put("filePath", filePath.substring(0, filePath.lastIndexOf(File.separator)));
|
|
2448
|
-
fileProperities.put("fileName", fileName);
|
|
2449
|
-
fileProperities.put("fileSize", fileSize);
|
|
2450
|
-
fileProperities.put("fileExtension", extension);
|
|
2451
|
-
fileProperities.put("thumbnail", getFileThumbnail(filePath, extension));
|
|
2452
|
-
attachmentDestPath = "";
|
|
2453
|
-
callback.success(fileProperities);
|
|
2454
|
-
}
|
|
2455
|
-
} else {
|
|
2456
|
-
fileProperities = new JSONObject();
|
|
2457
|
-
fileProperities.put("filePath", filePath.substring(0, filePath.lastIndexOf(File.separator)));
|
|
2458
|
-
fileProperities.put("fileName", fileName);
|
|
2459
|
-
fileProperities.put("fileSize", fileSize);
|
|
2460
|
-
fileProperities.put("fileExtension", extension);
|
|
2461
|
-
fileProperities.put("thumbnail", getFileThumbnail(filePath, extension));
|
|
2462
|
-
callback.success(fileProperities);
|
|
2463
|
-
}
|
|
2464
|
-
}
|
|
2465
|
-
} catch (Exception e) {
|
|
2466
|
-
callback.error("onActivityResult failed, exception is : " + e.getMessage());
|
|
2467
|
-
}
|
|
2468
|
-
} else {
|
|
2469
|
-
callback.error("onActivityResult: Selected file path is null");
|
|
2470
|
-
}
|
|
2471
|
-
} catch (Exception e) {
|
|
2472
|
-
callback.error("onActivityResult failed, exception is : " + e.getMessage());
|
|
2473
|
-
}
|
|
2337
|
+
} else if ((requestCode == PICK_IMAGE_FROM_GALLERY || requestCode == NEW_FILE_PICK_REQUEST
|
|
2338
|
+
|| requestCode == PICK_FILE_REQUEST) && callback != null) {
|
|
2339
|
+
handlePickedFile(requestCode, resultCode, data);
|
|
2474
2340
|
} else if (requestCode == REQUEST_IMAGE_CAPTURE && callback != null) {
|
|
2475
2341
|
if (resultCode == RESULT_OK) {
|
|
2476
|
-
String imagePath = data.getStringExtra("imagePath");
|
|
2342
|
+
String imagePath = data == null ? null : data.getStringExtra("imagePath");
|
|
2477
2343
|
if (imagePath != null && !imagePath.isEmpty()) {
|
|
2478
2344
|
pictureFilePath = imagePath;
|
|
2479
2345
|
if (cameraAttachmentInd.equals("true")) {
|
|
@@ -2485,12 +2351,10 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2485
2351
|
callback.error("failure");
|
|
2486
2352
|
}
|
|
2487
2353
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2354
|
+
if (pictureFilePath != null && !pictureFilePath.isEmpty()) {
|
|
2355
|
+
File file = new File(pictureFilePath);
|
|
2356
|
+
if (file.exists()) file.delete();
|
|
2357
|
+
}
|
|
2494
2358
|
callback.error("failure");
|
|
2495
2359
|
} else {
|
|
2496
2360
|
callback.error(resultCode);
|
|
@@ -2499,158 +2363,10 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2499
2363
|
if (resultCode == RESULT_OK) {
|
|
2500
2364
|
convertImageTo64BaseString(callback, pictureFilePath, "compress", attachmentDestPath);
|
|
2501
2365
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
file.delete();
|
|
2505
|
-
}
|
|
2506
|
-
callback.error("failure");
|
|
2507
|
-
} else {
|
|
2508
|
-
callback.error(resultCode);
|
|
2509
|
-
}
|
|
2510
|
-
} else if (requestCode == PICK_FILE_REQUEST && callback != null) {
|
|
2511
|
-
if (resultCode == RESULT_OK) {
|
|
2512
|
-
String fileName = null,
|
|
2513
|
-
getfilePath = null,
|
|
2514
|
-
filePath,
|
|
2515
|
-
fileExtension,
|
|
2516
|
-
fileType,
|
|
2517
|
-
fileSize = null,
|
|
2518
|
-
storageDefinition;
|
|
2519
|
-
final String docId,
|
|
2520
|
-
type,
|
|
2521
|
-
id;
|
|
2522
|
-
final String[] split;
|
|
2523
|
-
final String tag,
|
|
2524
|
-
path;
|
|
2525
|
-
final int splitIndex;
|
|
2526
|
-
Cursor cursor;
|
|
2527
|
-
long getSize;
|
|
2528
|
-
JSONObject fileProperities;
|
|
2529
|
-
Uri uri = data.getData(); //get uri for selected file
|
|
2530
|
-
fileType = this.cordova.getActivity().getContentResolver().getType(uri); // get mimeType for selected file
|
|
2531
|
-
File getFileName,
|
|
2532
|
-
file;
|
|
2533
|
-
try {
|
|
2534
|
-
//API LEVEL 19 AND ABOVE (TO GET FILEPATH)
|
|
2535
|
-
if (Build.VERSION.SDK_INT >= 19 && !Build.MANUFACTURER.equals("samsung") && DocumentsContract.isDocumentUri(cordova.getActivity(), uri)) {
|
|
2536
|
-
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { // ExternalStorageProvider
|
|
2537
|
-
docId = DocumentsContract.getDocumentId(uri);
|
|
2538
|
-
split = docId.split(":");
|
|
2539
|
-
type = split[0];
|
|
2540
|
-
if ("primary".equalsIgnoreCase(type)) {
|
|
2541
|
-
getfilePath = mInterfaceUtil.rootDirectory + "/" + split[1];
|
|
2542
|
-
} else {
|
|
2543
|
-
if (Environment.isExternalStorageRemovable()) {
|
|
2544
|
-
storageDefinition = System.getenv("EXTERNAL_STORAGE");
|
|
2545
|
-
getfilePath = storageDefinition;
|
|
2546
|
-
} else {
|
|
2547
|
-
splitIndex = docId.indexOf(':', 1);
|
|
2548
|
-
tag = docId.substring(0, splitIndex);
|
|
2549
|
-
path = docId.substring(splitIndex + 1);
|
|
2550
|
-
if (new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) != null) {
|
|
2551
|
-
storageDefinition = new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) + "/" + path;
|
|
2552
|
-
file = new File(storageDefinition);
|
|
2553
|
-
if (file.exists() && file.canRead()) {
|
|
2554
|
-
getfilePath = storageDefinition;
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
}
|
|
2559
|
-
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { // DownloadsProvider
|
|
2560
|
-
id = DocumentsContract.getDocumentId(uri);
|
|
2561
|
-
final Uri contentUri = ContentUris.withAppendedId(
|
|
2562
|
-
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
|
|
2563
|
-
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, null, null);
|
|
2564
|
-
|
|
2565
|
-
} else if ("com.android.providers.media.documents".equals(uri.getAuthority())) { // MediaProvider
|
|
2566
|
-
docId = DocumentsContract.getDocumentId(uri);
|
|
2567
|
-
split = docId.split(":");
|
|
2568
|
-
type = split[0];
|
|
2569
|
-
Uri contentUri = null;
|
|
2570
|
-
if ("image".equals(type)) {
|
|
2571
|
-
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
|
2572
|
-
} else if ("video".equals(type)) {
|
|
2573
|
-
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
2574
|
-
} else if ("audio".equals(type)) {
|
|
2575
|
-
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
|
2576
|
-
}
|
|
2577
|
-
final String selection = "_id=?";
|
|
2578
|
-
final String[] selectionArgs = new String[]{
|
|
2579
|
-
split[1]
|
|
2580
|
-
};
|
|
2581
|
-
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, selection, selectionArgs);
|
|
2582
|
-
}
|
|
2583
|
-
// *** API Level 19 and Above (To Get FileName,FileExtension and FileSize)**** //
|
|
2584
|
-
cursor = cordova.getActivity().getContentResolver().query(uri, null, null, null, null, null);
|
|
2585
|
-
try {
|
|
2586
|
-
if (cursor != null && cursor.moveToFirst()) {
|
|
2587
|
-
int displayNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
2588
|
-
if (displayNameIndex != -1) {
|
|
2589
|
-
fileName = cursor.getString(displayNameIndex);
|
|
2590
|
-
} else {
|
|
2591
|
-
fileName = "";
|
|
2592
|
-
}
|
|
2593
|
-
|
|
2594
|
-
int fileSizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
|
|
2595
|
-
if (!cursor.isNull(fileSizeIndex) && fileSizeIndex != -1) {
|
|
2596
|
-
fileSize = cursor.getString(fileSizeIndex);
|
|
2597
|
-
} else {
|
|
2598
|
-
fileSize = "0";
|
|
2599
|
-
}
|
|
2600
|
-
}
|
|
2601
|
-
} finally {
|
|
2602
|
-
cursor.close();
|
|
2603
|
-
}
|
|
2604
|
-
// *** API Level 19 below and SAMSUNG (To Get FileProperties of MediaFiles)**** //
|
|
2605
|
-
} else {
|
|
2606
|
-
if (fileType != null) {
|
|
2607
|
-
String[] projection = {
|
|
2608
|
-
MediaStore.Images.Media.DATA,
|
|
2609
|
-
MediaStore.Images.Media.SIZE,
|
|
2610
|
-
MediaStore.Images.Media.DISPLAY_NAME
|
|
2611
|
-
};
|
|
2612
|
-
cursor = cordova.getActivity().getContentResolver().query(uri, projection, null, null, null);
|
|
2613
|
-
if (cursor.moveToFirst()) {
|
|
2614
|
-
getfilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
|
|
2615
|
-
fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
|
|
2616
|
-
fileSize = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE));
|
|
2617
|
-
}
|
|
2618
|
-
cursor.close();
|
|
2619
|
-
// API LEVEL 19 BELOW AND SAMSUNG (TO GET FILEPROPERTIES OF NORMAL FILES(EX:txt,.pdf,etc..,))
|
|
2620
|
-
} else {
|
|
2621
|
-
getfilePath = data.getData().getPath();
|
|
2622
|
-
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2623
|
-
getFileName = new File(getfilePath);
|
|
2624
|
-
fileName = getFileName.getName();
|
|
2625
|
-
getSize = getFileName.length();
|
|
2626
|
-
fileSize = String.valueOf(getSize);
|
|
2627
|
-
}
|
|
2628
|
-
}
|
|
2629
|
-
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2630
|
-
fileExtension = "." + getfilePath.substring(getfilePath.lastIndexOf(".") + 1).toLowerCase();
|
|
2631
|
-
// SEND BELOW JSON OBJECT TO PLUGIN CALLBACK
|
|
2632
|
-
if (filePath != null) {
|
|
2633
|
-
try {
|
|
2634
|
-
if (fileExtension.equals(".jpeg") || fileExtension.equals(".jpg") || fileExtension.equals(".png")) {
|
|
2635
|
-
convertImageTo64BaseString(callback, filePath + "/" + fileName, "compress", attachmentDestPath);
|
|
2636
|
-
} else {
|
|
2637
|
-
fileProperities = new JSONObject();
|
|
2638
|
-
fileProperities.put("filePath", filePath);
|
|
2639
|
-
fileProperities.put("fileName", fileName);
|
|
2640
|
-
fileProperities.put("fileSize", fileSize);
|
|
2641
|
-
fileProperities.put("fileExtension", fileExtension);
|
|
2642
|
-
callback.success(fileProperities);
|
|
2643
|
-
}
|
|
2644
|
-
} catch (Exception e) {
|
|
2645
|
-
callback.error("Failed to process PICK_FILE_REQUEST");
|
|
2646
|
-
}
|
|
2647
|
-
} else {
|
|
2648
|
-
callback.error("File path was null");
|
|
2649
|
-
}
|
|
2650
|
-
} catch (Exception e) {
|
|
2651
|
-
e.printStackTrace();
|
|
2366
|
+
if (pictureFilePath != null && !pictureFilePath.isEmpty()) {
|
|
2367
|
+
File file = new File(pictureFilePath);
|
|
2368
|
+
if (file.exists()) file.delete();
|
|
2652
2369
|
}
|
|
2653
|
-
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2654
2370
|
callback.error("failure");
|
|
2655
2371
|
} else {
|
|
2656
2372
|
callback.error(resultCode);
|
|
@@ -2665,62 +2381,130 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2665
2381
|
|
|
2666
2382
|
@Override
|
|
2667
2383
|
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
callback.success("success");
|
|
2682
|
-
} else {
|
|
2683
|
-
callback.error(failedPermission);
|
|
2384
|
+
if (requestCode != pendingPermissionRequest || permissionCallback == null) return;
|
|
2385
|
+
CallbackContext resultCallback = permissionCallback;
|
|
2386
|
+
permissionCallback = null;
|
|
2387
|
+
pendingPermissionRequest = -1;
|
|
2388
|
+
if (grantResults.length == 0) {
|
|
2389
|
+
resultCallback.error("failure");
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
for (String permission : permissions) {
|
|
2393
|
+
if (!isPermissionSatisfied(permission)) {
|
|
2394
|
+
resultCallback.error(Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)
|
|
2395
|
+
? "background_location" : "failure");
|
|
2396
|
+
return;
|
|
2684
2397
|
}
|
|
2685
|
-
} catch (Exception e) {
|
|
2686
|
-
e.printStackTrace();
|
|
2687
2398
|
}
|
|
2399
|
+
resultCallback.success("success");
|
|
2688
2400
|
}
|
|
2689
2401
|
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2402
|
+
private void handlePickedFile(int requestCode, int resultCode, Intent data) {
|
|
2403
|
+
final CallbackContext resultCallback = callback;
|
|
2404
|
+
callback = null;
|
|
2405
|
+
if (resultCallback == null) return;
|
|
2406
|
+
if (resultCode != RESULT_OK) {
|
|
2407
|
+
attachmentDestPath = "";
|
|
2408
|
+
if (resultCode == Activity.RESULT_CANCELED) resultCallback.error(requestCode == PICK_IMAGE_FROM_GALLERY ? "canceled" : "failure");
|
|
2409
|
+
else resultCallback.error(resultCode);
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2412
|
+
Uri selected = data == null ? null : data.getData();
|
|
2413
|
+
if (selected == null && data != null && data.getClipData() != null
|
|
2414
|
+
&& data.getClipData().getItemCount() > 0) {
|
|
2415
|
+
selected = data.getClipData().getItemAt(0).getUri();
|
|
2416
|
+
}
|
|
2417
|
+
final Uri uri = selected;
|
|
2418
|
+
if (uri == null) {
|
|
2419
|
+
attachmentDestPath = "";
|
|
2420
|
+
resultCallback.error("No file was selected");
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2423
|
+
final String destination = attachmentDestPath;
|
|
2424
|
+
final boolean gallery = requestCode == PICK_IMAGE_FROM_GALLERY;
|
|
2425
|
+
final boolean compressGallery = "true".equals(galleryAttachmentInd);
|
|
2426
|
+
attachmentDestPath = "";
|
|
2427
|
+
// Copy cloud/document content immediately while the picker URI grant is valid.
|
|
2428
|
+
cordova.getThreadPool().execute(() -> {
|
|
2429
|
+
try {
|
|
2430
|
+
Context context = cordova.getActivity().getApplicationContext();
|
|
2431
|
+
ContentResolver resolver = context.getContentResolver();
|
|
2432
|
+
String mimeType = null;
|
|
2433
|
+
try { mimeType = resolver.getType(uri); } catch (RuntimeException ignored) { }
|
|
2434
|
+
String displayName = getSelectedDisplayName(resolver, uri, mimeType);
|
|
2435
|
+
String extension = getExtension(displayName);
|
|
2436
|
+
if (gallery && !("image/jpeg".equals(mimeType) || "image/png".equals(mimeType)
|
|
2437
|
+
|| "image/heic".equals(mimeType) || "image/heif".equals(mimeType)
|
|
2438
|
+
|| ".jpg".equals(extension) || ".jpeg".equals(extension)
|
|
2439
|
+
|| ".png".equals(extension) || ".heic".equals(extension) || ".heif".equals(extension))) {
|
|
2440
|
+
resultCallback.error("Only JPEG, PNG or HEIC images are allowed to attach.");
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
2443
|
+
// A gallery import is an intermediate file, never the user's original photo.
|
|
2444
|
+
String path = copySelectedFile(context, uri, displayName, gallery ? "" : destination);
|
|
2445
|
+
File imported = new File(path);
|
|
2446
|
+
boolean image = gallery || (mimeType != null && mimeType.startsWith("image/"))
|
|
2447
|
+
|| ".heic".equals(extension) || ".heif".equals(extension);
|
|
2448
|
+
if (image) {
|
|
2449
|
+
convertImageTo64BaseStringAsync(resultCallback, path,
|
|
2450
|
+
gallery && !compressGallery ? "gallery" : "compress", destination, true);
|
|
2451
|
+
} else {
|
|
2452
|
+
JSONObject properties = new JSONObject();
|
|
2453
|
+
properties.put("filePath", imported.getParent());
|
|
2454
|
+
properties.put("fileName", imported.getName());
|
|
2455
|
+
properties.put("fileSize", imported.length());
|
|
2456
|
+
properties.put("fileExtension", getExtension(imported.getName()));
|
|
2457
|
+
properties.put("thumbnail", getFileThumbnail(path, getExtension(imported.getName())));
|
|
2458
|
+
resultCallback.success(properties);
|
|
2459
|
+
}
|
|
2460
|
+
} catch (Exception e) {
|
|
2461
|
+
resultCallback.error("Unable to read the selected file: " + e.getMessage());
|
|
2706
2462
|
}
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2707
2465
|
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
if (
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) >= 0) {
|
|
2715
|
-
outputStream.write(buffer, 0, buffer.length);
|
|
2716
|
-
}
|
|
2717
|
-
} else {
|
|
2718
|
-
callback.error("Error occurred in opening outputStream");
|
|
2466
|
+
private String getSelectedDisplayName(ContentResolver resolver, Uri uri, String mimeType) {
|
|
2467
|
+
String name = null;
|
|
2468
|
+
try (Cursor cursor = resolver.query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) {
|
|
2469
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
2470
|
+
int column = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
2471
|
+
if (column >= 0) name = cursor.getString(column);
|
|
2719
2472
|
}
|
|
2473
|
+
} catch (RuntimeException ignored) {
|
|
2474
|
+
// Providers are not required to supply a display name.
|
|
2475
|
+
}
|
|
2476
|
+
if (name == null || name.trim().isEmpty()) name = "attachment";
|
|
2477
|
+
if (getExtension(name).isEmpty() && mimeType != null) {
|
|
2478
|
+
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
|
|
2479
|
+
if (extension != null) name += "." + extension;
|
|
2480
|
+
}
|
|
2481
|
+
return name;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
private String getExtension(String name) {
|
|
2485
|
+
int dot = name.lastIndexOf('.');
|
|
2486
|
+
return dot > 0 ? name.substring(dot).toLowerCase(Locale.ROOT) : "";
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
private String copySelectedFile(Context context, Uri uri, String fileName, String destinationPath) throws IOException {
|
|
2490
|
+
File root = mInterfaceUtil.rootDirectory;
|
|
2491
|
+
if (root == null) throw new IOException("App storage is unavailable");
|
|
2492
|
+
File directory = new File(root, TextUtils.isEmpty(destinationPath)
|
|
2493
|
+
? mInterfaceUtil.packageName + "/images" : destinationPath);
|
|
2494
|
+
String rootPath = root.getCanonicalPath() + File.separator;
|
|
2495
|
+
if (!directory.getCanonicalPath().startsWith(rootPath)) {
|
|
2496
|
+
throw new IOException("Attachment destination must be inside app storage");
|
|
2497
|
+
}
|
|
2498
|
+
return AttachmentFileIO.copy(context.getContentResolver().openInputStream(uri), directory, fileName).getAbsolutePath();
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
public String copyFileFromUri(Context context, Uri uri, String fileName, String destinationPath, CallbackContext resultCallback) {
|
|
2502
|
+
try {
|
|
2503
|
+
return copySelectedFile(context, uri, fileName, destinationPath);
|
|
2720
2504
|
} catch (Exception e) {
|
|
2721
|
-
|
|
2505
|
+
resultCallback.error("copyFileFromUri failed: " + e.getMessage());
|
|
2506
|
+
return null;
|
|
2722
2507
|
}
|
|
2723
|
-
return outPutFilePath;
|
|
2724
2508
|
}
|
|
2725
2509
|
|
|
2726
2510
|
/* CHECKING THE BACKGROUND SERVICE RUNNING OR NOT */
|