306 lines
11 KiB
Java
306 lines
11 KiB
Java
package io.lbry.browser.reactmodules;
|
|
|
|
import android.content.Context;
|
|
import android.content.ContentResolver;
|
|
import android.database.Cursor;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.Manifest;
|
|
import android.media.ThumbnailUtils;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.provider.MediaStore;
|
|
|
|
import com.facebook.react.bridge.Arguments;
|
|
import com.facebook.react.bridge.Promise;
|
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
import com.facebook.react.bridge.ReactMethod;
|
|
import com.facebook.react.bridge.WritableArray;
|
|
import com.facebook.react.bridge.WritableMap;
|
|
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
|
|
import io.lbry.browser.MainActivity;
|
|
import io.lbry.browser.Utils;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
import java.util.ArrayList;
|
|
|
|
public class GalleryModule extends ReactContextBaseJavaModule {
|
|
private Context context;
|
|
|
|
public GalleryModule(ReactApplicationContext reactContext) {
|
|
super(reactContext);
|
|
this.context = reactContext;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "Gallery";
|
|
}
|
|
|
|
@ReactMethod
|
|
public void getVideos(Promise promise) {
|
|
WritableArray items = Arguments.createArray();
|
|
List<GalleryItem> videos = loadVideos();
|
|
for (int i = 0; i < videos.size(); i++) {
|
|
items.pushMap(videos.get(i).toMap());
|
|
}
|
|
|
|
promise.resolve(items);
|
|
}
|
|
|
|
@ReactMethod
|
|
public void getThumbnailPath(Promise promise) {
|
|
if (context != null) {
|
|
File cacheDir = context.getExternalCacheDir();
|
|
String thumbnailPath = String.format("%s/thumbnails", cacheDir.getAbsolutePath());
|
|
promise.resolve(thumbnailPath);
|
|
return;
|
|
}
|
|
|
|
promise.resolve(null);
|
|
}
|
|
|
|
@ReactMethod
|
|
public void getUploadsPath(Promise promise) {
|
|
if (context != null) {
|
|
String baseFolder = Utils.getExternalStorageDir(context);
|
|
String uploadsPath = String.format("%s/LBRY/Uploads", baseFolder);
|
|
File uploadsDir = new File(uploadsPath);
|
|
if (!uploadsDir.isDirectory()) {
|
|
uploadsDir.mkdirs();
|
|
}
|
|
promise.resolve(uploadsPath);
|
|
}
|
|
|
|
promise.reject("The content could not be saved to the device. Please check your storage permissions.");
|
|
}
|
|
|
|
@ReactMethod
|
|
public void createVideoThumbnail(String targetId, String filePath, Promise promise) {
|
|
(new AsyncTask<Void, Void, String>() {
|
|
protected String doInBackground(Void... param) {
|
|
String thumbnailPath = null;
|
|
|
|
if (context != null) {
|
|
Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
|
|
File cacheDir = context.getExternalCacheDir();
|
|
thumbnailPath = String.format("%s/thumbnails/%s.png", cacheDir.getAbsolutePath(), targetId);
|
|
|
|
File file = new File(thumbnailPath);
|
|
try (FileOutputStream os = new FileOutputStream(thumbnailPath)) {
|
|
thumbnail.compress(Bitmap.CompressFormat.PNG, 80, os);
|
|
os.close();
|
|
} catch (IOException ex) {
|
|
promise.reject("Could not create a thumbnail for the video");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return thumbnailPath;
|
|
}
|
|
|
|
public void onPostExecute(String thumbnailPath) {
|
|
if (thumbnailPath != null && thumbnailPath.trim().length() > 0) {
|
|
promise.resolve(thumbnailPath);
|
|
}
|
|
}
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
}
|
|
|
|
@ReactMethod
|
|
public void createImageThumbnail(String targetId, String filePath, Promise promise) {
|
|
(new AsyncTask<Void, Void, String>() {
|
|
protected String doInBackground(Void... param) {
|
|
String thumbnailPath = null;
|
|
FileOutputStream os = null;
|
|
try {
|
|
Bitmap source = BitmapFactory.decodeFile(filePath);
|
|
// MINI_KIND dimensions
|
|
Bitmap thumbnail = Bitmap.createScaledBitmap(source, 512, 384, false);
|
|
|
|
if (context != null) {
|
|
File cacheDir = context.getExternalCacheDir();
|
|
thumbnailPath = String.format("%s/thumbnails/%s.png", cacheDir.getAbsolutePath(), targetId);
|
|
os = new FileOutputStream(thumbnailPath);
|
|
if (thumbnail != null) {
|
|
thumbnail.compress(Bitmap.CompressFormat.PNG, 80, os);
|
|
}
|
|
os.close();
|
|
}
|
|
} catch (IOException ex) {
|
|
promise.reject("Could not create a thumbnail for the image");
|
|
return null;
|
|
} finally {
|
|
if (os != null) {
|
|
try {
|
|
os.close();
|
|
} catch (IOException ex) {
|
|
// ignoe
|
|
}
|
|
}
|
|
}
|
|
|
|
return thumbnailPath;
|
|
}
|
|
|
|
public void onPostExecute(String thumbnailPath) {
|
|
if (thumbnailPath != null && thumbnailPath.trim().length() > 0) {
|
|
promise.resolve(thumbnailPath);
|
|
}
|
|
}
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
}
|
|
|
|
private List<GalleryItem> loadVideos() {
|
|
String[] projection = {
|
|
MediaStore.MediaColumns._ID,
|
|
MediaStore.MediaColumns.DATA,
|
|
MediaStore.MediaColumns.DISPLAY_NAME,
|
|
MediaStore.MediaColumns.MIME_TYPE,
|
|
MediaStore.Video.Media.DURATION
|
|
};
|
|
|
|
List<String> ids = new ArrayList<String>();
|
|
List<GalleryItem> items = new ArrayList<GalleryItem>();
|
|
Cursor cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null,
|
|
String.format("%s DESC", MediaStore.MediaColumns.DATE_MODIFIED));
|
|
while (cursor.moveToNext()) {
|
|
int idColumn = cursor.getColumnIndex(MediaStore.MediaColumns._ID);
|
|
int nameColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
|
|
int typeColumn = cursor.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE);
|
|
int pathColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
|
|
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
|
|
|
|
String id = cursor.getString(idColumn);
|
|
GalleryItem item = new GalleryItem();
|
|
item.setId(id);
|
|
item.setName(cursor.getString(nameColumn));
|
|
item.setType(cursor.getString(typeColumn));
|
|
item.setFilePath(cursor.getString(pathColumn));
|
|
items.add(item);
|
|
ids.add(id);
|
|
}
|
|
|
|
checkThumbnails(ids);
|
|
|
|
return items;
|
|
}
|
|
|
|
private void checkThumbnails(final List<String> ids) {
|
|
(new AsyncTask<Void, Void, Void>() {
|
|
protected Void doInBackground(Void... param) {
|
|
if (context != null) {
|
|
ContentResolver resolver = context.getContentResolver();
|
|
for (int i = 0; i < ids.size(); i++) {
|
|
String id = ids.get(i);
|
|
File cacheDir = context.getExternalCacheDir();
|
|
File thumbnailsDir = new File(String.format("%s/thumbnails", cacheDir.getAbsolutePath()));
|
|
if (!thumbnailsDir.isDirectory()) {
|
|
thumbnailsDir.mkdirs();
|
|
}
|
|
|
|
String thumbnailPath = String.format("%s/%s.png", thumbnailsDir.getAbsolutePath(), id);
|
|
File file = new File(thumbnailPath);
|
|
if (!file.exists()) {
|
|
// save the thumbnail to the path
|
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
options.inSampleSize = 1;
|
|
Bitmap thumbnail = MediaStore.Video.Thumbnails.getThumbnail(
|
|
resolver, Long.parseLong(id), MediaStore.Video.Thumbnails.MINI_KIND, options);
|
|
if (thumbnail != null) {
|
|
try (FileOutputStream os = new FileOutputStream(thumbnailPath)) {
|
|
thumbnail.compress(Bitmap.CompressFormat.PNG, 80, os);
|
|
} catch (IOException ex) {
|
|
// skip
|
|
}
|
|
}
|
|
}
|
|
|
|
if (file.exists() && file.length() > 0 && GalleryModule.this.context != null) {
|
|
WritableMap params = Arguments.createMap();
|
|
params.putString("id", id);
|
|
((ReactApplicationContext) GalleryModule.this.context).getJSModule(
|
|
DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("onGalleryThumbnailChecked", params);
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
}
|
|
|
|
private static class GalleryItem {
|
|
private String id;
|
|
|
|
private int duration;
|
|
|
|
private String filePath;
|
|
|
|
private String name;
|
|
|
|
private String type;
|
|
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
public void setId(String id) {
|
|
this.id = id;
|
|
}
|
|
|
|
public int getDuration() {
|
|
return duration;
|
|
}
|
|
|
|
public void setDuration(int duration) {
|
|
this.duration = duration;
|
|
}
|
|
|
|
public String getFilePath() {
|
|
return filePath;
|
|
}
|
|
|
|
public void setFilePath(String filePath) {
|
|
this.filePath = filePath;
|
|
}
|
|
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
public void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
public String getType() {
|
|
return type;
|
|
}
|
|
|
|
public void setType(String type) {
|
|
this.type = type;
|
|
}
|
|
|
|
public WritableMap toMap() {
|
|
WritableMap map = Arguments.createMap();
|
|
map.putString("id", id);
|
|
map.putString("name", name);
|
|
map.putString("filePath", filePath);
|
|
map.putString("type", type);
|
|
map.putInt("duration", duration);
|
|
|
|
return map;
|
|
}
|
|
}
|
|
|
|
@ReactMethod
|
|
public void canUseCamera(final Promise promise) {
|
|
promise.resolve(MainActivity.hasPermission(Manifest.permission.CAMERA, MainActivity.getActivity()));
|
|
}
|
|
}
|