cordova-plugin-mserviceinterface-2.0 1.0.103 → 1.0.105
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 +2 -2
- package/plugin.xml +7 -13
- package/src/android/GeofenceBroadcastReceiver.java +20 -103
- package/src/android/doubleogradle.gradle +0 -4
- package/src/android/mInterface.java +667 -365
- package/src/android/mInterfaceService.java +10 -3
- package/src/android/mInterfaceUtil.java +233 -152
- package/src/android/res/layout/activity_camera.xml +12 -0
- package/scripts/mservice-deeplink-setup.js +0 -1182
- package/templates/ios/SceneDelegate.swift +0 -358
- package/www/mServiceAppLink.js +0 -115
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
package com.selfservit.util;
|
|
2
2
|
|
|
3
|
+
import com.google.android.gms.tasks.CancellationTokenSource;
|
|
4
|
+
|
|
5
|
+
import com.google.android.gms.location.CurrentLocationRequest;
|
|
6
|
+
|
|
7
|
+
import com.google.android.gms.common.GoogleApiAvailability;
|
|
8
|
+
|
|
9
|
+
import androidx.core.location.LocationManagerCompat;
|
|
10
|
+
|
|
11
|
+
import android.os.SystemClock;
|
|
12
|
+
|
|
13
|
+
import android.os.Looper;
|
|
14
|
+
|
|
15
|
+
import android.os.Handler;
|
|
16
|
+
|
|
17
|
+
import android.location.LocationManager;
|
|
18
|
+
|
|
3
19
|
import static android.app.Activity.RESULT_OK;
|
|
4
20
|
|
|
5
21
|
import android.Manifest;
|
|
@@ -9,7 +25,7 @@ import android.app.AlertDialog;
|
|
|
9
25
|
import android.app.PendingIntent;
|
|
10
26
|
import android.app.ProgressDialog;
|
|
11
27
|
import android.content.ContentResolver;
|
|
12
|
-
import android.content.
|
|
28
|
+
import android.content.ContentUris;
|
|
13
29
|
import android.content.Context;
|
|
14
30
|
import android.content.DialogInterface;
|
|
15
31
|
import android.content.Intent;
|
|
@@ -35,6 +51,7 @@ import android.os.AsyncTask;
|
|
|
35
51
|
import android.os.Build;
|
|
36
52
|
import android.os.Bundle;
|
|
37
53
|
import android.os.Environment;
|
|
54
|
+
import android.provider.DocumentsContract;
|
|
38
55
|
import android.provider.MediaStore;
|
|
39
56
|
import android.provider.OpenableColumns;
|
|
40
57
|
import android.provider.Settings;
|
|
@@ -42,6 +59,7 @@ import android.text.TextUtils;
|
|
|
42
59
|
import android.util.Base64;
|
|
43
60
|
import android.util.Log;
|
|
44
61
|
import android.util.Patterns;
|
|
62
|
+
import android.view.KeyEvent;
|
|
45
63
|
import android.webkit.MimeTypeMap;
|
|
46
64
|
import android.widget.ProgressBar;
|
|
47
65
|
import android.widget.Toast;
|
|
@@ -100,7 +118,6 @@ import java.util.Arrays;
|
|
|
100
118
|
import java.util.Collections;
|
|
101
119
|
import java.util.Date;
|
|
102
120
|
import java.util.List;
|
|
103
|
-
import java.util.Locale;
|
|
104
121
|
import java.util.Stack;
|
|
105
122
|
import java.util.TimeZone;
|
|
106
123
|
import java.util.zip.ZipEntry;
|
|
@@ -117,11 +134,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
117
134
|
public Stack<ProgressDialog> spinnerDialogStack = new Stack<ProgressDialog>();
|
|
118
135
|
private static final int PICK_FILE_REQUEST = 1;
|
|
119
136
|
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;
|
|
125
137
|
private static JSONArray arguments = null;
|
|
126
138
|
private String pictureFilePath;
|
|
127
139
|
private String cameraAttachmentInd = "false";
|
|
@@ -140,7 +152,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
140
152
|
private static final String PORTRAIT = "portrait";
|
|
141
153
|
private static final String LANDSCAPE = "landscape";
|
|
142
154
|
private static final String ANDROID_PLATFORM = "Android";
|
|
143
|
-
String currentLocationInd = "";
|
|
144
155
|
Location mCurrentLocation1;
|
|
145
156
|
LocationRequest mLocationRequest1;
|
|
146
157
|
GoogleApiClient mGoogleApiClient1;
|
|
@@ -158,7 +169,8 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
158
169
|
try {
|
|
159
170
|
super.onResume(multitasking);
|
|
160
171
|
//To avoid starting service after getting permissions initially.
|
|
161
|
-
if (!mInterfaceUtil.deviceID.equalsIgnoreCase("")) {
|
|
172
|
+
if (!mInterfaceUtil.deviceID.equalsIgnoreCase("") || isServiceRunning(mInterfaceService.class)) {
|
|
173
|
+
// Re-evaluate an existing service too: legacy JS may skip StartService.
|
|
162
174
|
mInterfaceService.start(cordova.getActivity());
|
|
163
175
|
}
|
|
164
176
|
} catch (Exception e) {
|
|
@@ -174,6 +186,8 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
174
186
|
|
|
175
187
|
@Override
|
|
176
188
|
public void onDestroy() {
|
|
189
|
+
locationPluginDestroyed = true;
|
|
190
|
+
cancelCurrentLocationRequest();
|
|
177
191
|
mInterfaceService.stopIfNotTracking(cordova.getActivity());
|
|
178
192
|
if (mGoogleApiClient1 != null) {
|
|
179
193
|
if (mGoogleApiClient1.isConnected()) {
|
|
@@ -184,6 +198,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
184
198
|
super.onDestroy();
|
|
185
199
|
}
|
|
186
200
|
|
|
201
|
+
@Override
|
|
202
|
+
public void onReset() {
|
|
203
|
+
cancelCurrentLocationRequest();
|
|
204
|
+
super.onReset();
|
|
205
|
+
}
|
|
206
|
+
|
|
187
207
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
188
208
|
@Override
|
|
189
209
|
public boolean execute(final String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
|
|
@@ -219,11 +239,10 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
219
239
|
try {
|
|
220
240
|
boolean appInfoUpdated = new mInterfaceUtil().updateAppInfo(args);
|
|
221
241
|
System.out.println("appInfoUpdated: " + appInfoUpdated);
|
|
222
|
-
if (mInterfaceService.start(cordova.getActivity())) {
|
|
223
|
-
|
|
224
|
-
} else {
|
|
225
|
-
callbackContext.error("Unable to start service while the app is in the background");
|
|
242
|
+
if (!mInterfaceService.start(cordova.getActivity())) {
|
|
243
|
+
throw new IllegalStateException("Service start deferred until the app is visible or permitted");
|
|
226
244
|
}
|
|
245
|
+
callbackContext.success("Success");
|
|
227
246
|
} catch (Exception e) {
|
|
228
247
|
System.out.println("Unable to StartService, Exception is: " + e.getMessage());
|
|
229
248
|
callbackContext.error("Unable to StartService, Exception is: " + e.getMessage());
|
|
@@ -491,6 +510,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
491
510
|
str = "true";
|
|
492
511
|
System.out.println("service check is: " + str + " " + isServiceRunning(mInterfaceService.class));
|
|
493
512
|
}
|
|
513
|
+
mInterfaceService.start(cordova.getActivity());
|
|
494
514
|
callbackContext.success(str);
|
|
495
515
|
} catch (Exception e) {
|
|
496
516
|
callbackContext.error(e.getMessage());
|
|
@@ -622,19 +642,8 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
622
642
|
callbackContext.error(e.getMessage());
|
|
623
643
|
}
|
|
624
644
|
} else if ("GetCurrentLocation".equals(action)) {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
callback = callbackContext;
|
|
628
|
-
createLocationRequest1();
|
|
629
|
-
this.mGoogleApiClient1 = new GoogleApiClient.Builder(cordova.getActivity())
|
|
630
|
-
.addConnectionCallbacks(this)
|
|
631
|
-
.addOnConnectionFailedListener(this)
|
|
632
|
-
.addApi(LocationServices.API)
|
|
633
|
-
.build();
|
|
634
|
-
mGoogleApiClient1.connect();
|
|
635
|
-
} catch (Exception e) {
|
|
636
|
-
callbackContext.error(e.getMessage());
|
|
637
|
-
}
|
|
645
|
+
getCurrentLocation(callbackContext);
|
|
646
|
+
return true;
|
|
638
647
|
} else if (action.equals("GetSyncIndicator")) {
|
|
639
648
|
try {
|
|
640
649
|
File newQueueFolder, oldQueueFolder;
|
|
@@ -904,8 +913,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
904
913
|
}
|
|
905
914
|
} else if (action.equals("CaptureImageFromCamera")) {
|
|
906
915
|
try {
|
|
907
|
-
attachmentDestPath = "";
|
|
908
|
-
cameraAttachmentInd = "false";
|
|
909
916
|
if (args.length() > 0) {
|
|
910
917
|
attachmentDestPath = args.optJSONObject(0).optString("destinationPath");
|
|
911
918
|
cameraAttachmentInd = args.getJSONObject(0).optString("attachmentInd");
|
|
@@ -917,8 +924,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
917
924
|
}
|
|
918
925
|
} else if (action.equals("PickImageFromGallery")) {
|
|
919
926
|
try {
|
|
920
|
-
attachmentDestPath = "";
|
|
921
|
-
galleryAttachmentInd = "false";
|
|
922
927
|
if (args.length() > 0) {
|
|
923
928
|
attachmentDestPath = args.optJSONObject(0).optString("destinationPath");
|
|
924
929
|
galleryAttachmentInd = args.getJSONObject(0).optString("attachmentInd");
|
|
@@ -1494,6 +1499,122 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1494
1499
|
return false;
|
|
1495
1500
|
}
|
|
1496
1501
|
|
|
1502
|
+
private static final long CURRENT_LOCATION_TIMEOUT_MS = 10_000L;
|
|
1503
|
+
private static final String CURRENT_LOCATION_TIMEOUT_ERROR = "Unable to obtain current location within 10 seconds";
|
|
1504
|
+
private final Handler currentLocationHandler = new Handler(Looper.getMainLooper());
|
|
1505
|
+
private CurrentLocationOperation currentLocationOperation;
|
|
1506
|
+
private volatile boolean locationPluginDestroyed;
|
|
1507
|
+
|
|
1508
|
+
private void getCurrentLocation(final CallbackContext resultCallback) {
|
|
1509
|
+
final long deadline = SystemClock.elapsedRealtime() + CURRENT_LOCATION_TIMEOUT_MS;
|
|
1510
|
+
currentLocationHandler.post(() -> {
|
|
1511
|
+
if (locationPluginDestroyed) {
|
|
1512
|
+
resultCallback.error("Current location request cancelled: plugin destroyed");
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
if (currentLocationOperation != null) {
|
|
1516
|
+
resultCallback.error("A current location request is already in progress");
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
CurrentLocationOperation operation = new CurrentLocationOperation(resultCallback, deadline);
|
|
1520
|
+
currentLocationOperation = operation;
|
|
1521
|
+
operation.start();
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
private void cancelCurrentLocationRequest() {
|
|
1526
|
+
currentLocationHandler.post(() -> {
|
|
1527
|
+
if (currentLocationOperation != null) {
|
|
1528
|
+
currentLocationOperation.finish(null, "Current location request cancelled");
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
// All request state and completion listeners run on the main looper. This
|
|
1534
|
+
// callback is separate from the shared camera/scanner/GPS-settings callback.
|
|
1535
|
+
private final class CurrentLocationOperation {
|
|
1536
|
+
private final CallbackContext resultCallback;
|
|
1537
|
+
private final long deadline;
|
|
1538
|
+
private final CancellationTokenSource cancellation = new CancellationTokenSource();
|
|
1539
|
+
private final Runnable timeout = () -> finish(null, CURRENT_LOCATION_TIMEOUT_ERROR);
|
|
1540
|
+
private boolean completed;
|
|
1541
|
+
|
|
1542
|
+
CurrentLocationOperation(CallbackContext resultCallback, long deadline) {
|
|
1543
|
+
this.resultCallback = resultCallback;
|
|
1544
|
+
this.deadline = deadline;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
void start() {
|
|
1548
|
+
long remaining = deadline - SystemClock.elapsedRealtime();
|
|
1549
|
+
if (remaining <= 0) {
|
|
1550
|
+
finish(null, CURRENT_LOCATION_TIMEOUT_ERROR);
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
currentLocationHandler.postDelayed(timeout, remaining);
|
|
1554
|
+
try {
|
|
1555
|
+
Context context = cordova.getActivity().getApplicationContext();
|
|
1556
|
+
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|
|
1557
|
+
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
1558
|
+
finish(null, "Location permission not granted");
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
|
1562
|
+
if (manager == null || !LocationManagerCompat.isLocationEnabled(manager)) {
|
|
1563
|
+
finish(null, "Device location is disabled");
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) != ConnectionResult.SUCCESS) {
|
|
1567
|
+
finish(null, "Google Play services is unavailable");
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
remaining = deadline - SystemClock.elapsedRealtime();
|
|
1571
|
+
if (remaining <= 0) {
|
|
1572
|
+
finish(null, CURRENT_LOCATION_TIMEOUT_ERROR);
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
CurrentLocationRequest request = new CurrentLocationRequest.Builder()
|
|
1576
|
+
.setPriority(Priority.PRIORITY_HIGH_ACCURACY)
|
|
1577
|
+
.setMaxUpdateAgeMillis(0)
|
|
1578
|
+
.setDurationMillis(remaining)
|
|
1579
|
+
.build();
|
|
1580
|
+
// No network precondition: a satellite fix can be available offline.
|
|
1581
|
+
LocationServices.getFusedLocationProviderClient(context)
|
|
1582
|
+
.getCurrentLocation(request, cancellation.getToken())
|
|
1583
|
+
.addOnSuccessListener(location -> finish(location,
|
|
1584
|
+
location == null ? "Current location is unavailable" : null))
|
|
1585
|
+
.addOnFailureListener(error -> finish(null,
|
|
1586
|
+
"Unable to obtain current location: " + error.getMessage()))
|
|
1587
|
+
.addOnCanceledListener(() -> finish(null, "Current location request cancelled"));
|
|
1588
|
+
} catch (Exception error) {
|
|
1589
|
+
finish(null, "Unable to obtain current location: " + error.getMessage());
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
void finish(Location location, String error) {
|
|
1594
|
+
if (completed) return;
|
|
1595
|
+
completed = true;
|
|
1596
|
+
currentLocationHandler.removeCallbacks(timeout);
|
|
1597
|
+
if (currentLocationOperation == this) currentLocationOperation = null;
|
|
1598
|
+
// Cancels outstanding acquisition on timeout/reset and releases the
|
|
1599
|
+
// one-shot request on every terminal path. Late results are ignored.
|
|
1600
|
+
try {
|
|
1601
|
+
cancellation.cancel();
|
|
1602
|
+
} catch (RuntimeException cancellationError) {
|
|
1603
|
+
Log.w(TAG, "Unable to cancel current location acquisition", cancellationError);
|
|
1604
|
+
}
|
|
1605
|
+
if (SystemClock.elapsedRealtime() >= deadline) {
|
|
1606
|
+
location = null;
|
|
1607
|
+
error = CURRENT_LOCATION_TIMEOUT_ERROR;
|
|
1608
|
+
}
|
|
1609
|
+
if (location != null) {
|
|
1610
|
+
resultCallback.success(location.getLatitude() + "," + location.getLongitude());
|
|
1611
|
+
} else {
|
|
1612
|
+
resultCallback.error(error);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
|
|
1497
1618
|
public void createLocationRequest1() {
|
|
1498
1619
|
try {
|
|
1499
1620
|
mLocationRequest1 = new LocationRequest();
|
|
@@ -1578,6 +1699,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1578
1699
|
boolean permissionGranted = true, checkPermission = true;
|
|
1579
1700
|
List<String> list;
|
|
1580
1701
|
try {
|
|
1702
|
+
callback = callbackContext;
|
|
1581
1703
|
Context context = cordova.getActivity().getApplicationContext();
|
|
1582
1704
|
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1583
1705
|
if (permissions[0].equalsIgnoreCase("android.permission.ACCESS_BACKGROUND_LOCATION")) {
|
|
@@ -1595,12 +1717,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1595
1717
|
}
|
|
1596
1718
|
}
|
|
1597
1719
|
if (!permissionGranted) {
|
|
1598
|
-
|
|
1720
|
+
callback.error("failure");
|
|
1599
1721
|
} else {
|
|
1600
|
-
|
|
1722
|
+
callback.success("success");
|
|
1601
1723
|
}
|
|
1602
1724
|
} else {
|
|
1603
|
-
|
|
1725
|
+
callback.success("success");
|
|
1604
1726
|
}
|
|
1605
1727
|
} catch (Exception e) {
|
|
1606
1728
|
e.printStackTrace();
|
|
@@ -1615,106 +1737,69 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1615
1737
|
}
|
|
1616
1738
|
|
|
1617
1739
|
private void getLocationPermission(JSONArray args, CallbackContext callbackContext) {
|
|
1740
|
+
boolean permissionGranted = true;
|
|
1741
|
+
List<String> list;
|
|
1618
1742
|
try {
|
|
1619
|
-
|
|
1743
|
+
callback = callbackContext;
|
|
1744
|
+
Context context = cordova.getActivity().getApplicationContext();
|
|
1745
|
+
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1746
|
+
list = new ArrayList<String>(Arrays.asList(permissions));
|
|
1747
|
+
permissions = list.toArray(new String[0]);
|
|
1748
|
+
|
|
1749
|
+
for (int i = 0; i < permissions.length; i++) {
|
|
1750
|
+
if (ActivityCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
|
|
1751
|
+
permissionGranted = false;
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
if (!permissionGranted) {
|
|
1755
|
+
PermissionHelper.requestPermissions(this, 111, permissions);
|
|
1756
|
+
} else {
|
|
1757
|
+
callback.success("success");
|
|
1758
|
+
}
|
|
1620
1759
|
} catch (Exception e) {
|
|
1621
|
-
|
|
1760
|
+
e.printStackTrace();
|
|
1622
1761
|
}
|
|
1623
1762
|
}
|
|
1624
1763
|
|
|
1625
1764
|
private void getPermissions(JSONArray args, CallbackContext callbackContext) {
|
|
1765
|
+
boolean permissionGranted = true;
|
|
1766
|
+
List<String> list;
|
|
1626
1767
|
try {
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
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;
|
|
1768
|
+
callback = callbackContext;
|
|
1769
|
+
Context context = cordova.getActivity().getApplicationContext();
|
|
1770
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
1771
|
+
String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
|
|
1772
|
+
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) {
|
|
1773
|
+
list = new ArrayList<String>(Arrays.asList(permissions));
|
|
1774
|
+
list.remove("android.permission.ACCESS_BACKGROUND_LOCATION");
|
|
1775
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
1776
|
+
list.remove("android.permission.POST_NOTIFICATIONS");
|
|
1777
|
+
} else {
|
|
1778
|
+
list.remove("android.permission.WRITE_EXTERNAL_STORAGE");
|
|
1779
|
+
list.remove("android.permission.READ_EXTERNAL_STORAGE");
|
|
1780
|
+
}
|
|
1781
|
+
permissions = list.toArray(new String[0]);
|
|
1782
|
+
}
|
|
1783
|
+
for (int i = 0; i < permissions.length; i++) {
|
|
1784
|
+
if (ActivityCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
|
|
1785
|
+
permissionGranted = false;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
if (!permissionGranted) {
|
|
1789
|
+
PermissionHelper.requestPermissions(this, 1, permissions);
|
|
1790
|
+
} else {
|
|
1791
|
+
callback.success("success");
|
|
1792
|
+
}
|
|
1793
|
+
} else {
|
|
1794
|
+
callback.success("success");
|
|
1683
1795
|
}
|
|
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);
|
|
1708
1796
|
} catch (Exception e) {
|
|
1709
|
-
|
|
1710
|
-
pendingPermissionRequest = -1;
|
|
1711
|
-
callbackContext.error("Unable to request permission: " + e.getMessage());
|
|
1797
|
+
callback.error("getPermissions failed, exception is : " + e.getMessage());
|
|
1712
1798
|
}
|
|
1713
1799
|
}
|
|
1714
1800
|
|
|
1715
1801
|
public void captureImageLiveCamera(CallbackContext callbackContext) {
|
|
1716
1802
|
callback = callbackContext;
|
|
1717
|
-
pictureFilePath = null;
|
|
1718
1803
|
Context context = cordova.getActivity().getApplicationContext();
|
|
1719
1804
|
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
|
1720
1805
|
File photoFile = null;
|
|
@@ -1722,7 +1807,6 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1722
1807
|
photoFile = createImageFile();
|
|
1723
1808
|
} catch (IOException ex) {
|
|
1724
1809
|
callback.error("there is error in create image");
|
|
1725
|
-
return;
|
|
1726
1810
|
}
|
|
1727
1811
|
//Continue only if the File was successfully created
|
|
1728
1812
|
if (photoFile != null) {
|
|
@@ -1737,14 +1821,11 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1737
1821
|
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
1738
1822
|
pluginResult.setKeepCallback(true);
|
|
1739
1823
|
callbackContext.sendPluginResult(pluginResult);
|
|
1740
|
-
} else {
|
|
1741
|
-
callbackContext.error("Unable to create the camera output file");
|
|
1742
1824
|
}
|
|
1743
1825
|
}
|
|
1744
1826
|
|
|
1745
1827
|
public void captureImage(CallbackContext callbackContext) {
|
|
1746
1828
|
callback = callbackContext;
|
|
1747
|
-
pictureFilePath = null;
|
|
1748
1829
|
Intent intent = new Intent(cordova.getActivity(), CameraActivity.class);
|
|
1749
1830
|
cordova.startActivityForResult(this, intent, REQUEST_IMAGE_CAPTURE);
|
|
1750
1831
|
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
@@ -1754,32 +1835,26 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1754
1835
|
|
|
1755
1836
|
void pickImageFromGallery(CallbackContext callbackContext) {
|
|
1756
1837
|
try {
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
intent.setType("image/*");
|
|
1838
|
+
Intent i;
|
|
1839
|
+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
|
|
1840
|
+
i = new Intent(MediaStore.ACTION_PICK_IMAGES);
|
|
1841
|
+
i.setType("image/*");
|
|
1762
1842
|
} else {
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
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);
|
|
1843
|
+
i = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
1844
|
+
i.addCategory(Intent.CATEGORY_OPENABLE);
|
|
1845
|
+
i.setType("image/*");
|
|
1846
|
+
i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
1777
1847
|
}
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1848
|
+
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
1849
|
+
this.callback = callbackContext;
|
|
1850
|
+
PluginResult pr = new PluginResult(PluginResult.Status.NO_RESULT);
|
|
1851
|
+
pr.setKeepCallback(true);
|
|
1852
|
+
callbackContext.sendPluginResult(pr);
|
|
1853
|
+
cordova.startActivityForResult(this, i, PICK_IMAGE_FROM_GALLERY);
|
|
1854
|
+
|
|
1855
|
+
|
|
1781
1856
|
} catch (Exception e) {
|
|
1782
|
-
callbackContext.error("pickImageFromGallery failed: " + e.getMessage());
|
|
1857
|
+
callbackContext.error("pickImageFromGallery failed, exception is : " + e.getMessage());
|
|
1783
1858
|
}
|
|
1784
1859
|
}
|
|
1785
1860
|
|
|
@@ -1970,10 +2045,10 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1970
2045
|
fileProperities.put("fileExtension", fileExtension);
|
|
1971
2046
|
fileProperities.put("thumbnail", thumbnail);
|
|
1972
2047
|
attachmentDestPath = "";
|
|
1973
|
-
|
|
2048
|
+
callback.success(fileProperities);
|
|
1974
2049
|
} catch (Exception e) {
|
|
1975
2050
|
attachmentDestPath = "";
|
|
1976
|
-
|
|
2051
|
+
callback.error("convertImageTo64BaseString failed, exception is : " + e.getMessage());
|
|
1977
2052
|
}
|
|
1978
2053
|
}
|
|
1979
2054
|
} catch (Exception e) {
|
|
@@ -1982,7 +2057,7 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
1982
2057
|
}
|
|
1983
2058
|
|
|
1984
2059
|
} catch (Exception e) {
|
|
1985
|
-
|
|
2060
|
+
e.printStackTrace();
|
|
1986
2061
|
}
|
|
1987
2062
|
|
|
1988
2063
|
}
|
|
@@ -2017,11 +2092,23 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2017
2092
|
}
|
|
2018
2093
|
|
|
2019
2094
|
public Intent getPickImageChooserIntent() {
|
|
2020
|
-
Intent
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2095
|
+
Intent openFile, selectFile;
|
|
2096
|
+
try {
|
|
2097
|
+
if (Build.MANUFACTURER.equals("samsung")) {
|
|
2098
|
+
openFile = new Intent("com.sec.android.app.myfiles.PICK_DATA");
|
|
2099
|
+
openFile.putExtra("CONTENT_TYPE", "*/*");
|
|
2100
|
+
} else {
|
|
2101
|
+
openFile = new Intent(Intent.ACTION_GET_CONTENT);
|
|
2102
|
+
openFile.setType("*/*");
|
|
2103
|
+
openFile.addCategory(Intent.CATEGORY_OPENABLE);
|
|
2104
|
+
openFile.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
2105
|
+
}
|
|
2106
|
+
selectFile = Intent.createChooser(openFile, "Select File");
|
|
2107
|
+
return selectFile;
|
|
2108
|
+
} catch (Exception e) {
|
|
2109
|
+
e.printStackTrace();
|
|
2110
|
+
}
|
|
2111
|
+
return null;
|
|
2025
2112
|
}
|
|
2026
2113
|
|
|
2027
2114
|
//App version plugin
|
|
@@ -2039,31 +2126,35 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2039
2126
|
|
|
2040
2127
|
//Rotate Screen plugin
|
|
2041
2128
|
public void rotateScreen(JSONArray args, CallbackContext callbackContext) {
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
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());
|
|
2129
|
+
try {
|
|
2130
|
+
String orientation = args.optString(0);
|
|
2131
|
+
String currentOrientation;
|
|
2132
|
+
Activity activity = cordova.getActivity();
|
|
2133
|
+
int orientation1 = activity.getResources().getConfiguration().orientation;
|
|
2134
|
+
if (orientation1 == Configuration.ORIENTATION_LANDSCAPE) {
|
|
2135
|
+
currentOrientation = "landscape";
|
|
2136
|
+
} else {
|
|
2137
|
+
currentOrientation = "portrait";
|
|
2065
2138
|
}
|
|
2066
|
-
|
|
2139
|
+
if (orientation.equals(ANY)) {
|
|
2140
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
|
2141
|
+
} else if (orientation.equals(LANDSCAPE_PRIMARY)) {
|
|
2142
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
|
2143
|
+
} else if (orientation.equals(PORTRAIT_PRIMARY)) {
|
|
2144
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
|
2145
|
+
} else if (orientation.equals(LANDSCAPE)) {
|
|
2146
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
|
2147
|
+
} else if (orientation.equals(PORTRAIT)) {
|
|
2148
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
|
2149
|
+
} else if (orientation.equals(LANDSCAPE_SECONDARY)) {
|
|
2150
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
|
|
2151
|
+
} else if (orientation.equals(PORTRAIT_SECONDARY)) {
|
|
2152
|
+
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
|
|
2153
|
+
}
|
|
2154
|
+
callbackContext.success(currentOrientation);
|
|
2155
|
+
} catch (Exception e) {
|
|
2156
|
+
callbackContext.success("rotateScreen failed, exception is : " + e.getMessage());
|
|
2157
|
+
}
|
|
2067
2158
|
}
|
|
2068
2159
|
|
|
2069
2160
|
public void deviceInfo(CallbackContext callbackContext) {
|
|
@@ -2161,20 +2252,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2161
2252
|
final String imageSourcePath,
|
|
2162
2253
|
final String imgSrcType,
|
|
2163
2254
|
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) {
|
|
2172
2255
|
cordova.getThreadPool().execute(new Runnable() {
|
|
2173
2256
|
@Override public void run() {
|
|
2174
|
-
|
|
2257
|
+
InputStream srcFileReader = null;
|
|
2258
|
+
OutputStream desFileWriter = null;
|
|
2175
2259
|
ByteArrayOutputStream baos = null;
|
|
2176
2260
|
Bitmap bitmap = null;
|
|
2177
|
-
File compressedTemp = null;
|
|
2178
2261
|
try {
|
|
2179
2262
|
// Common bits
|
|
2180
2263
|
final String[] parts = imageSourcePath.split("/");
|
|
@@ -2193,20 +2276,33 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2193
2276
|
.setCompressFormat(Bitmap.CompressFormat.JPEG)
|
|
2194
2277
|
.compressToFile(fileToCompress);
|
|
2195
2278
|
|
|
2196
|
-
compressedTemp = compressedImageFile;
|
|
2197
2279
|
String timeStamp = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
|
|
2198
2280
|
final String baseDir = (destinationPath != null && !destinationPath.isEmpty())
|
|
2199
2281
|
? (mInterfaceUtil.rootDirectory + "/" + destinationPath)
|
|
2200
2282
|
: (mInterfaceUtil.rootDirectory + "/" + mInterfaceUtil.packageName + "/images");
|
|
2201
2283
|
final String outName = baseName + "_" + timeStamp + ".jpg";
|
|
2284
|
+
final String outFullPath = baseDir + "/" + outName;
|
|
2285
|
+
|
|
2202
2286
|
File outDir = new File(baseDir);
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2287
|
+
if (!outDir.exists()) outDir.mkdirs();
|
|
2288
|
+
|
|
2289
|
+
// Copy compressed temp → final path
|
|
2290
|
+
if (compressedImageFile.exists()) {
|
|
2291
|
+
srcFileReader = new FileInputStream(compressedImageFile);
|
|
2292
|
+
desFileWriter = new FileOutputStream(new File(outFullPath));
|
|
2293
|
+
byte[] buf = new byte[64 * 1024];
|
|
2294
|
+
int n;
|
|
2295
|
+
while ((n = srcFileReader.read(buf)) > 0) {
|
|
2296
|
+
desFileWriter.write(buf, 0, n);
|
|
2297
|
+
}
|
|
2298
|
+
desFileWriter.flush();
|
|
2206
2299
|
}
|
|
2207
|
-
File outFile = AttachmentFileIO.copy(
|
|
2208
|
-
new FileInputStream(compressedImageFile), outDir, outName);
|
|
2209
2300
|
|
|
2301
|
+
// (Optional) load to normalize EXIF rotation like the sync version did
|
|
2302
|
+
try { bitmap = handleImageRotation(outFullPath); } catch (Throwable ignore) {}
|
|
2303
|
+
|
|
2304
|
+
// Build properties
|
|
2305
|
+
File outFile = new File(outFullPath);
|
|
2210
2306
|
org.json.JSONObject fileProps = new org.json.JSONObject();
|
|
2211
2307
|
fileProps.put("filePath", outFile.getParent());
|
|
2212
2308
|
fileProps.put("fileName", outFile.getName());
|
|
@@ -2215,37 +2311,25 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2215
2311
|
fileProps.put("thumbnail", thumbnail);
|
|
2216
2312
|
|
|
2217
2313
|
// Match original behavior: clear attachmentDestPath if you rely on that global
|
|
2218
|
-
|
|
2314
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2219
2315
|
|
|
2220
2316
|
postSuccess(cb, fileProps);
|
|
2221
2317
|
return;
|
|
2222
2318
|
}
|
|
2223
2319
|
|
|
2224
|
-
// === CAMERA / GALLERY
|
|
2320
|
+
// === CAMERA / GALLERY → return BASE64 string ===
|
|
2225
2321
|
// Decode with downsampling and fix rotation
|
|
2226
2322
|
BitmapFactory.Options o = new BitmapFactory.Options();
|
|
2227
2323
|
o.inJustDecodeBounds = true; BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2228
2324
|
o.inSampleSize = calcInSampleSize(o, 1920, 1920);
|
|
2229
2325
|
o.inJustDecodeBounds = false;
|
|
2230
2326
|
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
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) { }
|
|
2327
|
+
// Prefer your rotation-aware helper (handles EXIF)
|
|
2328
|
+
try {
|
|
2329
|
+
bitmap = handleImageRotation(imageSourcePath);
|
|
2330
|
+
if (bitmap == null) bitmap = BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2331
|
+
} catch (Throwable t) {
|
|
2332
|
+
bitmap = BitmapFactory.decodeFile(imageSourcePath, o);
|
|
2249
2333
|
}
|
|
2250
2334
|
if (bitmap == null) {
|
|
2251
2335
|
postError(cb, "decode_failed");
|
|
@@ -2262,18 +2346,18 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2262
2346
|
File f = new File(imageSourcePath);
|
|
2263
2347
|
if (f.exists()) f.delete();
|
|
2264
2348
|
} catch (Throwable ignore) {}
|
|
2265
|
-
|
|
2349
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2266
2350
|
} else if ("gallery".equalsIgnoreCase(imgSrcType)) {
|
|
2267
|
-
|
|
2351
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2268
2352
|
}
|
|
2269
2353
|
|
|
2270
2354
|
postSuccess(cb, encodedImage);
|
|
2271
2355
|
} catch (Exception e) {
|
|
2272
|
-
|
|
2356
|
+
try { attachmentDestPath = ""; } catch (Throwable ignore) {}
|
|
2273
2357
|
postError(cb, "convertImageTo64BaseStringAsync failed: " + e.getMessage());
|
|
2274
2358
|
} finally {
|
|
2275
|
-
if (
|
|
2276
|
-
if (
|
|
2359
|
+
try { if (srcFileReader != null) srcFileReader.close(); } catch (Exception ignore) {}
|
|
2360
|
+
try { if (desFileWriter != null) desFileWriter.close(); } catch (Exception ignore) {}
|
|
2277
2361
|
try { if (baos != null) baos.close(); } catch (Exception ignore) {}
|
|
2278
2362
|
try { if (bitmap != null) bitmap.recycle(); } catch (Exception ignore) {}
|
|
2279
2363
|
}
|
|
@@ -2283,10 +2367,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2283
2367
|
|
|
2284
2368
|
|
|
2285
2369
|
private String copyFileFromUriFast(Context ctx, Uri uri, String destName, String destDir) {
|
|
2370
|
+
java.io.File dir = (destDir != null && !destDir.isEmpty())
|
|
2371
|
+
? new java.io.File(ctx.getFilesDir(), destDir) : ctx.getFilesDir();
|
|
2286
2372
|
try {
|
|
2287
|
-
return
|
|
2288
|
-
} catch (
|
|
2289
|
-
android.util.Log.
|
|
2373
|
+
return AttachmentFileIO.copy(ctx.getContentResolver().openInputStream(uri), dir, destName).getAbsolutePath();
|
|
2374
|
+
} catch (Exception e) {
|
|
2375
|
+
android.util.Log.w("mInterface", "Unable to import selected attachment");
|
|
2290
2376
|
return null;
|
|
2291
2377
|
}
|
|
2292
2378
|
}
|
|
@@ -2298,17 +2384,15 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2298
2384
|
case LOCATION_ACCURACY_REQUEST_NEW:
|
|
2299
2385
|
switch (resultCode) {
|
|
2300
2386
|
case Activity.RESULT_OK:
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
callback.error("Unable to resume location service");
|
|
2305
|
-
}
|
|
2387
|
+
mInterfaceService mInterfaceService = new mInterfaceService();
|
|
2388
|
+
mInterfaceService.startLocationUpdates(cordova.getContext());
|
|
2389
|
+
callback.success();
|
|
2306
2390
|
break;
|
|
2307
2391
|
case Activity.RESULT_CANCELED:
|
|
2308
2392
|
callback.error("oops! you have cancelled...");
|
|
2309
2393
|
break;
|
|
2310
2394
|
}
|
|
2311
|
-
|
|
2395
|
+
break;
|
|
2312
2396
|
}
|
|
2313
2397
|
if (SCANCODEINT == 118 && callback != null) {
|
|
2314
2398
|
if (resultCode == RESULT_OK) {
|
|
@@ -2334,12 +2418,177 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2334
2418
|
SCANCODEINT = 0;
|
|
2335
2419
|
callback.error(resultCode);
|
|
2336
2420
|
}
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
|
-
|
|
2421
|
+
}else if (requestCode == PICK_IMAGE_FROM_GALLERY) {
|
|
2422
|
+
final CallbackContext cb = this.callback;
|
|
2423
|
+
this.callback = null;
|
|
2424
|
+
if (cb == null) return;
|
|
2425
|
+
|
|
2426
|
+
try {
|
|
2427
|
+
if (resultCode != RESULT_OK || data == null) {
|
|
2428
|
+
cb.error("canceled");
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
// Photo Picker may return via getData() or ClipData
|
|
2433
|
+
Uri uri = data.getData();
|
|
2434
|
+
if (uri == null && data.getClipData() != null && data.getClipData().getItemCount() > 0) {
|
|
2435
|
+
uri = data.getClipData().getItemAt(0).getUri();
|
|
2436
|
+
}
|
|
2437
|
+
if (uri == null) {
|
|
2438
|
+
cb.error("no_file_selected");
|
|
2439
|
+
return;
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
final Uri selectedUri = uri;
|
|
2443
|
+
final String destPath = attachmentDestPath; // capture current dest
|
|
2444
|
+
final String galleryInd = String.valueOf(galleryAttachmentInd);
|
|
2445
|
+
|
|
2446
|
+
// Offload ALL heavy work (resolver, copy, bitmap/encode) to Cordova thread pool
|
|
2447
|
+
cordova.getThreadPool().execute(new Runnable() {
|
|
2448
|
+
@Override public void run() {
|
|
2449
|
+
try {
|
|
2450
|
+
ContentResolver cr = cordova.getActivity().getContentResolver();
|
|
2451
|
+
|
|
2452
|
+
String mime = null;
|
|
2453
|
+
try { mime = cr.getType(selectedUri); } catch (Throwable ignore) {}
|
|
2454
|
+
|
|
2455
|
+
String defExt = (mime != null && mime.contains("/"))
|
|
2456
|
+
? mime.substring(mime.indexOf('/') + 1).toLowerCase()
|
|
2457
|
+
: "jpg";
|
|
2458
|
+
|
|
2459
|
+
// Get a display name if provider allows; otherwise build a sane fallback
|
|
2460
|
+
String fileName = safeGetDisplayName(cr, selectedUri, defExt);
|
|
2461
|
+
String ext = fileName.contains(".")
|
|
2462
|
+
? fileName.substring(fileName.lastIndexOf('.')).toLowerCase()
|
|
2463
|
+
: ("." + defExt);
|
|
2464
|
+
|
|
2465
|
+
// Copy the user-selected URI into app-private storage (no READ_MEDIA_* needed)
|
|
2466
|
+
String localPath = copyFileFromUriFast(
|
|
2467
|
+
cordova.getActivity().getApplicationContext(),
|
|
2468
|
+
selectedUri, fileName, destPath);
|
|
2469
|
+
|
|
2470
|
+
if (localPath == null) {
|
|
2471
|
+
cb.error("copy_failed");
|
|
2472
|
+
return;
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
// Accept only image-like picks (by MIME or extension)
|
|
2476
|
+
boolean imageLike =
|
|
2477
|
+
(mime != null && mime.startsWith("image/")) ||
|
|
2478
|
+
ext.equals(".jpg") || ext.equals(".jpeg") ||
|
|
2479
|
+
ext.equals(".png") || ext.equals(".heic");
|
|
2480
|
+
|
|
2481
|
+
if (!imageLike) {
|
|
2482
|
+
cb.error("Only JPEG/PNG/HEIC images are allowed.");
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
// Run your existing conversion on a worker too (non-blocking)
|
|
2487
|
+
if ("true".equals(galleryInd)) {
|
|
2488
|
+
convertImageTo64BaseStringAsync(cb, localPath, "compress", destPath);
|
|
2489
|
+
} else {
|
|
2490
|
+
convertImageTo64BaseStringAsync(cb, localPath, "gallery", "");
|
|
2491
|
+
}
|
|
2492
|
+
} catch (Exception e) {
|
|
2493
|
+
cb.error("PICK_IMAGE_FROM_GALLERY: " + e.getMessage());
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
});
|
|
2497
|
+
return; // IMPORTANT: stop here so no other branch falls through
|
|
2498
|
+
} catch (Exception e) {
|
|
2499
|
+
cb.error("PICK_IMAGE_FROM_GALLERY dispatch failed: " + e.getMessage());
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
else if (requestCode == NEW_FILE_PICK_REQUEST && callback != null) {
|
|
2504
|
+
try {
|
|
2505
|
+
Uri uri = data.getData();
|
|
2506
|
+
String fileName, extension, filePath;
|
|
2507
|
+
JSONObject fileProperities;
|
|
2508
|
+
Cursor cursor = null;
|
|
2509
|
+
if (uri.getScheme().equals("file")) {
|
|
2510
|
+
fileName = uri.getLastPathSegment();
|
|
2511
|
+
if (fileName.indexOf(".") > 0) {
|
|
2512
|
+
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
|
2513
|
+
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
2514
|
+
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2515
|
+
fileName = fileName + "_" + timeStamp + extension;
|
|
2516
|
+
}
|
|
2517
|
+
} else {
|
|
2518
|
+
try {
|
|
2519
|
+
cursor = cordova.getActivity().getApplicationContext().getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DISPLAY_NAME}, null, null, null);
|
|
2520
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
2521
|
+
int displayNameIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME);
|
|
2522
|
+
if (displayNameIndex != -1) {
|
|
2523
|
+
fileName = cursor.getString(displayNameIndex);
|
|
2524
|
+
} else {
|
|
2525
|
+
fileName = "";
|
|
2526
|
+
}
|
|
2527
|
+
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2528
|
+
if (!extension.equals(".jpeg") && !extension.equals(".jpg") && !extension.equals(".png")) {
|
|
2529
|
+
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
|
2530
|
+
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
|
2531
|
+
fileName = fileName + "_" + timeStamp + extension;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
} else {
|
|
2535
|
+
fileName = uri.getLastPathSegment();
|
|
2536
|
+
}
|
|
2537
|
+
} finally {
|
|
2538
|
+
if (cursor != null) {
|
|
2539
|
+
cursor.close();
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
extension = "." + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
|
2545
|
+
|
|
2546
|
+
filePath = copyFileFromUri(cordova.getActivity().getApplicationContext(), uri, fileName, attachmentDestPath, callback);
|
|
2547
|
+
if (filePath == null) return;
|
|
2548
|
+
File file = new File(filePath);
|
|
2549
|
+
String mimeType = getMimeType(filePath, uri);
|
|
2550
|
+
System.out.println("Mime type is: " + mimeType);
|
|
2551
|
+
double fileSize = file.length();
|
|
2552
|
+
if (filePath != null) {
|
|
2553
|
+
try {
|
|
2554
|
+
if (requestCode == NEW_FILE_PICK_REQUEST) {
|
|
2555
|
+
if (extension.equals(".heic")) {
|
|
2556
|
+
convertImageTo64BaseString(callback, filePath, "compress", attachmentDestPath);
|
|
2557
|
+
} else if (mimeType != null) {
|
|
2558
|
+
if (mimeType.contains("image")) {
|
|
2559
|
+
convertImageTo64BaseString(callback, filePath, "compress", attachmentDestPath);
|
|
2560
|
+
} else {
|
|
2561
|
+
fileProperities = new JSONObject();
|
|
2562
|
+
fileProperities.put("filePath", filePath.substring(0, filePath.lastIndexOf(File.separator)));
|
|
2563
|
+
fileProperities.put("fileName", fileName);
|
|
2564
|
+
fileProperities.put("fileSize", fileSize);
|
|
2565
|
+
fileProperities.put("fileExtension", extension);
|
|
2566
|
+
fileProperities.put("thumbnail", getFileThumbnail(filePath, extension));
|
|
2567
|
+
attachmentDestPath = "";
|
|
2568
|
+
callback.success(fileProperities);
|
|
2569
|
+
}
|
|
2570
|
+
} else {
|
|
2571
|
+
fileProperities = new JSONObject();
|
|
2572
|
+
fileProperities.put("filePath", filePath.substring(0, filePath.lastIndexOf(File.separator)));
|
|
2573
|
+
fileProperities.put("fileName", fileName);
|
|
2574
|
+
fileProperities.put("fileSize", fileSize);
|
|
2575
|
+
fileProperities.put("fileExtension", extension);
|
|
2576
|
+
fileProperities.put("thumbnail", getFileThumbnail(filePath, extension));
|
|
2577
|
+
callback.success(fileProperities);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
} catch (Exception e) {
|
|
2581
|
+
callback.error("onActivityResult failed, exception is : " + e.getMessage());
|
|
2582
|
+
}
|
|
2583
|
+
} else {
|
|
2584
|
+
callback.error("onActivityResult: Selected file path is null");
|
|
2585
|
+
}
|
|
2586
|
+
} catch (Exception e) {
|
|
2587
|
+
callback.error("onActivityResult failed, exception is : " + e.getMessage());
|
|
2588
|
+
}
|
|
2340
2589
|
} else if (requestCode == REQUEST_IMAGE_CAPTURE && callback != null) {
|
|
2341
2590
|
if (resultCode == RESULT_OK) {
|
|
2342
|
-
String imagePath = data
|
|
2591
|
+
String imagePath = data.getStringExtra("imagePath");
|
|
2343
2592
|
if (imagePath != null && !imagePath.isEmpty()) {
|
|
2344
2593
|
pictureFilePath = imagePath;
|
|
2345
2594
|
if (cameraAttachmentInd.equals("true")) {
|
|
@@ -2351,10 +2600,12 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2351
2600
|
callback.error("failure");
|
|
2352
2601
|
}
|
|
2353
2602
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2603
|
+
if (pictureFilePath != null && !pictureFilePath.isEmpty()) {
|
|
2604
|
+
File file = new File(pictureFilePath);
|
|
2605
|
+
if (file.exists()) {
|
|
2606
|
+
file.delete();
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2358
2609
|
callback.error("failure");
|
|
2359
2610
|
} else {
|
|
2360
2611
|
callback.error(resultCode);
|
|
@@ -2363,10 +2614,158 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2363
2614
|
if (resultCode == RESULT_OK) {
|
|
2364
2615
|
convertImageTo64BaseString(callback, pictureFilePath, "compress", attachmentDestPath);
|
|
2365
2616
|
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2617
|
+
File file = new File(pictureFilePath);
|
|
2618
|
+
if (file.exists()) {
|
|
2619
|
+
file.delete();
|
|
2620
|
+
}
|
|
2621
|
+
callback.error("failure");
|
|
2622
|
+
} else {
|
|
2623
|
+
callback.error(resultCode);
|
|
2624
|
+
}
|
|
2625
|
+
} else if (requestCode == PICK_FILE_REQUEST && callback != null) {
|
|
2626
|
+
if (resultCode == RESULT_OK) {
|
|
2627
|
+
String fileName = null,
|
|
2628
|
+
getfilePath = null,
|
|
2629
|
+
filePath,
|
|
2630
|
+
fileExtension,
|
|
2631
|
+
fileType,
|
|
2632
|
+
fileSize = null,
|
|
2633
|
+
storageDefinition;
|
|
2634
|
+
final String docId,
|
|
2635
|
+
type,
|
|
2636
|
+
id;
|
|
2637
|
+
final String[] split;
|
|
2638
|
+
final String tag,
|
|
2639
|
+
path;
|
|
2640
|
+
final int splitIndex;
|
|
2641
|
+
Cursor cursor;
|
|
2642
|
+
long getSize;
|
|
2643
|
+
JSONObject fileProperities;
|
|
2644
|
+
Uri uri = data.getData(); //get uri for selected file
|
|
2645
|
+
fileType = this.cordova.getActivity().getContentResolver().getType(uri); // get mimeType for selected file
|
|
2646
|
+
File getFileName,
|
|
2647
|
+
file;
|
|
2648
|
+
try {
|
|
2649
|
+
//API LEVEL 19 AND ABOVE (TO GET FILEPATH)
|
|
2650
|
+
if (Build.VERSION.SDK_INT >= 19 && !Build.MANUFACTURER.equals("samsung") && DocumentsContract.isDocumentUri(cordova.getActivity(), uri)) {
|
|
2651
|
+
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { // ExternalStorageProvider
|
|
2652
|
+
docId = DocumentsContract.getDocumentId(uri);
|
|
2653
|
+
split = docId.split(":");
|
|
2654
|
+
type = split[0];
|
|
2655
|
+
if ("primary".equalsIgnoreCase(type)) {
|
|
2656
|
+
getfilePath = mInterfaceUtil.rootDirectory + "/" + split[1];
|
|
2657
|
+
} else {
|
|
2658
|
+
if (Environment.isExternalStorageRemovable()) {
|
|
2659
|
+
storageDefinition = System.getenv("EXTERNAL_STORAGE");
|
|
2660
|
+
getfilePath = storageDefinition;
|
|
2661
|
+
} else {
|
|
2662
|
+
splitIndex = docId.indexOf(':', 1);
|
|
2663
|
+
tag = docId.substring(0, splitIndex);
|
|
2664
|
+
path = docId.substring(splitIndex + 1);
|
|
2665
|
+
if (new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) != null) {
|
|
2666
|
+
storageDefinition = new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) + "/" + path;
|
|
2667
|
+
file = new File(storageDefinition);
|
|
2668
|
+
if (file.exists() && file.canRead()) {
|
|
2669
|
+
getfilePath = storageDefinition;
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { // DownloadsProvider
|
|
2675
|
+
id = DocumentsContract.getDocumentId(uri);
|
|
2676
|
+
final Uri contentUri = ContentUris.withAppendedId(
|
|
2677
|
+
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
|
|
2678
|
+
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, null, null);
|
|
2679
|
+
|
|
2680
|
+
} else if ("com.android.providers.media.documents".equals(uri.getAuthority())) { // MediaProvider
|
|
2681
|
+
docId = DocumentsContract.getDocumentId(uri);
|
|
2682
|
+
split = docId.split(":");
|
|
2683
|
+
type = split[0];
|
|
2684
|
+
Uri contentUri = null;
|
|
2685
|
+
if ("image".equals(type)) {
|
|
2686
|
+
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
|
2687
|
+
} else if ("video".equals(type)) {
|
|
2688
|
+
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
|
|
2689
|
+
} else if ("audio".equals(type)) {
|
|
2690
|
+
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
|
2691
|
+
}
|
|
2692
|
+
final String selection = "_id=?";
|
|
2693
|
+
final String[] selectionArgs = new String[]{
|
|
2694
|
+
split[1]
|
|
2695
|
+
};
|
|
2696
|
+
getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, selection, selectionArgs);
|
|
2697
|
+
}
|
|
2698
|
+
// *** API Level 19 and Above (To Get FileName,FileExtension and FileSize)**** //
|
|
2699
|
+
cursor = cordova.getActivity().getContentResolver().query(uri, null, null, null, null, null);
|
|
2700
|
+
try {
|
|
2701
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
2702
|
+
int displayNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
2703
|
+
if (displayNameIndex != -1) {
|
|
2704
|
+
fileName = cursor.getString(displayNameIndex);
|
|
2705
|
+
} else {
|
|
2706
|
+
fileName = "";
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
int fileSizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
|
|
2710
|
+
if (!cursor.isNull(fileSizeIndex) && fileSizeIndex != -1) {
|
|
2711
|
+
fileSize = cursor.getString(fileSizeIndex);
|
|
2712
|
+
} else {
|
|
2713
|
+
fileSize = "0";
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
} finally {
|
|
2717
|
+
cursor.close();
|
|
2718
|
+
}
|
|
2719
|
+
// *** API Level 19 below and SAMSUNG (To Get FileProperties of MediaFiles)**** //
|
|
2720
|
+
} else {
|
|
2721
|
+
if (fileType != null) {
|
|
2722
|
+
String[] projection = {
|
|
2723
|
+
MediaStore.Images.Media.DATA,
|
|
2724
|
+
MediaStore.Images.Media.SIZE,
|
|
2725
|
+
MediaStore.Images.Media.DISPLAY_NAME
|
|
2726
|
+
};
|
|
2727
|
+
cursor = cordova.getActivity().getContentResolver().query(uri, projection, null, null, null);
|
|
2728
|
+
if (cursor.moveToFirst()) {
|
|
2729
|
+
getfilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
|
|
2730
|
+
fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
|
|
2731
|
+
fileSize = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE));
|
|
2732
|
+
}
|
|
2733
|
+
cursor.close();
|
|
2734
|
+
// API LEVEL 19 BELOW AND SAMSUNG (TO GET FILEPROPERTIES OF NORMAL FILES(EX:txt,.pdf,etc..,))
|
|
2735
|
+
} else {
|
|
2736
|
+
getfilePath = data.getData().getPath();
|
|
2737
|
+
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2738
|
+
getFileName = new File(getfilePath);
|
|
2739
|
+
fileName = getFileName.getName();
|
|
2740
|
+
getSize = getFileName.length();
|
|
2741
|
+
fileSize = String.valueOf(getSize);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
|
|
2745
|
+
fileExtension = "." + getfilePath.substring(getfilePath.lastIndexOf(".") + 1).toLowerCase();
|
|
2746
|
+
// SEND BELOW JSON OBJECT TO PLUGIN CALLBACK
|
|
2747
|
+
if (filePath != null) {
|
|
2748
|
+
try {
|
|
2749
|
+
if (fileExtension.equals(".jpeg") || fileExtension.equals(".jpg") || fileExtension.equals(".png")) {
|
|
2750
|
+
convertImageTo64BaseString(callback, filePath + "/" + fileName, "compress", attachmentDestPath);
|
|
2751
|
+
} else {
|
|
2752
|
+
fileProperities = new JSONObject();
|
|
2753
|
+
fileProperities.put("filePath", filePath);
|
|
2754
|
+
fileProperities.put("fileName", fileName);
|
|
2755
|
+
fileProperities.put("fileSize", fileSize);
|
|
2756
|
+
fileProperities.put("fileExtension", fileExtension);
|
|
2757
|
+
callback.success(fileProperities);
|
|
2758
|
+
}
|
|
2759
|
+
} catch (Exception e) {
|
|
2760
|
+
callback.error("Failed to process PICK_FILE_REQUEST");
|
|
2761
|
+
}
|
|
2762
|
+
} else {
|
|
2763
|
+
callback.error("File path was null");
|
|
2764
|
+
}
|
|
2765
|
+
} catch (Exception e) {
|
|
2766
|
+
e.printStackTrace();
|
|
2369
2767
|
}
|
|
2768
|
+
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
2370
2769
|
callback.error("failure");
|
|
2371
2770
|
} else {
|
|
2372
2771
|
callback.error(resultCode);
|
|
@@ -2381,128 +2780,36 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2381
2780
|
|
|
2382
2781
|
@Override
|
|
2383
2782
|
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
resultCallback.error(Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission)
|
|
2395
|
-
? "background_location" : "failure");
|
|
2396
|
-
return;
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2399
|
-
resultCallback.success("success");
|
|
2400
|
-
}
|
|
2401
|
-
|
|
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);
|
|
2783
|
+
try {
|
|
2784
|
+
boolean indicator = true;
|
|
2785
|
+
String failedPermission = "failure";
|
|
2786
|
+
for (int i = 0; i < grantResults.length; i++) {
|
|
2787
|
+
if (grantResults[i] != 0) {
|
|
2788
|
+
if (permissions[i].equalsIgnoreCase("android.permission.ACCESS_BACKGROUND_LOCATION")) {
|
|
2789
|
+
failedPermission = "background_location";
|
|
2790
|
+
}
|
|
2791
|
+
indicator = false;
|
|
2792
|
+
break;
|
|
2459
2793
|
}
|
|
2460
|
-
} catch (Exception e) {
|
|
2461
|
-
resultCallback.error("Unable to read the selected file: " + e.getMessage());
|
|
2462
2794
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
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);
|
|
2795
|
+
if (indicator) {
|
|
2796
|
+
callback.success("success");
|
|
2797
|
+
} else {
|
|
2798
|
+
callback.error(failedPermission);
|
|
2472
2799
|
}
|
|
2473
|
-
} catch (
|
|
2474
|
-
|
|
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");
|
|
2800
|
+
} catch (Exception e) {
|
|
2801
|
+
e.printStackTrace();
|
|
2497
2802
|
}
|
|
2498
|
-
return AttachmentFileIO.copy(context.getContentResolver().openInputStream(uri), directory, fileName).getAbsolutePath();
|
|
2499
2803
|
}
|
|
2500
2804
|
|
|
2501
|
-
public String copyFileFromUri(Context context, Uri
|
|
2805
|
+
public String copyFileFromUri(Context context, Uri fileUri, String fileName, String destinationPath, CallbackContext callback) {
|
|
2502
2806
|
try {
|
|
2503
|
-
|
|
2807
|
+
File saveDirectory = destinationPath != null && !destinationPath.isEmpty()
|
|
2808
|
+
? new File(mInterfaceUtil.rootDirectory, destinationPath)
|
|
2809
|
+
: new File(mInterfaceUtil.rootDirectory, mInterfaceUtil.packageName + "/images");
|
|
2810
|
+
return AttachmentFileIO.copy(context.getContentResolver().openInputStream(fileUri), saveDirectory, fileName).getAbsolutePath();
|
|
2504
2811
|
} catch (Exception e) {
|
|
2505
|
-
|
|
2812
|
+
callback.error("copyFileFromUri failed, exception is : " + e.getMessage());
|
|
2506
2813
|
return null;
|
|
2507
2814
|
}
|
|
2508
2815
|
}
|
|
@@ -2585,36 +2892,31 @@ public class mInterface extends CordovaPlugin implements com.google.android.gms.
|
|
|
2585
2892
|
final Status status = locationSettingsResult.getStatus();
|
|
2586
2893
|
switch (status.getStatusCode()) {
|
|
2587
2894
|
case LocationSettingsStatusCodes.SUCCESS:
|
|
2895
|
+
callback.success();
|
|
2588
2896
|
break;
|
|
2589
2897
|
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
|
|
2590
2898
|
try {
|
|
2591
2899
|
this.cordova.setActivityResultCallback(this);
|
|
2592
2900
|
status.startResolutionForResult(this.cordova.getActivity(), LOCATION_ACCURACY_REQUEST_NEW);
|
|
2593
2901
|
} catch (IntentSender.SendIntentException e) {
|
|
2594
|
-
|
|
2902
|
+
callback.error("Unable to open location settings: " + e.getMessage());
|
|
2595
2903
|
}
|
|
2596
2904
|
break;
|
|
2597
2905
|
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
|
|
2598
|
-
|
|
2906
|
+
callback.error("Location settings cannot be changed on this device");
|
|
2907
|
+
break;
|
|
2908
|
+
default:
|
|
2909
|
+
callback.error("Unable to check location settings: " + status.getStatusCode());
|
|
2599
2910
|
break;
|
|
2600
2911
|
}
|
|
2601
2912
|
} catch (Exception e) {
|
|
2602
|
-
|
|
2913
|
+
callback.error("LocationSettingsResult failed, exception is : " + e.getMessage());
|
|
2603
2914
|
}
|
|
2604
2915
|
}
|
|
2605
2916
|
|
|
2606
2917
|
@Override
|
|
2607
2918
|
public void onLocationChanged(@NonNull Location location) {
|
|
2608
2919
|
mCurrentLocation1 = location;
|
|
2609
|
-
try {
|
|
2610
|
-
System.out.println(mCurrentLocation1.getLatitude() + "," + mCurrentLocation1.getLongitude());
|
|
2611
|
-
if (currentLocationInd.equals("true")) {
|
|
2612
|
-
currentLocationInd = "";
|
|
2613
|
-
callback.success(mCurrentLocation1.getLatitude() + "," + mCurrentLocation1.getLongitude());
|
|
2614
|
-
}
|
|
2615
|
-
} catch (Exception e) {
|
|
2616
|
-
callback.error("onLocationChanged failed, exception is : " + e.getMessage());
|
|
2617
|
-
}
|
|
2618
2920
|
}
|
|
2619
2921
|
|
|
2620
2922
|
private class DownloadTask extends AsyncTask<String, Integer, String> {
|