session-android/src/org/thoughtcrime/securesms/util/SaveAttachmentTask.java
Jake McGinty 07bb07c342 streaming media
// FREEBIE
2014-12-12 18:49:32 -08:00

160 lines
5.9 KiB
Java

package org.thoughtcrime.securesms.util;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.mms.PartAuthority;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTask.Attachment, Void, Integer> {
private static final String TAG = SaveAttachmentTask.class.getSimpleName();
private static final int SUCCESS = 0;
private static final int FAILURE = 1;
private static final int WRITE_ACCESS_FAILURE = 2;
private final WeakReference<Context> contextReference;
private final WeakReference<MasterSecret> masterSecretReference;
public SaveAttachmentTask(Context context, MasterSecret masterSecret) {
super(context, R.string.ConversationFragment_saving_attachment, R.string.ConversationFragment_saving_attachment_to_sd_card);
this.contextReference = new WeakReference<Context>(context);
this.masterSecretReference = new WeakReference<MasterSecret>(masterSecret);
}
@Override
protected Integer doInBackground(SaveAttachmentTask.Attachment... attachments) {
if (attachments == null || attachments.length != 1 || attachments[0] == null) {
throw new AssertionError("must pass in exactly one attachment");
}
Attachment attachment = attachments[0];
try {
Context context = contextReference.get();
MasterSecret masterSecret = masterSecretReference.get();
if (!Environment.getExternalStorageDirectory().canWrite()) {
return WRITE_ACCESS_FAILURE;
}
if (context == null) {
return FAILURE;
}
File mediaFile = constructOutputFile(attachment.contentType, attachment.date);
InputStream inputStream = PartAuthority.getPartStream(context, masterSecret, attachment.uri);
OutputStream outputStream = new FileOutputStream(mediaFile);
Util.copy(inputStream, outputStream);
MediaScannerConnection.scanFile(context, new String[]{mediaFile.getAbsolutePath()},
new String[]{attachment.contentType}, null);
return SUCCESS;
} catch (IOException ioe) {
Log.w(TAG, ioe);
return FAILURE;
}
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
Context context = contextReference.get();
if (context == null) return;
switch (result) {
case FAILURE:
Toast.makeText(context, R.string.ConversationFragment_error_while_saving_attachment_to_sd_card,
Toast.LENGTH_LONG).show();
break;
case SUCCESS:
Toast.makeText(context, R.string.ConversationFragment_success_exclamation,
Toast.LENGTH_LONG).show();
break;
case WRITE_ACCESS_FAILURE:
Toast.makeText(context, R.string.ConversationFragment_unable_to_write_to_sd_card_exclamation,
Toast.LENGTH_LONG).show();
break;
}
}
private File constructOutputFile(String contentType, long timestamp) throws IOException {
File sdCard = Environment.getExternalStorageDirectory();
File outputDirectory;
if (contentType.startsWith("video/")) {
outputDirectory = new File(sdCard.getAbsoluteFile() + File.separator + Environment.DIRECTORY_MOVIES);
} else if (contentType.startsWith("audio/")) {
outputDirectory = new File(sdCard.getAbsolutePath() + File.separator + Environment.DIRECTORY_MUSIC);
} else if (contentType.startsWith("image/")) {
outputDirectory = new File(sdCard.getAbsolutePath() + File.separator + Environment.DIRECTORY_PICTURES);
} else {
outputDirectory = new File(sdCard.getAbsolutePath() + File.separator + Environment.DIRECTORY_DOWNLOADS);
}
if (!outputDirectory.mkdirs()) Log.w(TAG, "mkdirs() returned false, attempting to continue");
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String extension = mimeTypeMap.getExtensionFromMimeType(contentType);
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd-HHmmss");
String base = "textsecure-" + dateFormatter.format(timestamp);
if (extension == null)
extension = "attach";
int i = 0;
File file = new File(outputDirectory, base + "." + extension);
while (file.exists()) {
file = new File(outputDirectory, base + "-" + (++i) + "." + extension);
}
return file;
}
public static class Attachment {
public Uri uri;
public String contentType;
public long date;
public Attachment(Uri uri, String contentType, long date) {
if (uri == null || contentType == null || date < 0) {
throw new AssertionError("uri, content type, and date must all be specified");
}
this.uri = uri;
this.contentType = contentType;
this.date = date;
}
}
public static void showWarningDialog(Context context, OnClickListener onAcceptListener) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.ConversationFragment_save_to_sd_card);
builder.setIcon(Dialogs.resolveIcon(context, R.attr.dialog_alert_icon));
builder.setCancelable(true);
builder.setMessage(R.string.ConversationFragment_this_media_has_been_stored_in_an_encrypted_database_warning);
builder.setPositiveButton(R.string.yes, onAcceptListener);
builder.setNegativeButton(R.string.no, null);
builder.show();
}
}