AttachFileToConversationRunnable.java

  1package eu.siacs.conversations.services;
  2
  3import android.net.Uri;
  4import android.os.Build;
  5import android.os.ParcelFileDescriptor;
  6import android.util.Log;
  7
  8import net.ypresto.androidtranscoder.MediaTranscoder;
  9import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
 10import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets;
 11
 12import java.io.FileDescriptor;
 13import java.io.FileNotFoundException;
 14import java.util.concurrent.atomic.AtomicInteger;
 15
 16import eu.siacs.conversations.Config;
 17import eu.siacs.conversations.R;
 18import eu.siacs.conversations.crypto.PgpEngine;
 19import eu.siacs.conversations.entities.DownloadableFile;
 20import eu.siacs.conversations.entities.Message;
 21import eu.siacs.conversations.persistance.FileBackend;
 22import eu.siacs.conversations.ui.UiCallback;
 23import eu.siacs.conversations.utils.MimeUtils;
 24
 25public class AttachFileToConversationRunnable implements Runnable, MediaTranscoder.Listener {
 26
 27	private final XmppConnectionService mXmppConnectionService;
 28	private final Message message;
 29	private final Uri uri;
 30	private final UiCallback<Message> callback;
 31	private final boolean isVideoMessage;
 32	private int currentProgress = -1;
 33
 34	public AttachFileToConversationRunnable(XmppConnectionService xmppConnectionService, Uri uri, Message message, UiCallback<Message> callback) {
 35		this.uri = uri;
 36		this.mXmppConnectionService = xmppConnectionService;
 37		this.message = message;
 38		this.callback = callback;
 39		final String mimeType = MimeUtils.guessMimeTypeFromUri(mXmppConnectionService, uri);
 40		this.isVideoMessage = (mimeType != null && mimeType.startsWith("video/") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2);
 41	}
 42
 43
 44	private void processAsFile() {
 45		final String path = mXmppConnectionService.getFileBackend().getOriginalPath(uri);
 46		if (path != null) {
 47			message.setRelativeFilePath(path);
 48			mXmppConnectionService.getFileBackend().updateFileParams(message);
 49			if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
 50				mXmppConnectionService.getPgpEngine().encrypt(message, callback);
 51			} else {
 52				callback.success(message);
 53			}
 54		} else {
 55			try {
 56				mXmppConnectionService.getFileBackend().copyFileToPrivateStorage(message, uri);
 57				mXmppConnectionService.getFileBackend().updateFileParams(message);
 58				if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
 59					final PgpEngine pgpEngine = mXmppConnectionService.getPgpEngine();
 60					if (pgpEngine != null) {
 61						pgpEngine.encrypt(message, callback);
 62					} else if (callback != null) {
 63						callback.error(R.string.unable_to_connect_to_keychain, null);
 64					}
 65				} else {
 66					callback.success(message);
 67				}
 68			} catch (FileBackend.FileCopyException e) {
 69				callback.error(e.getResId(), message);
 70			}
 71		}
 72	}
 73
 74	private void processAsVideo() throws FileNotFoundException {
 75		Log.d(Config.LOGTAG,"processing file as video");
 76		mXmppConnectionService.startForcingForegroundNotification();
 77		message.setRelativeFilePath(message.getUuid() + ".mp4");
 78		final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
 79		final int runtime = mXmppConnectionService.getFileBackend().getMediaRuntime(uri);
 80		MediaFormatStrategy formatStrategy = runtime >= 8000 ? MediaFormatStrategyPresets.createExportPreset960x540Strategy() : MediaFormatStrategyPresets.createAndroid720pStrategy();
 81		Log.d(Config.LOGTAG,"runtime "+runtime);
 82		file.getParentFile().mkdirs();
 83		ParcelFileDescriptor parcelFileDescriptor = mXmppConnectionService.getContentResolver().openFileDescriptor(uri, "r");
 84		FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
 85		MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(), formatStrategy, this);
 86	}
 87
 88	@Override
 89	public void onTranscodeProgress(double progress) {
 90		final int p = (int) Math.round(progress * 100);
 91		if (p > currentProgress) {
 92			currentProgress = p;
 93			mXmppConnectionService.getNotificationService().updateFileAddingNotification(p,message);
 94		}
 95	}
 96
 97	@Override
 98	public void onTranscodeCompleted() {
 99		mXmppConnectionService.stopForcingForegroundNotification();
100		mXmppConnectionService.getFileBackend().updateFileParams(message);
101		if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
102			mXmppConnectionService.getPgpEngine().encrypt(message, callback);
103		} else {
104			callback.success(message);
105		}
106	}
107
108	@Override
109	public void onTranscodeCanceled() {
110		mXmppConnectionService.stopForcingForegroundNotification();
111		processAsFile();
112	}
113
114	@Override
115	public void onTranscodeFailed(Exception e) {
116		mXmppConnectionService.stopForcingForegroundNotification();
117		Log.d(Config.LOGTAG,"video transcoding failed "+e.getMessage());
118		processAsFile();
119	}
120
121	@Override
122	public void run() {
123		if (isVideoMessage) {
124			try {
125				processAsVideo();
126			} catch (Throwable e) {
127				processAsFile();
128			}
129		} else {
130			processAsFile();
131		}
132	}
133
134}