mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Introduce unique part ID column for better cache accuracy.
Closes #3226 // FREEBIE
This commit is contained in:
parent
2cfc714b64
commit
9c2f14dade
@ -72,7 +72,7 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
|
|||||||
|
|
||||||
part.setDataUri(imageRecord.getUri());
|
part.setDataUri(imageRecord.getUri());
|
||||||
part.setContentType(imageRecord.getContentType().getBytes());
|
part.setContentType(imageRecord.getContentType().getBytes());
|
||||||
part.setId(imageRecord.getPartId());
|
part.setPartId(imageRecord.getPartId());
|
||||||
|
|
||||||
Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType());
|
Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType());
|
||||||
if (slide != null) {
|
if (slide != null) {
|
||||||
|
@ -60,7 +60,8 @@ public class DatabaseFactory {
|
|||||||
private static final int INTRODUCED_PART_DATA_SIZE_VERSION = 14;
|
private static final int INTRODUCED_PART_DATA_SIZE_VERSION = 14;
|
||||||
private static final int INTRODUCED_THUMBNAILS_VERSION = 15;
|
private static final int INTRODUCED_THUMBNAILS_VERSION = 15;
|
||||||
private static final int INTRODUCED_IDENTITY_COLUMN_VERSION = 16;
|
private static final int INTRODUCED_IDENTITY_COLUMN_VERSION = 16;
|
||||||
private static final int DATABASE_VERSION = 16;
|
private static final int INTRODUCED_UNIQUE_PART_IDS_VERSION = 17;
|
||||||
|
private static final int DATABASE_VERSION = 17;
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "messages.db";
|
private static final String DATABASE_NAME = "messages.db";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
@ -717,6 +718,10 @@ public class DatabaseFactory {
|
|||||||
db.execSQL("ALTER TABLE mms ADD COLUMN network_failures TEXT");
|
db.execSQL("ALTER TABLE mms ADD COLUMN network_failures TEXT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < INTRODUCED_UNIQUE_PART_IDS_VERSION) {
|
||||||
|
db.execSQL("ALTER TABLE part ADD COLUMN unique_id INTEGER NOT NULL DEFAULT 0");
|
||||||
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
@ -1171,11 +1171,11 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PduBody getPartsAsBody(List<Pair<Long, PduPart>> parts) {
|
private PduBody getPartsAsBody(List<PduPart> parts) {
|
||||||
PduBody body = new PduBody();
|
PduBody body = new PduBody();
|
||||||
|
|
||||||
for (Pair<Long, PduPart> part : parts) {
|
for (PduPart part : parts) {
|
||||||
body.addPart(part.second);
|
body.addPart(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -30,7 +29,6 @@ import android.util.Pair;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
|
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
|
||||||
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
|
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
@ -60,7 +58,7 @@ public class PartDatabase extends Database {
|
|||||||
private static final String TAG = PartDatabase.class.getSimpleName();
|
private static final String TAG = PartDatabase.class.getSimpleName();
|
||||||
|
|
||||||
private static final String TABLE_NAME = "part";
|
private static final String TABLE_NAME = "part";
|
||||||
private static final String ID = "_id";
|
private static final String ROW_ID = "_id";
|
||||||
private static final String MMS_ID = "mid";
|
private static final String MMS_ID = "mid";
|
||||||
private static final String SEQUENCE = "seq";
|
private static final String SEQUENCE = "seq";
|
||||||
private static final String CONTENT_TYPE = "ct";
|
private static final String CONTENT_TYPE = "ct";
|
||||||
@ -78,27 +76,28 @@ public class PartDatabase extends Database {
|
|||||||
private static final String SIZE = "data_size";
|
private static final String SIZE = "data_size";
|
||||||
private static final String THUMBNAIL = "thumbnail";
|
private static final String THUMBNAIL = "thumbnail";
|
||||||
private static final String ASPECT_RATIO = "aspect_ratio";
|
private static final String ASPECT_RATIO = "aspect_ratio";
|
||||||
|
private static final String UNIQUE_ID = "unique_id";
|
||||||
|
|
||||||
private static final String ID_CONTENT_WHERE = ID + " = ? AND " + CONTENT_ID + " = ?";
|
private static final String PART_ID_WHERE = ROW_ID + " = ? AND " + UNIQUE_ID + " = ?";
|
||||||
|
|
||||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " +
|
||||||
MMS_ID + " INTEGER, " + SEQUENCE + " INTEGER DEFAULT 0, " +
|
MMS_ID + " INTEGER, " + SEQUENCE + " INTEGER DEFAULT 0, " +
|
||||||
CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + CHARSET + " INTEGER, " +
|
CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + CHARSET + " INTEGER, " +
|
||||||
CONTENT_DISPOSITION + " TEXT, " + FILENAME + " TEXT, " + CONTENT_ID + " TEXT, " +
|
CONTENT_DISPOSITION + " TEXT, " + FILENAME + " TEXT, " + CONTENT_ID + " TEXT, " +
|
||||||
CONTENT_LOCATION + " TEXT, " + CONTENT_TYPE_START + " INTEGER, " +
|
CONTENT_LOCATION + " TEXT, " + CONTENT_TYPE_START + " INTEGER, " +
|
||||||
CONTENT_TYPE_TYPE + " TEXT, " + ENCRYPTED + " INTEGER, " +
|
CONTENT_TYPE_TYPE + " TEXT, " + ENCRYPTED + " INTEGER, " +
|
||||||
PENDING_PUSH_ATTACHMENT + " INTEGER, "+ DATA + " TEXT, " + SIZE + " INTEGER, " +
|
PENDING_PUSH_ATTACHMENT + " INTEGER, "+ DATA + " TEXT, " + SIZE + " INTEGER, " +
|
||||||
THUMBNAIL + " TEXT, " + ASPECT_RATIO + " REAL);";
|
THUMBNAIL + " TEXT, " + ASPECT_RATIO + " REAL, " + UNIQUE_ID + " INTEGER NOT NULL);";
|
||||||
|
|
||||||
public static final String[] CREATE_INDEXS = {
|
public static final String[] CREATE_INDEXS = {
|
||||||
"CREATE INDEX IF NOT EXISTS part_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
|
"CREATE INDEX IF NOT EXISTS part_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
|
||||||
"CREATE INDEX IF NOT EXISTS pending_push_index ON " + TABLE_NAME + " (" + PENDING_PUSH_ATTACHMENT + ");",
|
"CREATE INDEX IF NOT EXISTS pending_push_index ON " + TABLE_NAME + " (" + PENDING_PUSH_ATTACHMENT + ");",
|
||||||
};
|
};
|
||||||
|
|
||||||
private final static String IMAGES_QUERY = "SELECT " + TABLE_NAME + "." + ID + ", "
|
private final static String IMAGES_QUERY = "SELECT " + TABLE_NAME + "." + ROW_ID + ", "
|
||||||
+ TABLE_NAME + "." + CONTENT_TYPE + ", "
|
+ TABLE_NAME + "." + CONTENT_TYPE + ", "
|
||||||
+ TABLE_NAME + "." + ASPECT_RATIO + ", "
|
+ TABLE_NAME + "." + ASPECT_RATIO + ", "
|
||||||
+ TABLE_NAME + "." + CONTENT_ID + ", "
|
+ TABLE_NAME + "." + UNIQUE_ID + ", "
|
||||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.NORMALIZED_DATE_RECEIVED + ", "
|
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.NORMALIZED_DATE_RECEIVED + ", "
|
||||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.ADDRESS + " "
|
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.ADDRESS + " "
|
||||||
+ "FROM " + TABLE_NAME + " LEFT JOIN " + MmsDatabase.TABLE_NAME
|
+ "FROM " + TABLE_NAME + " LEFT JOIN " + MmsDatabase.TABLE_NAME
|
||||||
@ -107,7 +106,7 @@ public class PartDatabase extends Database {
|
|||||||
+ " FROM " + MmsDatabase.TABLE_NAME
|
+ " FROM " + MmsDatabase.TABLE_NAME
|
||||||
+ " WHERE " + MmsDatabase.THREAD_ID + " = ?) AND "
|
+ " WHERE " + MmsDatabase.THREAD_ID + " = ?) AND "
|
||||||
+ CONTENT_TYPE + " LIKE 'image/%' "
|
+ CONTENT_TYPE + " LIKE 'image/%' "
|
||||||
+ "ORDER BY " + TABLE_NAME + "." + ID + " DESC";
|
+ "ORDER BY " + TABLE_NAME + "." + ROW_ID + " DESC";
|
||||||
|
|
||||||
|
|
||||||
private final ExecutorService thumbnailExecutor = Util.newSingleThreadedLifoExecutor();
|
private final ExecutorService thumbnailExecutor = Util.newSingleThreadedLifoExecutor();
|
||||||
@ -116,13 +115,13 @@ public class PartDatabase extends Database {
|
|||||||
super(context, databaseHelper);
|
super(context, databaseHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getPartStream(MasterSecret masterSecret, long partId, byte[] contentId)
|
public InputStream getPartStream(MasterSecret masterSecret, PartId partId)
|
||||||
throws FileNotFoundException
|
throws FileNotFoundException
|
||||||
{
|
{
|
||||||
return getDataStream(masterSecret, partId, contentId, DATA);
|
return getDataStream(masterSecret, partId, DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateFailedDownloadedPart(long messageId, long partId, PduPart part)
|
public void updateFailedDownloadedPart(long messageId, PartId partId, PduPart part)
|
||||||
throws MmsException
|
throws MmsException
|
||||||
{
|
{
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
@ -134,16 +133,16 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
values.put(DATA, (String)null);
|
values.put(DATA, (String)null);
|
||||||
|
|
||||||
database.update(TABLE_NAME, values, ID_WHERE, new String[] {partId+""});
|
database.update(TABLE_NAME, values, PART_ID_WHERE, partId.toStrings());
|
||||||
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PduPart getPart(long partId) {
|
public PduPart getPart(PartId partId) {
|
||||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = database.query(TABLE_NAME, null, ID_WHERE, new String[] {partId+""}, null, null, null);
|
cursor = database.query(TABLE_NAME, null, PART_ID_WHERE, partId.toStrings(), null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) return getPart(cursor);
|
if (cursor != null && cursor.moveToFirst()) return getPart(cursor);
|
||||||
else return null;
|
else return null;
|
||||||
@ -161,9 +160,9 @@ public class PartDatabase extends Database {
|
|||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Pair<Long, PduPart>> getParts(long mmsId) {
|
public List<PduPart> getParts(long mmsId) {
|
||||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||||
List<Pair<Long, PduPart>> results = new LinkedList<>();
|
List<PduPart> results = new LinkedList<>();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -171,9 +170,7 @@ public class PartDatabase extends Database {
|
|||||||
null, null, null);
|
null, null, null);
|
||||||
|
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
PduPart part = getPart(cursor);
|
results.add(getPart(cursor));
|
||||||
results.add(new Pair<>(cursor.getLong(cursor.getColumnIndexOrThrow(ID)),
|
|
||||||
part));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@ -228,14 +225,15 @@ public class PartDatabase extends Database {
|
|||||||
void insertParts(MasterSecret masterSecret, long mmsId, PduBody body) throws MmsException {
|
void insertParts(MasterSecret masterSecret, long mmsId, PduBody body) throws MmsException {
|
||||||
for (int i=0;i<body.getPartsNum();i++) {
|
for (int i=0;i<body.getPartsNum();i++) {
|
||||||
PduPart part = body.getPart(i);
|
PduPart part = body.getPart(i);
|
||||||
long partId = insertPart(masterSecret, part, mmsId, part.getThumbnail());
|
PartId partId = insertPart(masterSecret, part, mmsId, part.getThumbnail());
|
||||||
Log.w(TAG, "Inserted part at ID: " + partId);
|
Log.w(TAG, "Inserted part at ID: " + partId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getPartValues(PduPart part, Cursor cursor) {
|
private void getPartValues(PduPart part, Cursor cursor) {
|
||||||
|
|
||||||
part.setId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
|
part.setRowId(cursor.getLong(cursor.getColumnIndexOrThrow(ROW_ID)));
|
||||||
|
part.setUniqueId(cursor.getLong(cursor.getColumnIndexOrThrow(UNIQUE_ID)));
|
||||||
|
|
||||||
int charsetColumn = cursor.getColumnIndexOrThrow(CHARSET);
|
int charsetColumn = cursor.getColumnIndexOrThrow(CHARSET);
|
||||||
|
|
||||||
@ -286,6 +284,7 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
if (!cursor.isNull(sizeColumn))
|
if (!cursor.isNull(sizeColumn))
|
||||||
part.setDataSize(cursor.getLong(cursor.getColumnIndexOrThrow(SIZE)));
|
part.setDataSize(cursor.getLong(cursor.getColumnIndexOrThrow(SIZE)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContentValues getContentValuesForPart(PduPart part) throws MmsException {
|
private ContentValues getContentValuesForPart(PduPart part) throws MmsException {
|
||||||
@ -327,6 +326,7 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
contentValues.put(ENCRYPTED, part.getEncrypted() ? 1 : 0);
|
contentValues.put(ENCRYPTED, part.getEncrypted() ? 1 : 0);
|
||||||
contentValues.put(PENDING_PUSH_ATTACHMENT, part.isPendingPush() ? 1 : 0);
|
contentValues.put(PENDING_PUSH_ATTACHMENT, part.isPendingPush() ? 1 : 0);
|
||||||
|
contentValues.put(UNIQUE_ID, part.getUniqueId());
|
||||||
|
|
||||||
return contentValues;
|
return contentValues;
|
||||||
}
|
}
|
||||||
@ -346,16 +346,14 @@ public class PartDatabase extends Database {
|
|||||||
return new EncryptingPartOutputStream(path, masterSecret);
|
return new EncryptingPartOutputStream(path, masterSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting InputStream getDataStream(MasterSecret masterSecret, long partId, byte[] contentId, String dataType)
|
@VisibleForTesting InputStream getDataStream(MasterSecret masterSecret, PartId partId, String dataType)
|
||||||
throws FileNotFoundException
|
throws FileNotFoundException
|
||||||
{
|
{
|
||||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = database.query(TABLE_NAME, new String[]{dataType}, ID_CONTENT_WHERE,
|
cursor = database.query(TABLE_NAME, new String[]{dataType}, PART_ID_WHERE, partId.toStrings(),
|
||||||
new String[] {String.valueOf(partId),
|
|
||||||
Util.toIsoString(contentId)},
|
|
||||||
null, null, null);
|
null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
@ -407,15 +405,15 @@ public class PartDatabase extends Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getThumbnailStream(MasterSecret masterSecret, long partId, byte[] contentId) throws IOException {
|
public InputStream getThumbnailStream(MasterSecret masterSecret, PartId partId) throws IOException {
|
||||||
Log.w(TAG, "getThumbnailStream(" + partId + ")");
|
Log.w(TAG, "getThumbnailStream(" + partId + ")");
|
||||||
final InputStream dataStream = getDataStream(masterSecret, partId, contentId, THUMBNAIL);
|
final InputStream dataStream = getDataStream(masterSecret, partId, THUMBNAIL);
|
||||||
if (dataStream != null) {
|
if (dataStream != null) {
|
||||||
return dataStream;
|
return dataStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId, contentId)).get();
|
return thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId)).get();
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
throw new AssertionError("interrupted");
|
throw new AssertionError("interrupted");
|
||||||
} catch (ExecutionException ee) {
|
} catch (ExecutionException ee) {
|
||||||
@ -429,12 +427,12 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
getPartValues(part, cursor);
|
getPartValues(part, cursor);
|
||||||
|
|
||||||
part.setDataUri(PartAuthority.getPartUri(part.getId(), part.getContentId()));
|
part.setDataUri(PartAuthority.getPartUri(part.getPartId()));
|
||||||
|
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertPart(MasterSecret masterSecret, PduPart part, long mmsId, Bitmap thumbnail) throws MmsException {
|
private PartId insertPart(MasterSecret masterSecret, PduPart part, long mmsId, Bitmap thumbnail) throws MmsException {
|
||||||
Log.w(TAG, "inserting part to mms " + mmsId);
|
Log.w(TAG, "inserting part to mms " + mmsId);
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
Pair<File, Long> partData = null;
|
Pair<File, Long> partData = null;
|
||||||
@ -452,21 +450,22 @@ public class PartDatabase extends Database {
|
|||||||
contentValues.put(SIZE, partData.second);
|
contentValues.put(SIZE, partData.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
long partId = database.insert(TABLE_NAME, null, contentValues);
|
long partRowId = database.insert(TABLE_NAME, null, contentValues);
|
||||||
|
PartId partId = new PartId(partRowId, part.getUniqueId());
|
||||||
|
|
||||||
if (thumbnail != null) {
|
if (thumbnail != null) {
|
||||||
Log.w(TAG, "inserting pre-generated thumbnail");
|
Log.w(TAG, "inserting pre-generated thumbnail");
|
||||||
ThumbnailData data = new ThumbnailData(thumbnail);
|
ThumbnailData data = new ThumbnailData(thumbnail);
|
||||||
updatePartThumbnail(masterSecret, partId, part, data.toDataStream(), data.getAspectRatio());
|
updatePartThumbnail(masterSecret, partId, part, data.toDataStream(), data.getAspectRatio());
|
||||||
} else if (!part.isPendingPush()) {
|
} else if (!part.isPendingPush()) {
|
||||||
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId, part.getContentId()));
|
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return partId;
|
return partId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateDownloadedPart(MasterSecret masterSecret, long messageId,
|
public void updateDownloadedPart(MasterSecret masterSecret, long messageId,
|
||||||
long partId, PduPart part, InputStream data)
|
PartId partId, PduPart part, InputStream data)
|
||||||
throws MmsException
|
throws MmsException
|
||||||
{
|
{
|
||||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||||
@ -482,9 +481,9 @@ public class PartDatabase extends Database {
|
|||||||
values.put(SIZE, partData.second);
|
values.put(SIZE, partData.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
database.update(TABLE_NAME, values, ID_WHERE, new String[]{partId+""});
|
database.update(TABLE_NAME, values, PART_ID_WHERE, partId.toStrings());
|
||||||
|
|
||||||
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId, part.getContentId()));
|
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId));
|
||||||
|
|
||||||
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId));
|
||||||
}
|
}
|
||||||
@ -499,8 +498,8 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = database.query(TABLE_NAME, new String[]{DATA}, ID_WHERE,
|
cursor = database.query(TABLE_NAME, new String[]{DATA}, PART_ID_WHERE,
|
||||||
new String[]{part.getId()+""}, null, null, null);
|
part.getPartId().toStrings(), null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
int dataColumn = cursor.getColumnIndexOrThrow(DATA);
|
int dataColumn = cursor.getColumnIndexOrThrow(DATA);
|
||||||
@ -517,11 +516,11 @@ public class PartDatabase extends Database {
|
|||||||
|
|
||||||
part.setDataSize(partData.second);
|
part.setDataSize(partData.second);
|
||||||
|
|
||||||
database.update(TABLE_NAME, values, ID_WHERE, new String[] {part.getId()+""});
|
database.update(TABLE_NAME, values, PART_ID_WHERE, part.getPartId().toStrings());
|
||||||
Log.w(TAG, "updated data for part #" + part.getId());
|
Log.w(TAG, "updated data for part #" + part.getPartId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePartThumbnail(MasterSecret masterSecret, long partId, PduPart part, InputStream in, float aspectRatio)
|
public void updatePartThumbnail(MasterSecret masterSecret, PartId partId, PduPart part, InputStream in, float aspectRatio)
|
||||||
throws MmsException
|
throws MmsException
|
||||||
{
|
{
|
||||||
Log.w(TAG, "updating part thumbnail for #" + partId);
|
Log.w(TAG, "updating part thumbnail for #" + partId);
|
||||||
@ -534,17 +533,16 @@ public class PartDatabase extends Database {
|
|||||||
values.put(THUMBNAIL, thumbnailFile.first.getAbsolutePath());
|
values.put(THUMBNAIL, thumbnailFile.first.getAbsolutePath());
|
||||||
values.put(ASPECT_RATIO, aspectRatio);
|
values.put(ASPECT_RATIO, aspectRatio);
|
||||||
|
|
||||||
database.update(TABLE_NAME, values, ID_WHERE, new String[]{partId+""});
|
database.update(TABLE_NAME, values, PART_ID_WHERE, partId.toStrings());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ImageRecord {
|
public static class ImageRecord {
|
||||||
private long partId;
|
private PartId partId;
|
||||||
private byte[] contentId;
|
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private String address;
|
private String address;
|
||||||
private long date;
|
private long date;
|
||||||
|
|
||||||
private ImageRecord(long partId, byte[] contentId, String contentType, String address, long date) {
|
private ImageRecord(PartId partId, String contentType, String address, long date) {
|
||||||
this.partId = partId;
|
this.partId = partId;
|
||||||
this.contentType = contentType;
|
this.contentType = contentType;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
@ -552,14 +550,16 @@ public class PartDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ImageRecord from(Cursor cursor) {
|
public static ImageRecord from(Cursor cursor) {
|
||||||
return new ImageRecord(cursor.getLong(cursor.getColumnIndexOrThrow(ID)),
|
PartId partId = new PartId(cursor.getLong(cursor.getColumnIndexOrThrow(ROW_ID)),
|
||||||
Util.toIsoBytes(cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_ID))),
|
cursor.getLong(cursor.getColumnIndexOrThrow(UNIQUE_ID)));
|
||||||
|
|
||||||
|
return new ImageRecord(partId,
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_TYPE)),
|
cursor.getString(cursor.getColumnIndexOrThrow(CONTENT_TYPE)),
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS)),
|
cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS)),
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED)) * 1000);
|
cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED)) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getPartId() {
|
public PartId getPartId() {
|
||||||
return partId;
|
return partId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,24 +576,22 @@ public class PartDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri getUri() {
|
public Uri getUri() {
|
||||||
return PartAuthority.getPartUri(partId, contentId);
|
return PartAuthority.getPartUri(partId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting class ThumbnailFetchCallable implements Callable<InputStream> {
|
@VisibleForTesting class ThumbnailFetchCallable implements Callable<InputStream> {
|
||||||
private final MasterSecret masterSecret;
|
private final MasterSecret masterSecret;
|
||||||
private final long partId;
|
private final PartId partId;
|
||||||
private final byte[] contentId;
|
|
||||||
|
|
||||||
public ThumbnailFetchCallable(MasterSecret masterSecret, long partId, byte[] contentId) {
|
public ThumbnailFetchCallable(MasterSecret masterSecret, PartId partId) {
|
||||||
this.masterSecret = masterSecret;
|
this.masterSecret = masterSecret;
|
||||||
this.partId = partId;
|
this.partId = partId;
|
||||||
this.contentId = contentId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream call() throws Exception {
|
public InputStream call() throws Exception {
|
||||||
final InputStream stream = getDataStream(masterSecret, partId, contentId, THUMBNAIL);
|
final InputStream stream = getDataStream(masterSecret, partId, THUMBNAIL);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
@ -609,7 +607,38 @@ public class PartDatabase extends Database {
|
|||||||
throw new IOException(bde);
|
throw new IOException(bde);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDataStream(masterSecret, partId, contentId, THUMBNAIL);
|
return getDataStream(masterSecret, partId, THUMBNAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PartId {
|
||||||
|
|
||||||
|
private final long rowId;
|
||||||
|
private final long uniqueId;
|
||||||
|
|
||||||
|
public PartId(long rowId, long uniqueId) {
|
||||||
|
this.rowId = rowId;
|
||||||
|
this.uniqueId = uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRowId() {
|
||||||
|
return rowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUniqueId() {
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] toStrings() {
|
||||||
|
return new String[] {String.valueOf(rowId), String.valueOf(uniqueId)};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "(row id: " + rowId + ", unique ID: " + uniqueId + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return rowId >= 0 && uniqueId >= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.jobs;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
@ -57,21 +56,21 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
|
|||||||
|
|
||||||
Log.w(TAG, "Downloading push parts for: " + messageId);
|
Log.w(TAG, "Downloading push parts for: " + messageId);
|
||||||
|
|
||||||
List<Pair<Long, PduPart>> parts = database.getParts(messageId);
|
List<PduPart> parts = database.getParts(messageId);
|
||||||
|
|
||||||
for (Pair<Long, PduPart> partPair : parts) {
|
for (PduPart part : parts) {
|
||||||
retrievePart(masterSecret, partPair.second, messageId, partPair.first);
|
retrievePart(masterSecret, part, messageId);
|
||||||
Log.w(TAG, "Got part: " + partPair.first);
|
Log.w(TAG, "Got part: " + part.getPartId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCanceled() {
|
public void onCanceled() {
|
||||||
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
||||||
List<Pair<Long, PduPart>> parts = database.getParts(messageId);
|
List<PduPart> parts = database.getParts(messageId);
|
||||||
|
|
||||||
for (Pair<Long, PduPart> partPair : parts) {
|
for (PduPart part : parts) {
|
||||||
markFailed(messageId, partPair.second, partPair.first);
|
markFailed(messageId, part, part.getPartId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +79,12 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
|
|||||||
return (exception instanceof PushNetworkException);
|
return (exception instanceof PushNetworkException);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void retrievePart(MasterSecret masterSecret, PduPart part, long messageId, long partId)
|
private void retrievePart(MasterSecret masterSecret, PduPart part, long messageId)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
||||||
File attachmentFile = null;
|
File attachmentFile = null;
|
||||||
|
PartDatabase.PartId partId = part.getPartId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
attachmentFile = createTempFile();
|
attachmentFile = createTempFile();
|
||||||
@ -133,7 +133,7 @@ public class AttachmentDownloadJob extends MasterSecretJob implements Injectable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markFailed(long messageId, PduPart part, long partId) {
|
private void markFailed(long messageId, PduPart part, PartDatabase.PartId partId) {
|
||||||
try {
|
try {
|
||||||
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
PartDatabase database = DatabaseFactory.getPartDatabase(context);
|
||||||
database.updateFailedDownloadedPart(messageId, partId, part);
|
database.updateFailedDownloadedPart(messageId, partId, part);
|
||||||
|
@ -87,7 +87,7 @@ public abstract class SendJob extends MasterSecretJob {
|
|||||||
PduPart part)
|
PduPart part)
|
||||||
throws IOException, MmsException
|
throws IOException, MmsException
|
||||||
{
|
{
|
||||||
Log.w(TAG, "resizing part " + part.getId());
|
Log.w(TAG, "resizing part " + part.getPartId());
|
||||||
|
|
||||||
final long oldSize = part.getDataSize();
|
final long oldSize = part.getDataSize();
|
||||||
final byte[] data = constraints.getResizedMedia(context, masterSecret, part);
|
final byte[] data = constraints.getResizedMedia(context, masterSecret, part);
|
||||||
|
@ -46,7 +46,7 @@ public class ImageSlide extends Slide {
|
|||||||
if (!getPart().isPendingPush() && getPart().getDataUri() != null) {
|
if (!getPart().isPendingPush() && getPart().getDataUri() != null) {
|
||||||
return isDraft()
|
return isDraft()
|
||||||
? getPart().getDataUri()
|
? getPart().getDataUri()
|
||||||
: PartAuthority.getThumbnailUri(getPart().getId(), part.getContentId());
|
: PartAuthority.getThumbnailUri(getPart().getPartId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -27,15 +27,11 @@ public class IncomingMediaMessage {
|
|||||||
private final String groupId;
|
private final String groupId;
|
||||||
private final boolean push;
|
private final boolean push;
|
||||||
|
|
||||||
public IncomingMediaMessage(RetrieveConf retreived) {
|
public IncomingMediaMessage(RetrieveConf retrieved) {
|
||||||
this.headers = retreived.getPduHeaders();
|
this.headers = retrieved.getPduHeaders();
|
||||||
this.body = retreived.getBody();
|
this.body = retrieved.getBody();
|
||||||
this.groupId = null;
|
this.groupId = null;
|
||||||
this.push = false;
|
this.push = false;
|
||||||
|
|
||||||
for (int i=0;i<body.getPartsNum();i++) {
|
|
||||||
body.getPart(i).setContentId(String.valueOf(System.currentTimeMillis()).getBytes());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingMediaMessage(MasterSecret masterSecret,
|
public IncomingMediaMessage(MasterSecret masterSecret,
|
||||||
|
@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.PartDatabase;
|
import org.thoughtcrime.securesms.database.PartDatabase;
|
||||||
import org.thoughtcrime.securesms.providers.PartProvider;
|
import org.thoughtcrime.securesms.providers.PartProvider;
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -41,11 +40,11 @@ public class PartAuthority {
|
|||||||
try {
|
try {
|
||||||
switch (match) {
|
switch (match) {
|
||||||
case PART_ROW:
|
case PART_ROW:
|
||||||
PartUri partUri = new PartUri(uri);
|
PartUriParser partUri = new PartUriParser(uri);
|
||||||
return partDatabase.getPartStream(masterSecret, partUri.getId(), partUri.getContentId());
|
return partDatabase.getPartStream(masterSecret, partUri.getPartId());
|
||||||
case THUMB_ROW:
|
case THUMB_ROW:
|
||||||
partUri = new PartUri(uri);
|
partUri = new PartUriParser(uri);
|
||||||
return partDatabase.getThumbnailStream(masterSecret, partUri.getId(), partUri.getContentId());
|
return partDatabase.getThumbnailStream(masterSecret, partUri.getPartId());
|
||||||
default:
|
default:
|
||||||
return context.getContentResolver().openInputStream(uri);
|
return context.getContentResolver().openInputStream(uri);
|
||||||
}
|
}
|
||||||
@ -55,17 +54,17 @@ public class PartAuthority {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Uri getPublicPartUri(Uri uri) {
|
public static Uri getPublicPartUri(Uri uri) {
|
||||||
PartUri partUri = new PartUri(uri);
|
PartUriParser partUri = new PartUriParser(uri);
|
||||||
return PartProvider.getContentUri(partUri.getId(), partUri.getContentId());
|
return PartProvider.getContentUri(partUri.getPartId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri getPartUri(long partId, byte[] contentId) {
|
public static Uri getPartUri(PartDatabase.PartId partId) {
|
||||||
Uri uri = Uri.withAppendedPath(PART_CONTENT_URI, Hex.toStringCondensed(contentId));
|
Uri uri = Uri.withAppendedPath(PART_CONTENT_URI, String.valueOf(partId.getUniqueId()));
|
||||||
return ContentUris.withAppendedId(uri, partId);
|
return ContentUris.withAppendedId(uri, partId.getRowId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri getThumbnailUri(long partId, byte[] contentId) {
|
public static Uri getThumbnailUri(PartDatabase.PartId partId) {
|
||||||
Uri uri = Uri.withAppendedPath(THUMB_CONTENT_URI, Hex.toStringCondensed(contentId));
|
Uri uri = Uri.withAppendedPath(THUMB_CONTENT_URI, String.valueOf(partId.getUniqueId()));
|
||||||
return ContentUris.withAppendedId(uri, partId);
|
return ContentUris.withAppendedId(uri, partId.getRowId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
|
||||||
|
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class PartUri {
|
|
||||||
|
|
||||||
private final Uri uri;
|
|
||||||
|
|
||||||
public PartUri(Uri uri) {
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return ContentUris.parseId(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getContentId() {
|
|
||||||
try {
|
|
||||||
return Hex.fromStringCondensed(uri.getPathSegments().get(1));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
31
src/org/thoughtcrime/securesms/mms/PartUriParser.java
Normal file
31
src/org/thoughtcrime/securesms/mms/PartUriParser.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
|
import android.content.ContentUris;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.database.PartDatabase;
|
||||||
|
import org.thoughtcrime.securesms.util.Hex;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PartUriParser {
|
||||||
|
|
||||||
|
private final Uri uri;
|
||||||
|
|
||||||
|
public PartUriParser(Uri uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PartDatabase.PartId getPartId() {
|
||||||
|
return new PartDatabase.PartId(getId(), getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getId() {
|
||||||
|
return ContentUris.parseId(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getUniqueId() {
|
||||||
|
return Long.parseLong(uri.getPathSegments().get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -80,7 +80,7 @@ public abstract class Slide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDraft() {
|
public boolean isDraft() {
|
||||||
return getPart().getId() < 0;
|
return !getPart().getPartId().isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void assertMediaSize(Context context, Uri uri)
|
protected static void assertMediaSize(Context context, Uri uri)
|
||||||
|
@ -27,9 +27,9 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.mms.PartUri;
|
import org.thoughtcrime.securesms.database.PartDatabase;
|
||||||
|
import org.thoughtcrime.securesms.mms.PartUriParser;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -57,13 +57,13 @@ public class PartProvider extends ContentProvider {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri getContentUri(long partId, byte[] contentId) {
|
public static Uri getContentUri(PartDatabase.PartId partId) {
|
||||||
Uri uri = Uri.withAppendedPath(CONTENT_URI, Hex.toStringCondensed(contentId));
|
Uri uri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(partId.getUniqueId()));
|
||||||
return ContentUris.withAppendedId(uri, partId);
|
return ContentUris.withAppendedId(uri, partId.getRowId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private File copyPartToTemporaryFile(MasterSecret masterSecret, long partId, byte[] contentId) throws IOException {
|
private File copyPartToTemporaryFile(MasterSecret masterSecret, PartDatabase.PartId partId) throws IOException {
|
||||||
InputStream in = DatabaseFactory.getPartDatabase(getContext()).getPartStream(masterSecret, partId, contentId);
|
InputStream in = DatabaseFactory.getPartDatabase(getContext()).getPartStream(masterSecret, partId);
|
||||||
File tmpDir = getContext().getDir("tmp", 0);
|
File tmpDir = getContext().getDir("tmp", 0);
|
||||||
File tmpFile = File.createTempFile("test", ".jpg", tmpDir);
|
File tmpFile = File.createTempFile("test", ".jpg", tmpDir);
|
||||||
FileOutputStream fout = new FileOutputStream(tmpFile);
|
FileOutputStream fout = new FileOutputStream(tmpFile);
|
||||||
@ -93,8 +93,8 @@ public class PartProvider extends ContentProvider {
|
|||||||
case SINGLE_ROW:
|
case SINGLE_ROW:
|
||||||
Log.w(TAG, "Parting out a single row...");
|
Log.w(TAG, "Parting out a single row...");
|
||||||
try {
|
try {
|
||||||
PartUri partUri = new PartUri(uri);
|
PartUriParser partUri = new PartUriParser(uri);
|
||||||
File tmpFile = copyPartToTemporaryFile(masterSecret, partUri.getId(), partUri.getContentId());
|
File tmpFile = copyPartToTemporaryFile(masterSecret, partUri.getPartId());
|
||||||
ParcelFileDescriptor pdf = ParcelFileDescriptor.open(tmpFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
ParcelFileDescriptor pdf = ParcelFileDescriptor.open(tmpFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
|
||||||
if (!tmpFile.delete()) {
|
if (!tmpFile.delete()) {
|
||||||
|
@ -21,6 +21,7 @@ import android.graphics.Bitmap;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.database.PartDatabase;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
@ -131,7 +132,8 @@ public class PduPart {
|
|||||||
|
|
||||||
private static final String TAG = "PduPart";
|
private static final String TAG = "PduPart";
|
||||||
|
|
||||||
private long id = -1;
|
private long rowId = -1;
|
||||||
|
private long uniqueId = -1;
|
||||||
private boolean isEncrypted;
|
private boolean isEncrypted;
|
||||||
private boolean isPendingPush;
|
private boolean isPendingPush;
|
||||||
private long dataSize;
|
private long dataSize;
|
||||||
@ -142,7 +144,7 @@ public class PduPart {
|
|||||||
*/
|
*/
|
||||||
public PduPart() {
|
public PduPart() {
|
||||||
mPartHeader = new HashMap<Integer, Object>();
|
mPartHeader = new HashMap<Integer, Object>();
|
||||||
setContentId(String.valueOf(System.currentTimeMillis()).getBytes());
|
setUniqueId(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEncrypted(boolean isEncrypted) {
|
public void setEncrypted(boolean isEncrypted) {
|
||||||
@ -441,12 +443,21 @@ public class PduPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getId() {
|
public PartDatabase.PartId getPartId() {
|
||||||
return id;
|
return new PartDatabase.PartId(rowId, uniqueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(long id) {
|
public void setPartId(PartDatabase.PartId partId) {
|
||||||
this.id = id;
|
this.rowId = partId.getRowId();
|
||||||
|
this.uniqueId = partId.getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRowId() {
|
||||||
|
return rowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRowId(long rowId) {
|
||||||
|
this.rowId = rowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap getThumbnail() {
|
public Bitmap getThumbnail() {
|
||||||
@ -456,5 +467,13 @@ public class PduPart {
|
|||||||
public void setThumbnail(Bitmap thumbnail) {
|
public void setThumbnail(Bitmap thumbnail) {
|
||||||
this.thumbnail = thumbnail;
|
this.thumbnail = thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getUniqueId() {
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUniqueId(long uniqueId) {
|
||||||
|
this.uniqueId = uniqueId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user