diff options
Diffstat (limited to 'src/main/java/eu/siacs/conversations/persistance/FileBackend.java')
-rw-r--r-- | src/main/java/eu/siacs/conversations/persistance/FileBackend.java | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java new file mode 100644 index 00000000..a90e14e6 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -0,0 +1,233 @@ +package eu.siacs.conversations.persistance; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.Locale; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Environment; +import android.util.Log; +import android.webkit.MimeTypeMap; + +import de.thedevstack.conversationsplus.ConversationsPlusApplication; +import de.thedevstack.conversationsplus.exceptions.FileCopyException; +import de.thedevstack.conversationsplus.utils.ImageUtil; +import de.thedevstack.conversationsplus.utils.StreamUtil; + +import eu.siacs.conversations.Config; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Transferable; +import eu.siacs.conversations.entities.DownloadableFile; +import eu.siacs.conversations.entities.Message; + +public final class FileBackend { + + private static int IMAGE_SIZE = 1920; + + private static final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US); + + public static DownloadableFile getFile(Message message) { + return getFile(message, true); + } + + public static DownloadableFile getFile(Message message, boolean decrypted) { + String path = message.getRelativeFilePath(); + String extension; + if (path != null && !path.isEmpty()) { + String[] parts = path.split("\\."); + extension = "."+parts[parts.length - 1]; + } else { + if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_TEXT) { + extension = ".webp"; + } else { + extension = ""; + } + path = message.getUuid()+extension; + } + final boolean encrypted = !decrypted + && (message.getEncryption() == Message.ENCRYPTION_PGP + || message.getEncryption() == Message.ENCRYPTION_DECRYPTED); + if (encrypted) { + return new DownloadableFile(getConversationsFileDirectory()+message.getUuid()+extension+".pgp"); + } else { + if (path.startsWith("/")) { + return new DownloadableFile(path); + } else { + if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)) { + return new DownloadableFile(getConversationsFileDirectory() + path); + } else { + return new DownloadableFile(getConversationsImageDirectory() + path); + } + } + } + } + + public static String getConversationsFileDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/"; + } + + public static String getConversationsImageDirectory() { + return Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES).getAbsolutePath() + + "/Conversations/"; + } + + public static DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException { + Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage"); + String mime = ConversationsPlusApplication.getInstance().getContentResolver().getType(uri); + String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime); + message.setRelativeFilePath(message.getUuid() + "." + extension); + DownloadableFile file = getFile(message); + file.getParentFile().mkdirs(); + OutputStream os = null; + InputStream is = null; + try { + file.createNewFile(); + os = new FileOutputStream(file); + is = StreamUtil.openInputStreamFromContentResolver(uri); + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) > 0) { + os.write(buffer, 0, length); + } + os.flush(); + } catch(FileNotFoundException e) { + throw new FileCopyException(R.string.error_file_not_found); + } catch (IOException e) { + e.printStackTrace(); + throw new FileCopyException(R.string.error_io_exception); + } finally { + StreamUtil.close(os); + StreamUtil.close(is); + } + Log.d(Config.LOGTAG, "output file name " + file); + return file; + } + + public static DownloadableFile copyImageToPrivateStorage(Message message, Uri image) + throws FileCopyException { + return copyImageToPrivateStorage(message, image, 0); + } + + private static DownloadableFile copyImageToPrivateStorage(Message message, + Uri image, int sampleSize) throws FileCopyException { + DownloadableFile file = getFile(message); + file.getParentFile().mkdirs(); + InputStream is = null; + OutputStream os = null; + try { + file.createNewFile(); + is = StreamUtil.openInputStreamFromContentResolver(image); + os = new FileOutputStream(file); + + Bitmap originalBitmap; + BitmapFactory.Options options = new BitmapFactory.Options(); + int inSampleSize = (int) Math.pow(2, sampleSize); + Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize); + options.inSampleSize = inSampleSize; + originalBitmap = BitmapFactory.decodeStream(is, null, options); + is.close(); + if (originalBitmap == null) { + throw new FileCopyException(R.string.error_not_an_image_file); + } + Bitmap scaledBitmap = ImageUtil.resize(originalBitmap, IMAGE_SIZE); + int rotation = ImageUtil.getRotation(image); + if (rotation > 0) { + scaledBitmap = ImageUtil.rotate(scaledBitmap, rotation); + } + + boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os); + if (!success) { + throw new FileCopyException(R.string.error_compressing_image); + } + os.flush(); + long size = file.getSize(); + int width = scaledBitmap.getWidth(); + int height = scaledBitmap.getHeight(); + message.setBody(Long.toString(size) + '|' + width + '|' + height); + return file; + } catch (FileNotFoundException e) { + throw new FileCopyException(R.string.error_file_not_found); + } catch (IOException e) { + e.printStackTrace(); + throw new FileCopyException(R.string.error_io_exception); + } catch (SecurityException e) { + throw new FileCopyException(R.string.error_security_exception_during_image_copy); + } catch (OutOfMemoryError e) { + ++sampleSize; + if (sampleSize <= 3) { + return copyImageToPrivateStorage(message, image, sampleSize); + } else { + throw new FileCopyException(R.string.error_out_of_memory); + } + } catch (NullPointerException e) { + throw new FileCopyException(R.string.error_io_exception); + } finally { + StreamUtil.close(os); + StreamUtil.close(is); + } + } + + public static Uri getTakePhotoUri() { + StringBuilder pathBuilder = new StringBuilder(); + pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)); + pathBuilder.append('/'); + pathBuilder.append("Camera"); + pathBuilder.append('/'); + pathBuilder.append("IMG_" + imageDateFormat.format(new Date()) + ".jpg"); + Uri uri = Uri.parse("file://" + pathBuilder.toString()); + File file = new File(uri.toString()); + file.getParentFile().mkdirs(); + return uri; + } + + public static Uri getJingleFileUri(Message message) { + File file = getFile(message); + return Uri.parse("file://" + file.getAbsolutePath()); + } + + public static void updateFileParams(Message message) { + updateFileParams(message,null); + } + + public static void updateFileParams(Message message, URL url) { + DownloadableFile file = getFile(message); + if (message.getType() == Message.TYPE_IMAGE || file.getMimeType().startsWith("image/")) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + int imageHeight = options.outHeight; + int imageWidth = options.outWidth; + if (url == null) { + message.setBody(Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); + } else { + message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight); + } + } else { + if (url != null) { + message.setBody(url.toString()+"|"+Long.toString(file.getSize())); + } else { + message.setBody(Long.toString(file.getSize())); + } + } + + } + + public static boolean isFileAvailable(Message message) { + return getFile(message).exists(); + } + + private FileBackend() { + // Static helper class + } +} |