2017-09-18 15:56:25 +00:00
|
|
|
package eu.siacs.conversations.services;
|
|
|
|
|
2019-09-28 21:56:02 +00:00
|
|
|
import android.content.Context;
|
2018-10-07 01:25:16 +00:00
|
|
|
import android.content.SharedPreferences;
|
2017-09-18 15:56:25 +00:00
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.ParcelFileDescriptor;
|
2018-10-07 01:25:16 +00:00
|
|
|
import android.preference.PreferenceManager;
|
2017-09-18 15:56:25 +00:00
|
|
|
import android.util.Log;
|
|
|
|
|
2021-01-23 08:25:34 +00:00
|
|
|
import androidx.annotation.RequiresApi;
|
|
|
|
|
2017-09-18 15:56:25 +00:00
|
|
|
import net.ypresto.androidtranscoder.MediaTranscoder;
|
|
|
|
import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
|
|
|
|
|
2017-10-27 09:34:50 +00:00
|
|
|
import java.io.File;
|
2017-09-18 15:56:25 +00:00
|
|
|
import java.io.FileDescriptor;
|
|
|
|
import java.io.FileNotFoundException;
|
2017-09-18 20:42:25 +00:00
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
import java.util.concurrent.Future;
|
2017-09-18 15:56:25 +00:00
|
|
|
|
|
|
|
import eu.siacs.conversations.Config;
|
|
|
|
import eu.siacs.conversations.R;
|
|
|
|
import eu.siacs.conversations.crypto.PgpEngine;
|
|
|
|
import eu.siacs.conversations.entities.DownloadableFile;
|
|
|
|
import eu.siacs.conversations.entities.Message;
|
|
|
|
import eu.siacs.conversations.persistance.FileBackend;
|
|
|
|
import eu.siacs.conversations.ui.UiCallback;
|
2018-09-28 16:38:54 +00:00
|
|
|
import eu.siacs.conversations.utils.Android360pFormatStrategy;
|
2018-10-06 14:15:32 +00:00
|
|
|
import eu.siacs.conversations.utils.Android720pFormatStrategy;
|
2017-09-18 15:56:25 +00:00
|
|
|
import eu.siacs.conversations.utils.MimeUtils;
|
|
|
|
|
|
|
|
public class AttachFileToConversationRunnable implements Runnable, MediaTranscoder.Listener {
|
|
|
|
|
|
|
|
private final XmppConnectionService mXmppConnectionService;
|
|
|
|
private final Message message;
|
|
|
|
private final Uri uri;
|
2018-03-03 15:58:04 +00:00
|
|
|
private final String type;
|
2017-09-18 15:56:25 +00:00
|
|
|
private final UiCallback<Message> callback;
|
|
|
|
private final boolean isVideoMessage;
|
2017-10-27 09:34:50 +00:00
|
|
|
private final long originalFileSize;
|
2017-09-18 15:56:25 +00:00
|
|
|
private int currentProgress = -1;
|
|
|
|
|
2018-10-07 11:09:13 +00:00
|
|
|
AttachFileToConversationRunnable(XmppConnectionService xmppConnectionService, Uri uri, String type, Message message, UiCallback<Message> callback) {
|
2017-09-18 15:56:25 +00:00
|
|
|
this.uri = uri;
|
2018-03-03 15:58:04 +00:00
|
|
|
this.type = type;
|
2017-09-18 15:56:25 +00:00
|
|
|
this.mXmppConnectionService = xmppConnectionService;
|
|
|
|
this.message = message;
|
|
|
|
this.callback = callback;
|
2018-12-22 12:02:45 +00:00
|
|
|
final String mimeType = MimeUtils.guessMimeTypeFromUriAndMime(mXmppConnectionService, uri, type);
|
2017-10-27 09:34:50 +00:00
|
|
|
final int autoAcceptFileSize = mXmppConnectionService.getResources().getInteger(R.integer.auto_accept_filesize);
|
|
|
|
this.originalFileSize = FileBackend.getFileSize(mXmppConnectionService,uri);
|
2019-01-02 09:03:33 +00:00
|
|
|
this.isVideoMessage = (mimeType != null && mimeType.startsWith("video/")) && originalFileSize > autoAcceptFileSize && !"uncompressed".equals(getVideoCompression());
|
2017-09-18 15:56:25 +00:00
|
|
|
}
|
|
|
|
|
2018-10-07 11:09:13 +00:00
|
|
|
boolean isVideoMessage() {
|
2018-12-11 16:25:59 +00:00
|
|
|
return this.isVideoMessage && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
|
2017-09-21 19:54:10 +00:00
|
|
|
}
|
2017-09-18 15:56:25 +00:00
|
|
|
|
|
|
|
private void processAsFile() {
|
|
|
|
final String path = mXmppConnectionService.getFileBackend().getOriginalPath(uri);
|
2018-02-12 11:31:59 +00:00
|
|
|
if (path != null && !FileBackend.isPathBlacklisted(path)) {
|
2017-09-18 15:56:25 +00:00
|
|
|
message.setRelativeFilePath(path);
|
|
|
|
mXmppConnectionService.getFileBackend().updateFileParams(message);
|
|
|
|
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
|
|
|
|
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
|
|
|
|
} else {
|
2018-02-27 10:44:23 +00:00
|
|
|
mXmppConnectionService.sendMessage(message);
|
2017-09-18 15:56:25 +00:00
|
|
|
callback.success(message);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
try {
|
2018-03-03 15:58:04 +00:00
|
|
|
mXmppConnectionService.getFileBackend().copyFileToPrivateStorage(message, uri, type);
|
2017-09-18 15:56:25 +00:00
|
|
|
mXmppConnectionService.getFileBackend().updateFileParams(message);
|
|
|
|
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
|
|
|
|
final PgpEngine pgpEngine = mXmppConnectionService.getPgpEngine();
|
|
|
|
if (pgpEngine != null) {
|
|
|
|
pgpEngine.encrypt(message, callback);
|
|
|
|
} else if (callback != null) {
|
|
|
|
callback.error(R.string.unable_to_connect_to_keychain, null);
|
|
|
|
}
|
|
|
|
} else {
|
2018-02-27 10:44:23 +00:00
|
|
|
mXmppConnectionService.sendMessage(message);
|
2017-09-18 15:56:25 +00:00
|
|
|
callback.success(message);
|
|
|
|
}
|
|
|
|
} catch (FileBackend.FileCopyException e) {
|
|
|
|
callback.error(e.getResId(), message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-10 12:58:05 +00:00
|
|
|
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
2017-09-18 15:56:25 +00:00
|
|
|
private void processAsVideo() throws FileNotFoundException {
|
|
|
|
Log.d(Config.LOGTAG,"processing file as video");
|
|
|
|
mXmppConnectionService.startForcingForegroundNotification();
|
|
|
|
message.setRelativeFilePath(message.getUuid() + ".mp4");
|
|
|
|
final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
|
2018-10-07 01:25:16 +00:00
|
|
|
final MediaFormatStrategy formatStrategy = "720".equals(getVideoCompression()) ? new Android720pFormatStrategy() : new Android360pFormatStrategy();
|
2017-09-18 15:56:25 +00:00
|
|
|
file.getParentFile().mkdirs();
|
2017-10-14 00:38:05 +00:00
|
|
|
final ParcelFileDescriptor parcelFileDescriptor = mXmppConnectionService.getContentResolver().openFileDescriptor(uri, "r");
|
|
|
|
if (parcelFileDescriptor == null) {
|
|
|
|
throw new FileNotFoundException("Parcel File Descriptor was null");
|
|
|
|
}
|
2017-09-18 15:56:25 +00:00
|
|
|
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
|
2017-09-18 20:42:25 +00:00
|
|
|
Future<Void> future = MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(), formatStrategy, this);
|
|
|
|
try {
|
|
|
|
future.get();
|
2017-10-14 00:38:05 +00:00
|
|
|
} catch (InterruptedException e) {
|
2017-09-18 20:42:25 +00:00
|
|
|
throw new AssertionError(e);
|
2017-10-14 00:38:05 +00:00
|
|
|
} catch (ExecutionException e) {
|
2019-01-02 09:03:33 +00:00
|
|
|
if (e.getCause() instanceof Error) {
|
|
|
|
mXmppConnectionService.stopForcingForegroundNotification();
|
|
|
|
processAsFile();
|
|
|
|
} else {
|
|
|
|
Log.d(Config.LOGTAG, "ignoring execution exception. Should get handled by onTranscodeFiled() instead", e);
|
|
|
|
}
|
2017-09-18 20:42:25 +00:00
|
|
|
}
|
2017-09-18 15:56:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTranscodeProgress(double progress) {
|
|
|
|
final int p = (int) Math.round(progress * 100);
|
|
|
|
if (p > currentProgress) {
|
|
|
|
currentProgress = p;
|
|
|
|
mXmppConnectionService.getNotificationService().updateFileAddingNotification(p,message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTranscodeCompleted() {
|
|
|
|
mXmppConnectionService.stopForcingForegroundNotification();
|
2017-10-27 09:34:50 +00:00
|
|
|
final File file = mXmppConnectionService.getFileBackend().getFile(message);
|
|
|
|
long convertedFileSize = mXmppConnectionService.getFileBackend().getFile(message).getSize();
|
|
|
|
Log.d(Config.LOGTAG,"originalFileSize="+originalFileSize+" convertedFileSize="+convertedFileSize);
|
|
|
|
if (originalFileSize != 0 && convertedFileSize >= originalFileSize) {
|
|
|
|
if (file.delete()) {
|
|
|
|
Log.d(Config.LOGTAG,"original file size was smaller. deleting and processing as file");
|
|
|
|
processAsFile();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
Log.d(Config.LOGTAG,"unable to delete converted file");
|
|
|
|
}
|
|
|
|
}
|
2017-09-18 15:56:25 +00:00
|
|
|
mXmppConnectionService.getFileBackend().updateFileParams(message);
|
|
|
|
if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
|
|
|
|
mXmppConnectionService.getPgpEngine().encrypt(message, callback);
|
|
|
|
} else {
|
2018-02-27 17:08:09 +00:00
|
|
|
mXmppConnectionService.sendMessage(message);
|
2017-09-18 15:56:25 +00:00
|
|
|
callback.success(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTranscodeCanceled() {
|
|
|
|
mXmppConnectionService.stopForcingForegroundNotification();
|
|
|
|
processAsFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTranscodeFailed(Exception e) {
|
|
|
|
mXmppConnectionService.stopForcingForegroundNotification();
|
2017-09-18 20:42:25 +00:00
|
|
|
Log.d(Config.LOGTAG,"video transcoding failed",e);
|
2017-09-18 15:56:25 +00:00
|
|
|
processAsFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2018-12-11 16:25:59 +00:00
|
|
|
if (this.isVideoMessage()) {
|
2017-09-18 15:56:25 +00:00
|
|
|
try {
|
|
|
|
processAsVideo();
|
2017-10-14 00:38:05 +00:00
|
|
|
} catch (FileNotFoundException e) {
|
2017-09-18 15:56:25 +00:00
|
|
|
processAsFile();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
processAsFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-07 11:09:13 +00:00
|
|
|
private String getVideoCompression() {
|
2019-09-28 21:56:02 +00:00
|
|
|
return getVideoCompression(mXmppConnectionService);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getVideoCompression(final Context context) {
|
|
|
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
return preferences.getString("video_compression", context.getResources().getString(R.string.video_compression));
|
2018-10-07 01:25:16 +00:00
|
|
|
}
|
2017-09-18 15:56:25 +00:00
|
|
|
}
|