cleaned up file handling

This commit is contained in:
Daniel Gultsch 2015-04-25 14:08:24 +02:00
parent 5e1492fbff
commit d07baccf97
3 changed files with 87 additions and 71 deletions

View file

@ -1,6 +1,7 @@
package eu.siacs.conversations.persistance; package eu.siacs.conversations.persistance;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -42,8 +43,7 @@ public class FileBackend {
private static int IMAGE_SIZE = 1920; private static int IMAGE_SIZE = 1920;
private SimpleDateFormat imageDateFormat = new SimpleDateFormat( private final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
"yyyyMMdd_HHmmssSSS", Locale.US);
private XmppConnectionService mXmppConnectionService; private XmppConnectionService mXmppConnectionService;
@ -110,9 +110,7 @@ public class FileBackend {
scalledW = size; scalledW = size;
scalledH = (int) (h / ((double) w / size)); scalledH = (int) (h / ((double) w / size));
} }
Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap, return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
scalledW, scalledH, true);
return scalledBitmap;
} else { } else {
return originalBitmap; return originalBitmap;
} }
@ -148,31 +146,34 @@ public class FileBackend {
} }
public DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException { public DownloadableFile copyFileToPrivateStorage(Message message, Uri uri) throws FileCopyException {
Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage");
String mime = mXmppConnectionService.getContentResolver().getType(uri);
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
message.setRelativeFilePath(message.getUuid() + "." + extension);
DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
file.getParentFile().mkdirs();
OutputStream os = null;
InputStream is = null;
try { try {
Log.d(Config.LOGTAG, "copy " + uri.toString() + " to private storage"); if (!file.createNewFile()) {
String mime = mXmppConnectionService.getContentResolver().getType(uri); throw new FileCopyException(R.string.error_io_exception);
String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mime); }
message.setRelativeFilePath(message.getUuid() + "." + extension); os = new FileOutputStream(file);
DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message); is = mXmppConnectionService.getContentResolver().openInputStream(uri);
file.getParentFile().mkdirs();
file.createNewFile();
OutputStream os = new FileOutputStream(file);
InputStream is = mXmppConnectionService.getContentResolver().openInputStream(uri);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int length; int length;
while ((length = is.read(buffer)) > 0) { while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length); os.write(buffer, 0, length);
} }
os.flush(); os.flush();
os.close();
is.close();
Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
return file;
} catch (FileNotFoundException e) {
throw new FileCopyException(R.string.error_file_not_found);
} catch (IOException e) { } catch (IOException e) {
throw new FileCopyException(R.string.error_io_exception); throw new FileCopyException(R.string.error_io_exception);
} finally {
close(os);
close(is);
} }
Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
return file;
} }
public DownloadableFile copyImageToPrivateStorage(Message message, Uri image) public DownloadableFile copyImageToPrivateStorage(Message message, Uri image)
@ -182,40 +183,41 @@ public class FileBackend {
private DownloadableFile copyImageToPrivateStorage(Message message, private DownloadableFile copyImageToPrivateStorage(Message message,
Uri image, int sampleSize) throws FileCopyException { Uri image, int sampleSize) throws FileCopyException {
DownloadableFile file = getFile(message);
file.getParentFile().mkdirs();
InputStream is = null;
OutputStream os = null;
try { try {
InputStream is = mXmppConnectionService.getContentResolver() if (!file.createNewFile()) {
.openInputStream(image); throw new FileCopyException(R.string.error_io_exception);
DownloadableFile file = getFile(message); }
file.getParentFile().mkdirs(); is = mXmppConnectionService.getContentResolver().openInputStream(image);
file.createNewFile(); os = new FileOutputStream(file);
Bitmap originalBitmap; Bitmap originalBitmap;
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
int inSampleSize = (int) Math.pow(2, sampleSize); int inSampleSize = (int) Math.pow(2, sampleSize);
Log.d(Config.LOGTAG, "reading bitmap with sample size " Log.d(Config.LOGTAG, "reading bitmap with sample size " + inSampleSize);
+ inSampleSize);
options.inSampleSize = inSampleSize; options.inSampleSize = inSampleSize;
originalBitmap = BitmapFactory.decodeStream(is, null, options); originalBitmap = BitmapFactory.decodeStream(is, null, options);
is.close(); is.close();
if (originalBitmap == null) { if (originalBitmap == null) {
throw new FileCopyException(R.string.error_not_an_image_file); throw new FileCopyException(R.string.error_not_an_image_file);
} }
Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE); Bitmap scaledBitmap = resize(originalBitmap, IMAGE_SIZE);
originalBitmap = null;
int rotation = getRotation(image); int rotation = getRotation(image);
if (rotation > 0) { if (rotation > 0) {
scalledBitmap = rotate(scalledBitmap, rotation); scaledBitmap = rotate(scaledBitmap, rotation);
} }
OutputStream os = new FileOutputStream(file);
boolean success = scalledBitmap.compress( boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os);
Bitmap.CompressFormat.WEBP, 75, os);
if (!success) { if (!success) {
throw new FileCopyException(R.string.error_compressing_image); throw new FileCopyException(R.string.error_compressing_image);
} }
os.flush(); os.flush();
os.close();
long size = file.getSize(); long size = file.getSize();
int width = scalledBitmap.getWidth(); int width = scaledBitmap.getWidth();
int height = scalledBitmap.getHeight(); int height = scaledBitmap.getHeight();
message.setBody(Long.toString(size) + ',' + width + ',' + height); message.setBody(Long.toString(size) + ',' + width + ',' + height);
return file; return file;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
@ -223,8 +225,7 @@ public class FileBackend {
} catch (IOException e) { } catch (IOException e) {
throw new FileCopyException(R.string.error_io_exception); throw new FileCopyException(R.string.error_io_exception);
} catch (SecurityException e) { } catch (SecurityException e) {
throw new FileCopyException( throw new FileCopyException(R.string.error_security_exception_during_image_copy);
R.string.error_security_exception_during_image_copy);
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
++sampleSize; ++sampleSize;
if (sampleSize <= 3) { if (sampleSize <= 3) {
@ -232,23 +233,24 @@ public class FileBackend {
} else { } else {
throw new FileCopyException(R.string.error_out_of_memory); throw new FileCopyException(R.string.error_out_of_memory);
} }
} finally {
close(os);
close(is);
} }
} }
private int getRotation(Uri image) { private int getRotation(Uri image) {
InputStream is = null;
try { try {
InputStream is = mXmppConnectionService.getContentResolver() is = mXmppConnectionService.getContentResolver().openInputStream(image);
.openInputStream(image);
return ExifHelper.getOrientation(is); return ExifHelper.getOrientation(is);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
return 0; return 0;
} finally {
close(is);
} }
} }
public Bitmap getImageFromMessage(Message message) {
return BitmapFactory.decodeFile(getFile(message).getAbsolutePath());
}
public Bitmap getThumbnail(Message message, int size, boolean cacheOnly) public Bitmap getThumbnail(Message message, int size, boolean cacheOnly)
throws FileNotFoundException { throws FileNotFoundException {
Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get( Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(
@ -257,8 +259,7 @@ public class FileBackend {
File file = getFile(message); File file = getFile(message);
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(file, size); options.inSampleSize = calcSampleSize(file, size);
Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(), Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
options);
if (fullsize == null) { if (fullsize == null) {
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
@ -271,13 +272,11 @@ public class FileBackend {
public Uri getTakePhotoUri() { public Uri getTakePhotoUri() {
StringBuilder pathBuilder = new StringBuilder(); StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(Environment pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
pathBuilder.append('/'); pathBuilder.append('/');
pathBuilder.append("Camera"); pathBuilder.append("Camera");
pathBuilder.append('/'); pathBuilder.append('/');
pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) + ".jpg");
+ ".jpg");
Uri uri = Uri.parse("file://" + pathBuilder.toString()); Uri uri = Uri.parse("file://" + pathBuilder.toString());
File file = new File(uri.toString()); File file = new File(uri.toString());
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
@ -325,13 +324,13 @@ public class FileBackend {
String filename = getAvatarPath(avatar.getFilename()); String filename = getAvatarPath(avatar.getFilename());
file = new File(filename + ".tmp"); file = new File(filename + ".tmp");
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
OutputStream os = null;
try { try {
file.createNewFile(); file.createNewFile();
FileOutputStream mFileOutputStream = new FileOutputStream(file); os = new FileOutputStream(file);
MessageDigest digest = MessageDigest.getInstance("SHA-1"); MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset(); digest.reset();
DigestOutputStream mDigestOutputStream = new DigestOutputStream( DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest);
mFileOutputStream, digest);
mDigestOutputStream.write(avatar.getImageAsBytes()); mDigestOutputStream.write(avatar.getImageAsBytes());
mDigestOutputStream.flush(); mDigestOutputStream.flush();
mDigestOutputStream.close(); mDigestOutputStream.close();
@ -349,6 +348,8 @@ public class FileBackend {
return false; return false;
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
return false; return false;
} finally {
close(os);
} }
} }
avatar.size = file.length(); avatar.size = file.length();
@ -356,8 +357,7 @@ public class FileBackend {
} }
public String getAvatarPath(String avatar) { public String getAvatarPath(String avatar) {
return mXmppConnectionService.getFilesDir().getAbsolutePath() return mXmppConnectionService.getFilesDir().getAbsolutePath()+ "/avatars/" + avatar;
+ "/avatars/" + avatar;
} }
public Uri getAvatarUri(String avatar) { public Uri getAvatarUri(String avatar) {
@ -368,10 +368,11 @@ public class FileBackend {
if (image == null) { if (image == null) {
return null; return null;
} }
InputStream is = null;
try { try {
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(image, size); options.inSampleSize = calcSampleSize(image, size);
InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image); is = mXmppConnectionService.getContentResolver().openInputStream(image);
Bitmap input = BitmapFactory.decodeStream(is, null, options); Bitmap input = BitmapFactory.decodeStream(is, null, options);
if (input == null) { if (input == null) {
return null; return null;
@ -384,6 +385,8 @@ public class FileBackend {
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
return null; return null;
} finally {
close(is);
} }
} }
@ -391,10 +394,11 @@ public class FileBackend {
if (image == null) { if (image == null) {
return null; return null;
} }
InputStream is = null;
try { try {
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth)); options.inSampleSize = calcSampleSize(image,Math.max(newHeight, newWidth));
InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image); is = mXmppConnectionService.getContentResolver().openInputStream(image);
Bitmap source = BitmapFactory.decodeStream(is, null, options); Bitmap source = BitmapFactory.decodeStream(is, null, options);
int sourceWidth = source.getWidth(); int sourceWidth = source.getWidth();
@ -414,8 +418,11 @@ public class FileBackend {
return dest; return dest;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
return null; return null;
} catch (IOException e) {
return null;
} finally {
close(is);
} }
} }
public Bitmap cropCenterSquare(Bitmap input, int size) { public Bitmap cropCenterSquare(Bitmap input, int size) {
@ -522,4 +529,13 @@ public class FileBackend {
public boolean isFileAvailable(Message message) { public boolean isFileAvailable(Message message) {
return getFile(message).exists(); return getFile(message).exists();
} }
public static void close(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
}
}
}
} }

View file

@ -11,6 +11,7 @@ import android.util.Base64;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.OnIqPacketReceived;
@ -172,6 +173,7 @@ public class JingleInbandTransport extends JingleTransport {
connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100)); connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
} }
} catch (IOException e) { } catch (IOException e) {
FileBackend.close(fileInputStream);
this.onFileTransmissionStatusChanged.onFileTransferAborted(); this.onFileTransmissionStatusChanged.onFileTransferAborted();
} }
} }
@ -198,6 +200,7 @@ public class JingleInbandTransport extends JingleTransport {
connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100)); connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100));
} }
} catch (IOException e) { } catch (IOException e) {
FileBackend.close(fileOutputStream);
this.onFileTransmissionStatusChanged.onFileTransferAborted(); this.onFileTransmissionStatusChanged.onFileTransferAborted();
} }
} }

View file

@ -11,6 +11,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
public class JingleSocks5Transport extends JingleTransport { public class JingleSocks5Transport extends JingleTransport {
@ -126,25 +127,19 @@ public class JingleSocks5Transport extends JingleTransport {
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
callback.onFileTransferAborted(); callback.onFileTransferAborted();
} finally { } finally {
try { FileBackend.close(fileInputStream);
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
callback.onFileTransferAborted();
}
} }
} }
}).start(); }).start();
} }
public void receive(final DownloadableFile file, public void receive(final DownloadableFile file, final OnFileTransmissionStatusChanged callback) {
final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
OutputStream fileOutputStream = null;
try { try {
MessageDigest digest = MessageDigest.getInstance("SHA-1"); MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset(); digest.reset();
@ -152,7 +147,7 @@ public class JingleSocks5Transport extends JingleTransport {
socket.setSoTimeout(30000); socket.setSoTimeout(30000);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
file.createNewFile(); file.createNewFile();
OutputStream fileOutputStream = file.createOutputStream(); fileOutputStream = file.createOutputStream();
if (fileOutputStream == null) { if (fileOutputStream == null) {
callback.onFileTransferAborted(); callback.onFileTransferAborted();
return; return;
@ -183,6 +178,8 @@ public class JingleSocks5Transport extends JingleTransport {
callback.onFileTransferAborted(); callback.onFileTransferAborted();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
callback.onFileTransferAborted(); callback.onFileTransferAborted();
} finally {
FileBackend.close(fileOutputStream);
} }
} }
}).start(); }).start();