Allow CameraRoll to export videos

Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:

```
// old
saveImageWithTag(tag: string): Promise<string>

// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```

if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.

I've left in the `saveImageWithTag` method for now with a deprecation warning.

**Test plan (required)**

I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.

```js
// index.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988

Differential Revision: D3401251

Pulled By: nicklockwood

fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
This commit is contained in:
Kyle Corbitt
2016-06-07 16:37:48 -07:00
committed by Facebook Github Bot 7
parent d4e7c8a055
commit 7357ccc370
3 changed files with 70 additions and 39 deletions

View File

@@ -117,22 +117,26 @@ public class CameraRollManager extends ReactContextBaseJavaModule {
* @param promise to be resolved or rejected
*/
@ReactMethod
public void saveImageWithTag(String uri, Promise promise) {
new SaveImageTag(getReactApplicationContext(), Uri.parse(uri), promise)
public void saveToCameraRoll(String uri, String type, Promise promise) {
MediaType parsedType = type.equals("video") ? MediaType.VIDEO : MediaType.PHOTO;
new SaveToCameraRoll(getReactApplicationContext(), Uri.parse(uri), parsedType, promise)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private static class SaveImageTag extends GuardedAsyncTask<Void, Void> {
private enum MediaType { PHOTO, VIDEO };
private static class SaveToCameraRoll extends GuardedAsyncTask<Void, Void> {
private final Context mContext;
private final Uri mUri;
private final Promise mPromise;
private final MediaType mType;
public SaveImageTag(ReactContext context, Uri uri, Promise promise) {
public SaveToCameraRoll(ReactContext context, Uri uri, MediaType type, Promise promise) {
super(context);
mContext = context;
mUri = uri;
mPromise = promise;
mType = type;
}
@Override
@@ -140,14 +144,15 @@ public class CameraRollManager extends ReactContextBaseJavaModule {
File source = new File(mUri.getPath());
FileChannel input = null, output = null;
try {
File pictures =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
pictures.mkdirs();
if (!pictures.isDirectory()) {
mPromise.reject(ERROR_UNABLE_TO_LOAD, "External storage pictures directory not available");
File exportDir = (mType == MediaType.PHOTO)
? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
: Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
exportDir.mkdirs();
if (!exportDir.isDirectory()) {
mPromise.reject(ERROR_UNABLE_TO_LOAD, "External media storage directory not available");
return;
}
File dest = new File(pictures, source.getName());
File dest = new File(exportDir, source.getName());
int n = 0;
String fullSourceName = source.getName();
String sourceName, sourceExt;
@@ -159,7 +164,7 @@ public class CameraRollManager extends ReactContextBaseJavaModule {
sourceExt = "";
}
while (!dest.createNewFile()) {
dest = new File(pictures, sourceName + "_" + (n++) + sourceExt);
dest = new File(exportDir, sourceName + "_" + (n++) + sourceExt);
}
input = new FileInputStream(source).getChannel();
output = new FileOutputStream(dest).getChannel();