Skip to content

Commit 7992186

Browse files
authored
fix: remove exif metadata preservation (#3511)
## 🎯 Goal This PR addresses a crash on later RN versions (`0.84` that we're aware of specifically). The reason is the deprecation/removal of `assets-library` on iOS. One important point here is the fact that we've never used this anyway and while it could technically be invoked by various integrations there is no reason for the lightweight implementation SDK side to expose this kind of API. The native handlers can still be registered in a way that allows for data preservation through other libraries. ## 🛠 Implementation details <!-- Provide a description of the implementation --> ## 🎨 UI Changes <!-- Add relevant screenshots --> <details> <summary>iOS</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> <details> <summary>Android</summary> <table> <thead> <tr> <td>Before</td> <td>After</td> </tr> </thead> <tbody> <tr> <td> <!--<img src="" /> --> </td> <td> <!--<img src="" /> --> </td> </tr> </tbody> </table> </details> ## 🧪 Testing <!-- Explain how this change can be tested (or why it can't be tested) --> ## ☑️ Checklist - [ ] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [ ] PR targets the `develop` branch - [ ] Documentation is updated - [ ] New code is tested in main example apps, including all possible scenarios - [ ] SampleApp iOS and Android - [ ] Expo iOS and Android
1 parent 4f0e2f8 commit 7992186

7 files changed

Lines changed: 19 additions & 321 deletions

File tree

package/native-package/android/src/main/java/com/streamchatreactnative/StreamChatReactNative.java

Lines changed: 0 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import android.os.Build;
1212
import android.provider.MediaStore;
1313
import android.util.Base64;
14-
import android.util.Log;
1514

1615
import java.io.ByteArrayOutputStream;
1716
import java.io.File;
@@ -33,108 +32,6 @@ public class StreamChatReactNative {
3332
private final static String SCHEME_FILE = "file";
3433
private final static String SCHEME_HTTP = "http";
3534
private final static String SCHEME_HTTPS = "https";
36-
37-
38-
// List of known EXIF tags we will be copying.
39-
// Orientation, width, height, and some others are ignored
40-
// TODO: Find any missing tag that might be useful
41-
private final static String[] EXIF_TO_COPY_ROTATED = new String[]
42-
{
43-
ExifInterface.TAG_APERTURE_VALUE,
44-
ExifInterface.TAG_MAX_APERTURE_VALUE,
45-
ExifInterface.TAG_METERING_MODE,
46-
ExifInterface.TAG_ARTIST,
47-
ExifInterface.TAG_BITS_PER_SAMPLE,
48-
ExifInterface.TAG_COMPRESSION,
49-
ExifInterface.TAG_BODY_SERIAL_NUMBER,
50-
ExifInterface.TAG_BRIGHTNESS_VALUE,
51-
ExifInterface.TAG_CONTRAST,
52-
ExifInterface.TAG_CAMERA_OWNER_NAME,
53-
ExifInterface.TAG_COLOR_SPACE,
54-
ExifInterface.TAG_COPYRIGHT,
55-
ExifInterface.TAG_DATETIME,
56-
ExifInterface.TAG_DATETIME_DIGITIZED,
57-
ExifInterface.TAG_DATETIME_ORIGINAL,
58-
ExifInterface.TAG_DEVICE_SETTING_DESCRIPTION,
59-
ExifInterface.TAG_DIGITAL_ZOOM_RATIO,
60-
ExifInterface.TAG_EXIF_VERSION,
61-
ExifInterface.TAG_EXPOSURE_BIAS_VALUE,
62-
ExifInterface.TAG_EXPOSURE_INDEX,
63-
ExifInterface.TAG_EXPOSURE_MODE,
64-
ExifInterface.TAG_EXPOSURE_TIME,
65-
ExifInterface.TAG_EXPOSURE_PROGRAM,
66-
ExifInterface.TAG_FLASH,
67-
ExifInterface.TAG_FLASH_ENERGY,
68-
ExifInterface.TAG_FOCAL_LENGTH,
69-
ExifInterface.TAG_FOCAL_LENGTH_IN_35MM_FILM,
70-
ExifInterface.TAG_FOCAL_PLANE_RESOLUTION_UNIT,
71-
ExifInterface.TAG_FOCAL_PLANE_X_RESOLUTION,
72-
ExifInterface.TAG_FOCAL_PLANE_Y_RESOLUTION,
73-
ExifInterface.TAG_PHOTOMETRIC_INTERPRETATION,
74-
ExifInterface.TAG_PLANAR_CONFIGURATION,
75-
ExifInterface.TAG_F_NUMBER,
76-
ExifInterface.TAG_GAIN_CONTROL,
77-
ExifInterface.TAG_GAMMA,
78-
ExifInterface.TAG_GPS_ALTITUDE,
79-
ExifInterface.TAG_GPS_ALTITUDE_REF,
80-
ExifInterface.TAG_GPS_AREA_INFORMATION,
81-
ExifInterface.TAG_GPS_DATESTAMP,
82-
ExifInterface.TAG_GPS_DOP,
83-
ExifInterface.TAG_GPS_LATITUDE,
84-
ExifInterface.TAG_GPS_LATITUDE_REF,
85-
ExifInterface.TAG_GPS_LONGITUDE,
86-
ExifInterface.TAG_GPS_LONGITUDE_REF,
87-
ExifInterface.TAG_GPS_STATUS,
88-
ExifInterface.TAG_GPS_DEST_BEARING,
89-
ExifInterface.TAG_GPS_DEST_BEARING_REF,
90-
ExifInterface.TAG_GPS_DEST_DISTANCE,
91-
ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
92-
ExifInterface.TAG_GPS_DEST_LATITUDE,
93-
ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
94-
ExifInterface.TAG_GPS_DEST_LONGITUDE,
95-
ExifInterface.TAG_GPS_DEST_LONGITUDE_REF,
96-
ExifInterface.TAG_GPS_DIFFERENTIAL,
97-
ExifInterface.TAG_GPS_IMG_DIRECTION,
98-
ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
99-
ExifInterface.TAG_GPS_MAP_DATUM,
100-
ExifInterface.TAG_GPS_MEASURE_MODE,
101-
ExifInterface.TAG_GPS_PROCESSING_METHOD,
102-
ExifInterface.TAG_GPS_SATELLITES,
103-
ExifInterface.TAG_GPS_SPEED,
104-
ExifInterface.TAG_GPS_SPEED_REF,
105-
ExifInterface.TAG_GPS_STATUS,
106-
ExifInterface.TAG_GPS_TIMESTAMP,
107-
ExifInterface.TAG_GPS_TRACK,
108-
ExifInterface.TAG_GPS_TRACK_REF,
109-
ExifInterface.TAG_GPS_VERSION_ID,
110-
ExifInterface.TAG_IMAGE_DESCRIPTION,
111-
ExifInterface.TAG_IMAGE_UNIQUE_ID,
112-
ExifInterface.TAG_ISO_SPEED,
113-
ExifInterface.TAG_PHOTOGRAPHIC_SENSITIVITY,
114-
ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT,
115-
ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
116-
ExifInterface.TAG_LENS_MAKE,
117-
ExifInterface.TAG_LENS_MODEL,
118-
ExifInterface.TAG_LENS_SERIAL_NUMBER,
119-
ExifInterface.TAG_LENS_SPECIFICATION,
120-
ExifInterface.TAG_LIGHT_SOURCE,
121-
ExifInterface.TAG_MAKE,
122-
ExifInterface.TAG_MAKER_NOTE,
123-
ExifInterface.TAG_MODEL,
124-
// ExifInterface.TAG_ORIENTATION, // removed
125-
ExifInterface.TAG_SATURATION,
126-
ExifInterface.TAG_SHARPNESS,
127-
ExifInterface.TAG_SHUTTER_SPEED_VALUE,
128-
ExifInterface.TAG_SOFTWARE,
129-
ExifInterface.TAG_SUBJECT_DISTANCE,
130-
ExifInterface.TAG_SUBJECT_DISTANCE_RANGE,
131-
ExifInterface.TAG_SUBJECT_LOCATION,
132-
ExifInterface.TAG_USER_COMMENT,
133-
ExifInterface.TAG_WHITE_BALANCE
134-
};
135-
136-
137-
13835
/**
13936
* Resize the specified bitmap.
14037
*/
@@ -263,55 +160,6 @@ private static File getFileFromUri(Context context, Uri uri) {
263160
return file;
264161
}
265162

266-
/**
267-
* Attempts to copy exif info from one file to another. Note: orientation, width, and height
268-
exif attributes are not copied since those are lost after image rotation.
269-
270-
* imageUri: original image URI as provided from JS
271-
* dstPath: final image output path
272-
* Returns true if copy was successful, false otherwise.
273-
*/
274-
public static boolean copyExif(Context context, Uri imageUri, String dstPath){
275-
ExifInterface src = null;
276-
ExifInterface dst = null;
277-
278-
try {
279-
280-
File file = getFileFromUri(context, imageUri);
281-
if (!file.exists()) {
282-
return false;
283-
}
284-
285-
src = new ExifInterface(file.getAbsolutePath());
286-
dst = new ExifInterface(dstPath);
287-
288-
} catch (Exception ignored) {
289-
Log.e("StreamChatReactNative::copyExif", "EXIF read failed", ignored);
290-
}
291-
292-
if(src == null || dst == null){
293-
return false;
294-
}
295-
296-
try{
297-
298-
for (String attr : EXIF_TO_COPY_ROTATED)
299-
{
300-
String value = src.getAttribute(attr);
301-
if (value != null){
302-
dst.setAttribute(attr, value);
303-
}
304-
}
305-
dst.saveAttributes();
306-
307-
} catch (Exception ignored) {
308-
Log.e("StreamChatReactNative::copyExif", "EXIF copy failed", ignored);
309-
return false;
310-
}
311-
312-
return true;
313-
}
314-
315163
/**
316164
* Get orientation by reading Image metadata
317165
*/
@@ -591,4 +439,3 @@ public static Bitmap createResizedImage(Context context, Uri imageUri, int newWi
591439
return scaledImage;
592440
}
593441
}
594-

package/native-package/android/src/main/java/com/streamchatreactnative/StreamChatReactNativeModule.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import android.graphics.Bitmap;
55
import android.net.Uri;
66
import android.os.AsyncTask;
7-
import android.util.Log;
8-
97
import androidx.annotation.Nullable;
108
import androidx.annotation.NonNull;
119

@@ -36,7 +34,7 @@ public String getName() {
3634
}
3735

3836
@ReactMethod
39-
public void createResizedImage(String uri, double width, double height, String format, double quality, String mode, boolean onlyScaleDown, Double rotation, @Nullable String outputPath, Boolean keepMeta, Promise promise) {
37+
public void createResizedImage(String uri, double width, double height, String format, double quality, String mode, boolean onlyScaleDown, Double rotation, @Nullable String outputPath, Promise promise) {
4038
WritableMap options = Arguments.createMap();
4139
options.putString("mode", mode);
4240
options.putBoolean("onlyScaleDown", onlyScaleDown);
@@ -46,7 +44,7 @@ public void createResizedImage(String uri, double width, double height, String f
4644
@Override
4745
protected void doInBackgroundGuarded(Void... params) {
4846
try {
49-
Object response = createResizedImageWithExceptions(uri, (int) width, (int) height, format, (int) quality, rotation.intValue(), outputPath, keepMeta, options);
47+
Object response = createResizedImageWithExceptions(uri, (int) width, (int) height, format, (int) quality, rotation.intValue(), outputPath, options);
5048
promise.resolve(response);
5149
}
5250
catch (IOException e) {
@@ -59,7 +57,6 @@ protected void doInBackgroundGuarded(Void... params) {
5957
@SuppressLint("LongLogTag")
6058
private Object createResizedImageWithExceptions(String imagePath, int newWidth, int newHeight,
6159
String compressFormatString, int quality, int rotation, String outputPath,
62-
final boolean keepMeta,
6360
final ReadableMap options) throws IOException {
6461

6562
Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.valueOf(compressFormatString);
@@ -89,16 +86,6 @@ private Object createResizedImageWithExceptions(String imagePath, int newWidth,
8986
response.putDouble("size", resizedImage.length());
9087
response.putDouble("width", scaledImage.getWidth());
9188
response.putDouble("height", scaledImage.getHeight());
92-
93-
// Copy file's metadata/exif info if required
94-
if(keepMeta){
95-
try{
96-
StreamChatReactNative.copyExif(this.getReactApplicationContext(), imageUri, resizedImage.getAbsolutePath());
97-
}
98-
catch(Exception ignored){
99-
Log.e("StreamChatReactNative::createResizedImageWithExceptions", "EXIF copy failed", ignored);
100-
}
101-
}
10289
} else {
10390
throw new IOException("Error getting resized image path");
10491
}

package/native-package/android/src/oldarch/com/streamchatreactnative/StreamChatReactNative.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ abstract class StreamChatReactNativeSpec extends ReactContextBaseJavaModule {
1212
super(context);
1313
}
1414

15-
public abstract void createResizedImage(String uri, double width, double height, String format, double quality, String mode, boolean onlyScaleDown, Double rotation, @Nullable String outputPath, Boolean keepMeta, Promise promise);
15+
public abstract void createResizedImage(String uri, double width, double height, String format, double quality, String mode, boolean onlyScaleDown, Double rotation, @Nullable String outputPath, Promise promise);
1616
}

0 commit comments

Comments
 (0)