aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/persistance
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/persistance')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java90
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/persistance/FileBackend.java154
2 files changed, 176 insertions, 68 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java b/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
index bee19e4f..21eaf476 100644
--- a/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/DatabaseBackend.java
@@ -4,11 +4,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import de.thedevstack.conversationsplus.Config;
import de.thedevstack.conversationsplus.entities.Account;
import de.thedevstack.conversationsplus.entities.Contact;
import de.thedevstack.conversationsplus.entities.Conversation;
import de.thedevstack.conversationsplus.entities.Message;
import de.thedevstack.conversationsplus.entities.Roster;
+import de.thedevstack.conversationsplus.xmpp.jid.InvalidJidException;
import de.thedevstack.conversationsplus.xmpp.jid.Jid;
import android.content.Context;
@@ -16,13 +18,14 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteCantOpenDatabaseException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
public class DatabaseBackend extends SQLiteOpenHelper {
private static DatabaseBackend instance = null;
private static final String DATABASE_NAME = "history";
- private static final int DATABASE_VERSION = 13;
+ private static final int DATABASE_VERSION = 14;
private static String CREATE_CONTATCS_STATEMENT = "create table "
+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -130,6 +133,88 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL("delete from "+Contact.TABLENAME);
db.execSQL("update "+Account.TABLENAME+" set "+Account.ROSTERVERSION+" = NULL");
}
+ if (oldVersion < 14 && newVersion >= 14) {
+ // migrate db to new, canonicalized JID domainpart representation
+
+ // Conversation table
+ Cursor cursor = db.rawQuery("select * from " + Conversation.TABLENAME, new String[0]);
+ while(cursor.moveToNext()) {
+ String newJid;
+ try {
+ newJid = Jid.fromString(
+ cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
+ ).toString();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Conversation CONTACTJID "
+ +cursor.getString(cursor.getColumnIndex(Conversation.CONTACTJID))
+ +": " + ignored +". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newJid,
+ cursor.getString(cursor.getColumnIndex(Conversation.UUID)),
+ };
+ db.execSQL("update " + Conversation.TABLENAME
+ + " set " + Conversation.CONTACTJID + " = ? "
+ + " where " + Conversation.UUID + " = ?", updateArgs);
+ }
+ cursor.close();
+
+ // Contact table
+ cursor = db.rawQuery("select * from " + Contact.TABLENAME, new String[0]);
+ while(cursor.moveToNext()) {
+ String newJid;
+ try {
+ newJid = Jid.fromString(
+ cursor.getString(cursor.getColumnIndex(Contact.JID))
+ ).toString();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Contact JID "
+ +cursor.getString(cursor.getColumnIndex(Contact.JID))
+ +": " + ignored +". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newJid,
+ cursor.getString(cursor.getColumnIndex(Contact.ACCOUNT)),
+ cursor.getString(cursor.getColumnIndex(Contact.JID)),
+ };
+ db.execSQL("update " + Contact.TABLENAME
+ + " set " + Contact.JID + " = ? "
+ + " where " + Contact.ACCOUNT + " = ? "
+ + " AND " + Contact.JID + " = ?", updateArgs);
+ }
+ cursor.close();
+
+ // Account table
+ cursor = db.rawQuery("select * from " + Account.TABLENAME, new String[0]);
+ while(cursor.moveToNext()) {
+ String newServer;
+ try {
+ newServer = Jid.fromParts(
+ cursor.getString(cursor.getColumnIndex(Account.USERNAME)),
+ cursor.getString(cursor.getColumnIndex(Account.SERVER)),
+ "mobile"
+ ).getDomainpart();
+ } catch (InvalidJidException ignored) {
+ Log.e(Config.LOGTAG, "Failed to migrate Account SERVER "
+ +cursor.getString(cursor.getColumnIndex(Account.SERVER))
+ +": " + ignored +". Skipping...");
+ continue;
+ }
+
+ String updateArgs[] = {
+ newServer,
+ cursor.getString(cursor.getColumnIndex(Account.UUID)),
+ };
+ db.execSQL("update " + Account.TABLENAME
+ + " set " + Account.SERVER + " = ? "
+ + " where " + Account.UUID + " = ?", updateArgs);
+ }
+ cursor.close();
+ }
}
public static synchronized DatabaseBackend getInstance(Context context) {
@@ -301,8 +386,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor;
String args[] = { roster.getAccount().getUuid() };
- cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?",
- args, null, null, null);
+ cursor = db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", args, null, null, null);
while (cursor.moveToNext()) {
roster.initContact(Contact.fromCursor(cursor));
}
diff --git a/src/main/java/de/thedevstack/conversationsplus/persistance/FileBackend.java b/src/main/java/de/thedevstack/conversationsplus/persistance/FileBackend.java
index e3bf58c7..3a245d62 100644
--- a/src/main/java/de/thedevstack/conversationsplus/persistance/FileBackend.java
+++ b/src/main/java/de/thedevstack/conversationsplus/persistance/FileBackend.java
@@ -1,6 +1,7 @@
package de.thedevstack.conversationsplus.persistance;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -12,6 +13,7 @@ import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
@@ -31,6 +33,7 @@ import android.webkit.MimeTypeMap;
import de.thedevstack.conversationsplus.Config;
import de.thedevstack.conversationsplus.R;
+import de.thedevstack.conversationsplus.entities.Transferable;
import de.thedevstack.conversationsplus.entities.DownloadableFile;
import de.thedevstack.conversationsplus.entities.Message;
import de.thedevstack.conversationsplus.services.XmppConnectionService;
@@ -42,8 +45,7 @@ public class FileBackend {
private static int IMAGE_SIZE = 1920;
- private SimpleDateFormat imageDateFormat = new SimpleDateFormat(
- "yyyyMMdd_HHmmssSSS", Locale.US);
+ private final SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
private XmppConnectionService mXmppConnectionService;
@@ -78,10 +80,10 @@ public class FileBackend {
if (path.startsWith("/")) {
return new DownloadableFile(path);
} else {
- if (message.getType() == Message.TYPE_FILE) {
+ if (Arrays.asList(Transferable.VALID_IMAGE_EXTENSIONS).contains(extension)) {
return new DownloadableFile(getConversationsFileDirectory() + path);
} else {
- return new DownloadableFile(getConversationsImageDirectory()+path);
+ return new DownloadableFile(getConversationsImageDirectory() + path);
}
}
}
@@ -110,9 +112,7 @@ public class FileBackend {
scalledW = size;
scalledH = (int) (h / ((double) w / size));
}
- Bitmap scalledBitmap = Bitmap.createScaledBitmap(originalBitmap,
- scalledW, scalledH, true);
- return scalledBitmap;
+ return Bitmap.createScaledBitmap(originalBitmap, scalledW, scalledH, true);
} else {
return originalBitmap;
}
@@ -148,31 +148,35 @@ public class FileBackend {
}
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 {
- 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();
file.createNewFile();
- OutputStream os = new FileOutputStream(file);
- InputStream is = mXmppConnectionService.getContentResolver().openInputStream(uri);
+ os = new FileOutputStream(file);
+ is = mXmppConnectionService.getContentResolver().openInputStream(uri);
byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
+ int length;
+ while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
- }
+ }
os.flush();
- os.close();
- is.close();
- Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
- return file;
- } catch (FileNotFoundException e) {
+ } 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 {
+ close(os);
+ close(is);
}
+ Log.d(Config.LOGTAG, "output file name " + mXmppConnectionService.getFileBackend().getFile(message));
+ return file;
}
public DownloadableFile copyImageToPrivateStorage(Message message, Uri image)
@@ -182,49 +186,48 @@ public class FileBackend {
private DownloadableFile copyImageToPrivateStorage(Message message,
Uri image, int sampleSize) throws FileCopyException {
+ DownloadableFile file = getFile(message);
+ file.getParentFile().mkdirs();
+ InputStream is = null;
+ OutputStream os = null;
try {
- InputStream is = mXmppConnectionService.getContentResolver()
- .openInputStream(image);
- DownloadableFile file = getFile(message);
- file.getParentFile().mkdirs();
file.createNewFile();
+ is = mXmppConnectionService.getContentResolver().openInputStream(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);
+ 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 scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
- originalBitmap = null;
+ Bitmap scaledBitmap = resize(originalBitmap, IMAGE_SIZE);
int rotation = getRotation(image);
if (rotation > 0) {
- scalledBitmap = rotate(scalledBitmap, rotation);
+ scaledBitmap = rotate(scaledBitmap, rotation);
}
- OutputStream os = new FileOutputStream(file);
- boolean success = scalledBitmap.compress(
- Bitmap.CompressFormat.WEBP, 75, os);
+
+ boolean success = scaledBitmap.compress(Bitmap.CompressFormat.WEBP, 75, os);
if (!success) {
throw new FileCopyException(R.string.error_compressing_image);
}
os.flush();
- os.close();
long size = file.getSize();
- int width = scalledBitmap.getWidth();
- int height = scalledBitmap.getHeight();
- message.setBody(Long.toString(size) + ',' + width + ',' + height);
+ 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);
+ throw new FileCopyException(R.string.error_security_exception_during_image_copy);
} catch (OutOfMemoryError e) {
++sampleSize;
if (sampleSize <= 3) {
@@ -232,23 +235,26 @@ public class FileBackend {
} else {
throw new FileCopyException(R.string.error_out_of_memory);
}
+ } catch (NullPointerException e) {
+ throw new FileCopyException(R.string.error_io_exception);
+ } finally {
+ close(os);
+ close(is);
}
}
private int getRotation(Uri image) {
+ InputStream is = null;
try {
- InputStream is = mXmppConnectionService.getContentResolver()
- .openInputStream(image);
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
return ExifHelper.getOrientation(is);
} catch (FileNotFoundException e) {
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)
throws FileNotFoundException {
Bitmap thumbnail = mXmppConnectionService.getBitmapCache().get(
@@ -257,8 +263,7 @@ public class FileBackend {
File file = getFile(message);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(file, size);
- Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),
- options);
+ Bitmap fullsize = BitmapFactory.decodeFile(file.getAbsolutePath(),options);
if (fullsize == null) {
throw new FileNotFoundException();
}
@@ -271,13 +276,11 @@ public class FileBackend {
public Uri getTakePhotoUri() {
StringBuilder pathBuilder = new StringBuilder();
- pathBuilder.append(Environment
- .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
+ pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
pathBuilder.append('/');
pathBuilder.append("Camera");
pathBuilder.append('/');
- pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date())
- + ".jpg");
+ pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date()) + ".jpg");
Uri uri = Uri.parse("file://" + pathBuilder.toString());
File file = new File(uri.toString());
file.getParentFile().mkdirs();
@@ -325,13 +328,13 @@ public class FileBackend {
String filename = getAvatarPath(avatar.getFilename());
file = new File(filename + ".tmp");
file.getParentFile().mkdirs();
+ OutputStream os = null;
try {
file.createNewFile();
- FileOutputStream mFileOutputStream = new FileOutputStream(file);
+ os = new FileOutputStream(file);
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
- DigestOutputStream mDigestOutputStream = new DigestOutputStream(
- mFileOutputStream, digest);
+ DigestOutputStream mDigestOutputStream = new DigestOutputStream(os, digest);
mDigestOutputStream.write(avatar.getImageAsBytes());
mDigestOutputStream.flush();
mDigestOutputStream.close();
@@ -349,6 +352,8 @@ public class FileBackend {
return false;
} catch (NoSuchAlgorithmException e) {
return false;
+ } finally {
+ close(os);
}
}
avatar.size = file.length();
@@ -356,8 +361,7 @@ public class FileBackend {
}
public String getAvatarPath(String avatar) {
- return mXmppConnectionService.getFilesDir().getAbsolutePath()
- + "/avatars/" + avatar;
+ return mXmppConnectionService.getFilesDir().getAbsolutePath()+ "/avatars/" + avatar;
}
public Uri getAvatarUri(String avatar) {
@@ -368,10 +372,11 @@ public class FileBackend {
if (image == null) {
return null;
}
+ InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = calcSampleSize(image, size);
- InputStream is = mXmppConnectionService.getContentResolver().openInputStream(image);
+ is = mXmppConnectionService.getContentResolver().openInputStream(image);
Bitmap input = BitmapFactory.decodeStream(is, null, options);
if (input == null) {
return null;
@@ -384,6 +389,8 @@ public class FileBackend {
}
} catch (FileNotFoundException e) {
return null;
+ } finally {
+ close(is);
}
}
@@ -391,12 +398,15 @@ public class FileBackend {
if (image == null) {
return null;
}
+ InputStream is = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
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);
-
+ if (source == null) {
+ return null;
+ }
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
float xScale = (float) newWidth / sourceWidth;
@@ -408,14 +418,15 @@ public class FileBackend {
float top = (newHeight - scaledHeight) / 2;
RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
- Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
+ Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
return dest;
} catch (FileNotFoundException e) {
return null;
+ } finally {
+ close(is);
}
-
}
public Bitmap cropCenterSquare(Bitmap input, int size) {
@@ -430,7 +441,7 @@ public class FileBackend {
float top = (size - outHeight) / 2;
RectF target = new RectF(left, top, left + outWidth, top + outHeight);
- Bitmap output = Bitmap.createBitmap(size, size, input.getConfig());
+ Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawBitmap(input, null, target, null);
return output;
@@ -490,7 +501,11 @@ public class FileBackend {
message.setBody(url.toString()+"|"+Long.toString(file.getSize()) + '|' + imageWidth + '|' + imageHeight);
}
} else {
- message.setBody(Long.toString(file.getSize()));
+ if (url != null) {
+ message.setBody(url.toString()+"|"+Long.toString(file.getSize()));
+ } else {
+ message.setBody(Long.toString(file.getSize()));
+ }
}
}
@@ -522,4 +537,13 @@ public class FileBackend {
public boolean isFileAvailable(Message message) {
return getFile(message).exists();
}
+
+ public static void close(Closeable stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
}