mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-03-06 17:34:07 +08:00
Fixed bug with Android's CameraRoll module where saveToPhotos crashed devices on a very small subset of devices
Summary: For a small subset of Android devices, the following line of code caused the device to crash ``` output.transferFrom(input, 0, Long.MAX_VALUE); ``` According to the [Java docs](https://docs.oracle.com/javase/1.5.0/docs/api/java/nio/channels/FileChannel.html), this is what the function does. > Transfers bytes into this channel's file from the given readable byte channel. An attempt is made to read up to count bytes from the source channel and write them to this channel's file starting at the given position. An invocation of this method may or may not transfer all of the requested bytes; whether or not it does so depends upon the natures and states of the channels. Fewer than the requested number of bytes will be transferred if the source channel has fewer than count bytes remaining, or if the source channel is non-blocking and has fewer than count bytes immediately available in its input buffer. Hence, using `Long.MAX_VALUE` seemed to be the standard way to transfer all bytes from one channel to the other. However, it appeared that for some reason on a subset of old Android devices, the device tries to allocate `count` bytes of memory before transferring the bytes. Obviously, this caused a crash because no device has that much memory. This was fixed transferring bytes using a 1MB buffer. Differential Revision: D14921778 fbshipit-source-id: 7fa46e10c656e23ae7d5679c72b278188f09ad0a
This commit is contained in:
committed by
Facebook Github Bot
parent
0bd931e47e
commit
e28b6f314a
@@ -43,6 +43,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
@@ -111,6 +112,7 @@ public class CameraRollManager extends ReactContextBaseJavaModule {
|
||||
|
||||
private static class SaveToCameraRoll extends GuardedAsyncTask<Void, Void> {
|
||||
|
||||
private static final int SAVE_BUFFER_SIZE = 1048576; // 1MB
|
||||
private final Context mContext;
|
||||
private final Uri mUri;
|
||||
private final Promise mPromise;
|
||||
@@ -155,7 +157,18 @@ public class CameraRollManager extends ReactContextBaseJavaModule {
|
||||
dest = new File(exportDir, sourceName + "_" + (n++) + sourceExt);
|
||||
}
|
||||
output = new FileOutputStream(dest).getChannel();
|
||||
output.transferFrom(input, 0, Long.MAX_VALUE);
|
||||
// Performs a buffered copy
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(SAVE_BUFFER_SIZE);
|
||||
while (input.read(buffer) > 0) {
|
||||
buffer.flip();
|
||||
output.write(buffer);
|
||||
buffer.compact();
|
||||
}
|
||||
// Drains the buffer
|
||||
buffer.flip();
|
||||
while (buffer.hasRemaining()){
|
||||
output.write(buffer);
|
||||
}
|
||||
input.close();
|
||||
output.close();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user