@capawesome/capacitor-exif 0.0.1

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.
Files changed (43) hide show
  1. package/CapawesomeCapacitorExif.podspec +17 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +28 -0
  4. package/README.md +322 -0
  5. package/android/build.gradle +60 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/Exif.java +289 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/ExifPlugin.java +120 -0
  9. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/CustomException.java +20 -0
  10. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/CustomExceptions.java +27 -0
  11. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/options/ReadExifOptions.java +36 -0
  12. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/options/RemoveExifOptions.java +43 -0
  13. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/options/WriteExifOptions.java +185 -0
  14. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/classes/results/ReadExifResult.java +152 -0
  15. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/interfaces/Callback.java +5 -0
  16. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/interfaces/EmptyCallback.java +5 -0
  17. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/interfaces/NonEmptyResultCallback.java +7 -0
  18. package/android/src/main/java/io/capawesome/capacitorjs/plugins/exif/interfaces/Result.java +7 -0
  19. package/android/src/main/res/.gitkeep +0 -0
  20. package/dist/docs.json +746 -0
  21. package/dist/esm/definitions.d.ts +375 -0
  22. package/dist/esm/definitions.js +32 -0
  23. package/dist/esm/definitions.js.map +1 -0
  24. package/dist/esm/index.d.ts +4 -0
  25. package/dist/esm/index.js +7 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/web.d.ts +7 -0
  28. package/dist/esm/web.js +13 -0
  29. package/dist/esm/web.js.map +1 -0
  30. package/dist/plugin.cjs.js +59 -0
  31. package/dist/plugin.cjs.js.map +1 -0
  32. package/dist/plugin.js +62 -0
  33. package/dist/plugin.js.map +1 -0
  34. package/ios/Plugin/Classes/Options/ReadExifOptions.swift +20 -0
  35. package/ios/Plugin/Classes/Options/RemoveExifOptions.swift +12 -0
  36. package/ios/Plugin/Classes/Options/WriteExifOptions.swift +49 -0
  37. package/ios/Plugin/Classes/Results/ReadExifResult.swift +75 -0
  38. package/ios/Plugin/Enums/CustomError.swift +54 -0
  39. package/ios/Plugin/Exif.swift +219 -0
  40. package/ios/Plugin/ExifPlugin.swift +83 -0
  41. package/ios/Plugin/Info.plist +24 -0
  42. package/ios/Plugin/Protocols/Result.swift +5 -0
  43. package/package.json +97 -0
@@ -0,0 +1,289 @@
1
+ package io.capawesome.capacitorjs.plugins.exif;
2
+
3
+ import android.graphics.BitmapFactory;
4
+ import androidx.annotation.NonNull;
5
+ import androidx.annotation.Nullable;
6
+ import androidx.exifinterface.media.ExifInterface;
7
+ import io.capawesome.capacitorjs.plugins.exif.classes.CustomExceptions;
8
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.ReadExifOptions;
9
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.RemoveExifOptions;
10
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.WriteExifOptions;
11
+ import io.capawesome.capacitorjs.plugins.exif.classes.results.ReadExifResult;
12
+ import io.capawesome.capacitorjs.plugins.exif.interfaces.EmptyCallback;
13
+ import io.capawesome.capacitorjs.plugins.exif.interfaces.NonEmptyResultCallback;
14
+ import java.io.File;
15
+ import java.io.FileInputStream;
16
+ import java.io.InputStream;
17
+
18
+ public class Exif {
19
+
20
+ private static final String[] REMOVABLE_TAGS = {
21
+ ExifInterface.TAG_APERTURE_VALUE,
22
+ ExifInterface.TAG_ARTIST,
23
+ ExifInterface.TAG_BODY_SERIAL_NUMBER,
24
+ ExifInterface.TAG_BRIGHTNESS_VALUE,
25
+ ExifInterface.TAG_CAMERA_OWNER_NAME,
26
+ ExifInterface.TAG_CFA_PATTERN,
27
+ ExifInterface.TAG_COLOR_SPACE,
28
+ ExifInterface.TAG_COMPONENTS_CONFIGURATION,
29
+ ExifInterface.TAG_COMPRESSED_BITS_PER_PIXEL,
30
+ ExifInterface.TAG_CONTRAST,
31
+ ExifInterface.TAG_COPYRIGHT,
32
+ ExifInterface.TAG_CUSTOM_RENDERED,
33
+ ExifInterface.TAG_DATETIME,
34
+ ExifInterface.TAG_DATETIME_DIGITIZED,
35
+ ExifInterface.TAG_DATETIME_ORIGINAL,
36
+ ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION,
37
+ ExifInterface.TAG_DIGITAL_ZOOM_RATIO,
38
+ ExifInterface.TAG_EXIF_VERSION,
39
+ ExifInterface.TAG_EXPOSURE_BIAS_VALUE,
40
+ ExifInterface.TAG_EXPOSURE_INDEX,
41
+ ExifInterface.TAG_EXPOSURE_MODE,
42
+ ExifInterface.TAG_EXPOSURE_PROGRAM,
43
+ ExifInterface.TAG_EXPOSURE_TIME,
44
+ ExifInterface.TAG_FILE_SOURCE,
45
+ ExifInterface.TAG_FLASH,
46
+ ExifInterface.TAG_FLASHPIX_VERSION,
47
+ ExifInterface.TAG_FLASH_ENERGY,
48
+ ExifInterface.TAG_FOCAL_LENGTH,
49
+ ExifInterface.TAG_FOCAL_LENGTH_IN_35MM_FILM,
50
+ ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT,
51
+ ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION,
52
+ ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION,
53
+ ExifInterface.TAG_F_NUMBER,
54
+ ExifInterface.TAG_GAIN_CONTROL,
55
+ ExifInterface.TAG_GAMMA,
56
+ ExifInterface.TAG_GPS_ALTITUDE,
57
+ ExifInterface.TAG_GPS_ALTITUDE_REF,
58
+ ExifInterface.TAG_GPS_AREA_INFORMATION,
59
+ ExifInterface.TAG_GPS_DATESTAMP,
60
+ ExifInterface.TAG_GPS_DEST_BEARING,
61
+ ExifInterface.TAG_GPS_DEST_BEARING_REF,
62
+ ExifInterface.TAG_GPS_DEST_DISTANCE,
63
+ ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
64
+ ExifInterface.TAG_GPS_DEST_LATITUDE,
65
+ ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
66
+ ExifInterface.TAG_GPS_DEST_LONGITUDE,
67
+ ExifInterface.TAG_GPS_DEST_LONGITUDE_REF,
68
+ ExifInterface.TAG_GPS_DIFFERENTIAL,
69
+ ExifInterface.TAG_GPS_DOP,
70
+ ExifInterface.TAG_GPS_H_POSITIONING_ERROR,
71
+ ExifInterface.TAG_GPS_IMG_DIRECTION,
72
+ ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
73
+ ExifInterface.TAG_GPS_LATITUDE,
74
+ ExifInterface.TAG_GPS_LATITUDE_REF,
75
+ ExifInterface.TAG_GPS_LONGITUDE,
76
+ ExifInterface.TAG_GPS_LONGITUDE_REF,
77
+ ExifInterface.TAG_GPS_MAP_DATUM,
78
+ ExifInterface.TAG_GPS_MEASURE_MODE,
79
+ ExifInterface.TAG_GPS_PROCESSING_METHOD,
80
+ ExifInterface.TAG_GPS_SATELLITES,
81
+ ExifInterface.TAG_GPS_SPEED,
82
+ ExifInterface.TAG_GPS_SPEED_REF,
83
+ ExifInterface.TAG_GPS_STATUS,
84
+ ExifInterface.TAG_GPS_TIMESTAMP,
85
+ ExifInterface.TAG_GPS_TRACK,
86
+ ExifInterface.TAG_GPS_TRACK_REF,
87
+ ExifInterface.TAG_GPS_VERSION_ID,
88
+ ExifInterface.TAG_IMAGE_DESCRIPTION,
89
+ ExifInterface.TAG_IMAGE_UNIQUE_ID,
90
+ ExifInterface.TAG_INTEROPERABILITY_INDEX,
91
+ ExifInterface.TAG_ISO_SPEED,
92
+ ExifInterface.TAG_ISO_SPEED_LATITUDE_YYY,
93
+ ExifInterface.TAG_ISO_SPEED_LATITUDE_ZZZ,
94
+ ExifInterface.TAG_LENS_MAKE,
95
+ ExifInterface.TAG_LENS_MODEL,
96
+ ExifInterface.TAG_LENS_SERIAL_NUMBER,
97
+ ExifInterface.TAG_LENS_SPECIFICATION,
98
+ ExifInterface.TAG_LIGHT_SOURCE,
99
+ ExifInterface.TAG_MAKE,
100
+ ExifInterface.TAG_MAKER_NOTE,
101
+ ExifInterface.TAG_MAX_APERTURE_VALUE,
102
+ ExifInterface.TAG_METERING_MODE,
103
+ ExifInterface.TAG_MODEL,
104
+ ExifInterface.TAG_OECF,
105
+ ExifInterface.TAG_OFFSET_TIME,
106
+ ExifInterface.TAG_OFFSET_TIME_DIGITIZED,
107
+ ExifInterface.TAG_OFFSET_TIME_ORIGINAL,
108
+ ExifInterface.TAG_ORIENTATION,
109
+ ExifInterface.TAG_PHOTOGRAPHIC_SENSITIVITY,
110
+ ExifInterface.TAG_PIXEL_X_DIMENSION,
111
+ ExifInterface.TAG_PIXEL_Y_DIMENSION,
112
+ ExifInterface.TAG_RECOMMENDED_EXPOSURE_INDEX,
113
+ ExifInterface.TAG_RELATED_SOUND_FILE,
114
+ ExifInterface.TAG_RESOLUTION_UNIT,
115
+ ExifInterface.TAG_SATURATION,
116
+ ExifInterface.TAG_SCENE_CAPTURE_TYPE,
117
+ ExifInterface.TAG_SCENE_TYPE,
118
+ ExifInterface.TAG_SENSING_METHOD,
119
+ ExifInterface.TAG_SENSITIVITY_TYPE,
120
+ ExifInterface.TAG_SHARPNESS,
121
+ ExifInterface.TAG_SHUTTER_SPEED_VALUE,
122
+ ExifInterface.TAG_SOFTWARE,
123
+ ExifInterface.TAG_SPATIAL_FREQUENCY_RESPONSE,
124
+ ExifInterface.TAG_SPECTRAL_SENSITIVITY,
125
+ ExifInterface.TAG_STANDARD_OUTPUT_SENSITIVITY,
126
+ ExifInterface.TAG_SUBJECT_AREA,
127
+ ExifInterface.TAG_SUBJECT_DISTANCE,
128
+ ExifInterface.TAG_SUBJECT_DISTANCE_RANGE,
129
+ ExifInterface.TAG_SUBJECT_LOCATION,
130
+ ExifInterface.TAG_SUBSEC_TIME,
131
+ ExifInterface.TAG_SUBSEC_TIME_DIGITIZED,
132
+ ExifInterface.TAG_SUBSEC_TIME_ORIGINAL,
133
+ ExifInterface.TAG_USER_COMMENT,
134
+ ExifInterface.TAG_WHITE_BALANCE,
135
+ ExifInterface.TAG_X_RESOLUTION,
136
+ ExifInterface.TAG_Y_RESOLUTION
137
+ };
138
+
139
+ @NonNull
140
+ private final ExifPlugin plugin;
141
+
142
+ public Exif(@NonNull ExifPlugin plugin) {
143
+ this.plugin = plugin;
144
+ }
145
+
146
+ public void readExif(@NonNull ReadExifOptions options, @NonNull NonEmptyResultCallback<ReadExifResult> callback) {
147
+ File file = new File(options.getPath());
148
+ if (!file.exists()) {
149
+ callback.error(CustomExceptions.FILE_NOT_FOUND);
150
+ return;
151
+ }
152
+ try {
153
+ ExifInterface exifInterface = new ExifInterface(file);
154
+ BitmapFactory.Options boundsOptions = new BitmapFactory.Options();
155
+ boundsOptions.inJustDecodeBounds = true;
156
+ BitmapFactory.decodeFile(file.getPath(), boundsOptions);
157
+ Integer pixelWidth = boundsOptions.outWidth > 0 ? boundsOptions.outWidth : null;
158
+ Integer pixelHeight = boundsOptions.outHeight > 0 ? boundsOptions.outHeight : null;
159
+ callback.success(new ReadExifResult(exifInterface, pixelWidth, pixelHeight));
160
+ } catch (Exception exception) {
161
+ callback.error(CustomExceptions.READ_FAILED);
162
+ }
163
+ }
164
+
165
+ public void removeExif(@NonNull RemoveExifOptions options, @NonNull EmptyCallback callback) {
166
+ File file = new File(options.getPath());
167
+ if (!file.exists()) {
168
+ callback.error(CustomExceptions.FILE_NOT_FOUND);
169
+ return;
170
+ }
171
+ try {
172
+ if (!isWritableFormat(file)) {
173
+ callback.error(CustomExceptions.UNSUPPORTED_FORMAT);
174
+ return;
175
+ }
176
+ } catch (Exception exception) {
177
+ callback.error(CustomExceptions.READ_FAILED);
178
+ return;
179
+ }
180
+ try {
181
+ ExifInterface exifInterface = new ExifInterface(file);
182
+ String orientation = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);
183
+ for (String tag : REMOVABLE_TAGS) {
184
+ exifInterface.setAttribute(tag, null);
185
+ }
186
+ if (options.getKeepOrientation() && orientation != null) {
187
+ exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, orientation);
188
+ }
189
+ exifInterface.saveAttributes();
190
+ callback.success();
191
+ } catch (Exception exception) {
192
+ callback.error(CustomExceptions.WRITE_FAILED);
193
+ }
194
+ }
195
+
196
+ public void writeExif(@NonNull WriteExifOptions options, @NonNull EmptyCallback callback) {
197
+ File file = new File(options.getPath());
198
+ if (!file.exists()) {
199
+ callback.error(CustomExceptions.FILE_NOT_FOUND);
200
+ return;
201
+ }
202
+ try {
203
+ if (!isWritableFormat(file)) {
204
+ callback.error(CustomExceptions.UNSUPPORTED_FORMAT);
205
+ return;
206
+ }
207
+ } catch (Exception exception) {
208
+ callback.error(CustomExceptions.READ_FAILED);
209
+ return;
210
+ }
211
+ try {
212
+ ExifInterface exifInterface = new ExifInterface(file);
213
+ applyTags(exifInterface, options);
214
+ exifInterface.saveAttributes();
215
+ callback.success();
216
+ } catch (Exception exception) {
217
+ callback.error(CustomExceptions.WRITE_FAILED);
218
+ }
219
+ }
220
+
221
+ private void applyTags(@NonNull ExifInterface exifInterface, @NonNull WriteExifOptions options) {
222
+ if (options.getDateTimeOriginal() != null) {
223
+ exifInterface.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, options.getDateTimeOriginal());
224
+ }
225
+ if (options.getExposureTime() != null) {
226
+ exifInterface.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, String.valueOf(options.getExposureTime()));
227
+ }
228
+ if (options.getFNumber() != null) {
229
+ exifInterface.setAttribute(ExifInterface.TAG_F_NUMBER, String.valueOf(options.getFNumber()));
230
+ }
231
+ if (options.getFlash() != null) {
232
+ exifInterface.setAttribute(ExifInterface.TAG_FLASH, options.getFlash() ? "1" : "0");
233
+ }
234
+ if (options.getFocalLength() != null) {
235
+ exifInterface.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, convertDoubleToRational(options.getFocalLength()));
236
+ }
237
+ if (options.getGpsAltitude() != null) {
238
+ exifInterface.setAltitude(options.getGpsAltitude());
239
+ }
240
+ if (options.getGpsLatitude() != null && options.getGpsLongitude() != null) {
241
+ exifInterface.setLatLong(options.getGpsLatitude(), options.getGpsLongitude());
242
+ }
243
+ if (options.getIso() != null) {
244
+ exifInterface.setAttribute(ExifInterface.TAG_PHOTOGRAPHIC_SENSITIVITY, String.valueOf(options.getIso()));
245
+ }
246
+ if (options.getLensModel() != null) {
247
+ exifInterface.setAttribute(ExifInterface.TAG_LENS_MODEL, options.getLensModel());
248
+ }
249
+ if (options.getMake() != null) {
250
+ exifInterface.setAttribute(ExifInterface.TAG_MAKE, options.getMake());
251
+ }
252
+ if (options.getModel() != null) {
253
+ exifInterface.setAttribute(ExifInterface.TAG_MODEL, options.getModel());
254
+ }
255
+ if (options.getOrientation() != null) {
256
+ exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(options.getOrientation()));
257
+ }
258
+ if (options.getSoftware() != null) {
259
+ exifInterface.setAttribute(ExifInterface.TAG_SOFTWARE, options.getSoftware());
260
+ }
261
+ }
262
+
263
+ @NonNull
264
+ private String convertDoubleToRational(double value) {
265
+ return Math.round(value * 1000) + "/1000";
266
+ }
267
+
268
+ private boolean isWritableFormat(@NonNull File file) throws Exception {
269
+ byte[] header = new byte[12];
270
+ try (InputStream inputStream = new FileInputStream(file)) {
271
+ int bytesRead = inputStream.read(header);
272
+ if (bytesRead < 12) {
273
+ return false;
274
+ }
275
+ }
276
+ boolean isJpeg = (header[0] & 0xFF) == 0xFF && (header[1] & 0xFF) == 0xD8 && (header[2] & 0xFF) == 0xFF;
277
+ boolean isPng = (header[0] & 0xFF) == 0x89 && header[1] == 'P' && header[2] == 'N' && header[3] == 'G';
278
+ boolean isWebp =
279
+ header[0] == 'R' &&
280
+ header[1] == 'I' &&
281
+ header[2] == 'F' &&
282
+ header[3] == 'F' &&
283
+ header[8] == 'W' &&
284
+ header[9] == 'E' &&
285
+ header[10] == 'B' &&
286
+ header[11] == 'P';
287
+ return isJpeg || isPng || isWebp;
288
+ }
289
+ }
@@ -0,0 +1,120 @@
1
+ package io.capawesome.capacitorjs.plugins.exif;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import com.getcapacitor.Logger;
6
+ import com.getcapacitor.Plugin;
7
+ import com.getcapacitor.PluginCall;
8
+ import com.getcapacitor.PluginMethod;
9
+ import com.getcapacitor.annotation.CapacitorPlugin;
10
+ import io.capawesome.capacitorjs.plugins.exif.classes.CustomException;
11
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.ReadExifOptions;
12
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.RemoveExifOptions;
13
+ import io.capawesome.capacitorjs.plugins.exif.classes.options.WriteExifOptions;
14
+ import io.capawesome.capacitorjs.plugins.exif.classes.results.ReadExifResult;
15
+ import io.capawesome.capacitorjs.plugins.exif.interfaces.EmptyCallback;
16
+ import io.capawesome.capacitorjs.plugins.exif.interfaces.NonEmptyResultCallback;
17
+ import io.capawesome.capacitorjs.plugins.exif.interfaces.Result;
18
+
19
+ @CapacitorPlugin(name = "Exif")
20
+ public class ExifPlugin extends Plugin {
21
+
22
+ public static final String ERROR_UNKNOWN_ERROR = "An unknown error has occurred.";
23
+ public static final String TAG = "ExifPlugin";
24
+
25
+ private Exif implementation;
26
+
27
+ @Override
28
+ public void load() {
29
+ super.load();
30
+ this.implementation = new Exif(this);
31
+ }
32
+
33
+ @PluginMethod
34
+ public void readExif(PluginCall call) {
35
+ try {
36
+ ReadExifOptions options = new ReadExifOptions(call);
37
+ NonEmptyResultCallback<ReadExifResult> callback = new NonEmptyResultCallback<>() {
38
+ @Override
39
+ public void success(@NonNull ReadExifResult result) {
40
+ resolveCall(call, result);
41
+ }
42
+
43
+ @Override
44
+ public void error(Exception exception) {
45
+ rejectCall(call, exception);
46
+ }
47
+ };
48
+ implementation.readExif(options, callback);
49
+ } catch (Exception exception) {
50
+ rejectCall(call, exception);
51
+ }
52
+ }
53
+
54
+ @PluginMethod
55
+ public void removeExif(PluginCall call) {
56
+ try {
57
+ RemoveExifOptions options = new RemoveExifOptions(call);
58
+ EmptyCallback callback = new EmptyCallback() {
59
+ @Override
60
+ public void success() {
61
+ resolveCall(call);
62
+ }
63
+
64
+ @Override
65
+ public void error(Exception exception) {
66
+ rejectCall(call, exception);
67
+ }
68
+ };
69
+ implementation.removeExif(options, callback);
70
+ } catch (Exception exception) {
71
+ rejectCall(call, exception);
72
+ }
73
+ }
74
+
75
+ @PluginMethod
76
+ public void writeExif(PluginCall call) {
77
+ try {
78
+ WriteExifOptions options = new WriteExifOptions(call);
79
+ EmptyCallback callback = new EmptyCallback() {
80
+ @Override
81
+ public void success() {
82
+ resolveCall(call);
83
+ }
84
+
85
+ @Override
86
+ public void error(Exception exception) {
87
+ rejectCall(call, exception);
88
+ }
89
+ };
90
+ implementation.writeExif(options, callback);
91
+ } catch (Exception exception) {
92
+ rejectCall(call, exception);
93
+ }
94
+ }
95
+
96
+ private void rejectCall(@NonNull PluginCall call, @NonNull Exception exception) {
97
+ String message = exception.getMessage();
98
+ if (message == null) {
99
+ message = ERROR_UNKNOWN_ERROR;
100
+ }
101
+ String code = null;
102
+ if (exception instanceof CustomException) {
103
+ code = ((CustomException) exception).getCode();
104
+ }
105
+ Logger.error(TAG, message, exception);
106
+ call.reject(message, code);
107
+ }
108
+
109
+ private void resolveCall(@NonNull PluginCall call) {
110
+ call.resolve();
111
+ }
112
+
113
+ private void resolveCall(@NonNull PluginCall call, @Nullable Result result) {
114
+ if (result == null) {
115
+ call.resolve();
116
+ } else {
117
+ call.resolve(result.toJSObject());
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,20 @@
1
+ package io.capawesome.capacitorjs.plugins.exif.classes;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+
6
+ public class CustomException extends Exception {
7
+
8
+ @Nullable
9
+ private final String code;
10
+
11
+ public CustomException(@Nullable String code, @NonNull String message) {
12
+ super(message);
13
+ this.code = code;
14
+ }
15
+
16
+ @Nullable
17
+ public String getCode() {
18
+ return code;
19
+ }
20
+ }
@@ -0,0 +1,27 @@
1
+ package io.capawesome.capacitorjs.plugins.exif.classes;
2
+
3
+ public class CustomExceptions {
4
+
5
+ public static final CustomException FILE_NOT_FOUND = new CustomException(
6
+ "FILE_NOT_FOUND",
7
+ "The file was not found at the provided path."
8
+ );
9
+ public static final CustomException GPS_COORDINATES_INCOMPLETE = new CustomException(
10
+ null,
11
+ "gpsLatitude and gpsLongitude must be provided together."
12
+ );
13
+ public static final CustomException PATH_MISSING = new CustomException(null, "path must be provided.");
14
+ public static final CustomException READ_FAILED = new CustomException(
15
+ "READ_FAILED",
16
+ "The EXIF metadata could not be read from the file."
17
+ );
18
+ public static final CustomException TAGS_MISSING = new CustomException(null, "tags must be provided.");
19
+ public static final CustomException UNSUPPORTED_FORMAT = new CustomException(
20
+ "UNSUPPORTED_FORMAT",
21
+ "The file format does not support writing or removing EXIF metadata on this platform."
22
+ );
23
+ public static final CustomException WRITE_FAILED = new CustomException(
24
+ "WRITE_FAILED",
25
+ "The EXIF metadata could not be written to the file."
26
+ );
27
+ }
@@ -0,0 +1,36 @@
1
+ package io.capawesome.capacitorjs.plugins.exif.classes.options;
2
+
3
+ import android.net.Uri;
4
+ import androidx.annotation.NonNull;
5
+ import com.getcapacitor.PluginCall;
6
+ import io.capawesome.capacitorjs.plugins.exif.classes.CustomExceptions;
7
+
8
+ public class ReadExifOptions {
9
+
10
+ @NonNull
11
+ private final String path;
12
+
13
+ public ReadExifOptions(@NonNull PluginCall call) throws Exception {
14
+ this.path = ReadExifOptions.getPathFromCall(call);
15
+ }
16
+
17
+ @NonNull
18
+ public String getPath() {
19
+ return path;
20
+ }
21
+
22
+ @NonNull
23
+ private static String getPathFromCall(@NonNull PluginCall call) throws Exception {
24
+ String path = call.getString("path");
25
+ if (path == null || path.isEmpty()) {
26
+ throw CustomExceptions.PATH_MISSING;
27
+ }
28
+ if (path.startsWith("file://")) {
29
+ String uriPath = Uri.parse(path).getPath();
30
+ if (uriPath != null) {
31
+ return uriPath;
32
+ }
33
+ }
34
+ return path;
35
+ }
36
+ }
@@ -0,0 +1,43 @@
1
+ package io.capawesome.capacitorjs.plugins.exif.classes.options;
2
+
3
+ import android.net.Uri;
4
+ import androidx.annotation.NonNull;
5
+ import com.getcapacitor.PluginCall;
6
+ import io.capawesome.capacitorjs.plugins.exif.classes.CustomExceptions;
7
+
8
+ public class RemoveExifOptions {
9
+
10
+ private final boolean keepOrientation;
11
+
12
+ @NonNull
13
+ private final String path;
14
+
15
+ public RemoveExifOptions(@NonNull PluginCall call) throws Exception {
16
+ this.keepOrientation = call.getBoolean("keepOrientation", true);
17
+ this.path = RemoveExifOptions.getPathFromCall(call);
18
+ }
19
+
20
+ public boolean getKeepOrientation() {
21
+ return keepOrientation;
22
+ }
23
+
24
+ @NonNull
25
+ public String getPath() {
26
+ return path;
27
+ }
28
+
29
+ @NonNull
30
+ private static String getPathFromCall(@NonNull PluginCall call) throws Exception {
31
+ String path = call.getString("path");
32
+ if (path == null || path.isEmpty()) {
33
+ throw CustomExceptions.PATH_MISSING;
34
+ }
35
+ if (path.startsWith("file://")) {
36
+ String uriPath = Uri.parse(path).getPath();
37
+ if (uriPath != null) {
38
+ return uriPath;
39
+ }
40
+ }
41
+ return path;
42
+ }
43
+ }