aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/de/pixart/messenger/persistance/FileBackend.java10
-rw-r--r--src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java139
-rw-r--r--src/main/java/de/pixart/messenger/services/NotificationService.java12
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java135
-rw-r--r--src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java5
-rw-r--r--src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.pngbin0 -> 159 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.pngbin0 -> 135 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.pngbin0 -> 174 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.pngbin0 -> 255 bytes
-rw-r--r--src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.pngbin0 -> 273 bytes
-rw-r--r--src/main/res/values-de/strings.xml2
-rw-r--r--src/main/res/values/strings.xml2
12 files changed, 187 insertions, 118 deletions
diff --git a/src/main/java/de/pixart/messenger/persistance/FileBackend.java b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
index c0cb0a7bd..ee645c50b 100644
--- a/src/main/java/de/pixart/messenger/persistance/FileBackend.java
+++ b/src/main/java/de/pixart/messenger/persistance/FileBackend.java
@@ -835,6 +835,16 @@ public class FileBackend {
}
+ public int getMediaRuntime(Uri uri) {
+ try {
+ MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
+ mediaMetadataRetriever.setDataSource(mXmppConnectionService, uri);
+ return Integer.parseInt(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
+ } catch (IllegalArgumentException e) {
+ return 0;
+ }
+ }
+
private Dimensions getImageDimensions(File file) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
diff --git a/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java b/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java
new file mode 100644
index 000000000..707bd6ed4
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/services/AttachFileToConversationRunnable.java
@@ -0,0 +1,139 @@
+package de.pixart.messenger.services;
+
+import android.net.Uri;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import net.ypresto.androidtranscoder.MediaTranscoder;
+import net.ypresto.androidtranscoder.format.MediaFormatStrategy;
+import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets;
+
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+import de.pixart.messenger.crypto.PgpEngine;
+import de.pixart.messenger.entities.DownloadableFile;
+import de.pixart.messenger.entities.Message;
+import de.pixart.messenger.persistance.FileBackend;
+import de.pixart.messenger.ui.UiCallback;
+import de.pixart.messenger.utils.MimeUtils;
+
+public class AttachFileToConversationRunnable implements Runnable, MediaTranscoder.Listener {
+
+ private final XmppConnectionService mXmppConnectionService;
+ private final Message message;
+ private final Uri uri;
+ private final UiCallback<Message> callback;
+ private final boolean isVideoMessage;
+ private int currentProgress = -1;
+
+ public AttachFileToConversationRunnable(XmppConnectionService xmppConnectionService, Uri uri, Message message, UiCallback<Message> callback) {
+ this.uri = uri;
+ this.mXmppConnectionService = xmppConnectionService;
+ this.message = message;
+ this.callback = callback;
+ final String mimeType = MimeUtils.guessMimeTypeFromUri(mXmppConnectionService, uri);
+ this.isVideoMessage = (mimeType != null && mimeType.startsWith("video/") && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 || !getFileBackend().useFileAsIs(uri)));
+ }
+
+ private void processAsFile() {
+ final String path = mXmppConnectionService.getFileBackend().getOriginalPath(uri);
+ if (path != null) {
+ message.setRelativeFilePath(path);
+ mXmppConnectionService.getFileBackend().updateFileParams(message);
+ if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ mXmppConnectionService.getPgpEngine().encrypt(message, callback);
+ } else {
+ callback.success(message);
+ }
+ } else {
+ try {
+ mXmppConnectionService.getFileBackend().copyFileToPrivateStorage(message, uri);
+ 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 {
+ callback.success(message);
+ }
+ } catch (FileBackend.FileCopyException e) {
+ callback.error(e.getResId(), message);
+ }
+ }
+ }
+
+ private void processAsVideo() throws FileNotFoundException {
+ Log.d(Config.LOGTAG, "processing file as video");
+ mXmppConnectionService.startForcingForegroundNotification();
+ SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
+ message.setRelativeFilePath(fileDateFormat.format(new Date(message.getTimeSent())) + "_" + message.getUuid().substring(0, 4) + "_komp.mp4");
+ final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message);
+ final int runtime = mXmppConnectionService.getFileBackend().getMediaRuntime(uri);
+ MediaFormatStrategy formatStrategy = runtime >= 8000 ? MediaFormatStrategyPresets.createExportPreset960x540Strategy() : MediaFormatStrategyPresets.createAndroid720pStrategy();
+ Log.d(Config.LOGTAG, "runtime " + runtime);
+ file.getParentFile().mkdirs();
+ ParcelFileDescriptor parcelFileDescriptor = mXmppConnectionService.getContentResolver().openFileDescriptor(uri, "r");
+ FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
+ MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(), formatStrategy, this);
+ }
+
+ @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();
+ mXmppConnectionService.getFileBackend().updateFileParams(message);
+ if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ mXmppConnectionService.getPgpEngine().encrypt(message, callback);
+ } else {
+ callback.success(message);
+ }
+ }
+
+ @Override
+ public void onTranscodeCanceled() {
+ mXmppConnectionService.stopForcingForegroundNotification();
+ processAsFile();
+ }
+
+ @Override
+ public void onTranscodeFailed(Exception e) {
+ mXmppConnectionService.stopForcingForegroundNotification();
+ Log.d(Config.LOGTAG, "video transcoding failed " + e.getMessage());
+ processAsFile();
+ }
+
+ @Override
+ public void run() {
+ if (isVideoMessage) {
+ try {
+ processAsVideo();
+ } catch (Throwable e) {
+ processAsFile();
+ }
+ } else {
+ processAsFile();
+ }
+ }
+
+ public FileBackend getFileBackend() {
+ return mXmppConnectionService.fileBackend;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/services/NotificationService.java b/src/main/java/de/pixart/messenger/services/NotificationService.java
index f1a43dd28..daeba94e3 100644
--- a/src/main/java/de/pixart/messenger/services/NotificationService.java
+++ b/src/main/java/de/pixart/messenger/services/NotificationService.java
@@ -767,4 +767,16 @@ public class NotificationService {
notificationManager.notify(ERROR_NOTIFICATION_ID, mBuilder.build());
}
+
+ public Notification updateFileAddingNotification(int current, Message message) {
+ final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mXmppConnectionService);
+ mBuilder.setContentTitle(mXmppConnectionService.getString(R.string.transcoding_video));
+ mBuilder.setProgress(100, current, false);
+ mBuilder.setSmallIcon(R.drawable.ic_hourglass_empty_white_24dp);
+ mBuilder.setContentIntent(createContentIntent(message.getConversation()));
+ Notification notification = mBuilder.build();
+ notificationManager.notify(FOREGROUND_NOTIFICATION_ID, notification);
+ return notification;
+ }
}
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 464df2232..0900a4ec4 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -21,7 +21,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
@@ -42,15 +41,11 @@ import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus;
-import net.ypresto.androidtranscoder.MediaTranscoder;
-import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets;
import org.openintents.openpgp.IOpenPgpService2;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
-import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
import java.math.BigInteger;
import java.net.URL;
import java.security.SecureRandom;
@@ -62,7 +57,6 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@@ -112,7 +106,6 @@ import de.pixart.messenger.persistance.DatabaseBackend;
import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.ui.SettingsActivity;
import de.pixart.messenger.ui.UiCallback;
-import de.pixart.messenger.ui.UiInformableCallback;
import de.pixart.messenger.utils.ConversationsFileObserver;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.ExceptionHelper;
@@ -190,11 +183,12 @@ public class XmppConnectionService extends Service {
startService(intent);
}
};
- private FileBackend fileBackend = new FileBackend(this);
+ public FileBackend fileBackend = new FileBackend(this);
private MemorizingTrustManager mMemorizingTrustManager;
private NotificationService mNotificationService = new NotificationService(this);
private ShortcutService mShortcutService = new ShortcutService(this);
private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
+ private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
private OnMessagePacketReceived mMessageParser = new MessageParser(this);
private OnPresencePacketReceived mPresenceParser = new PresenceParser(this);
private IqParser mIqParser = new IqParser(this);
@@ -405,6 +399,16 @@ public class XmppConnectionService extends Service {
}
}
+ public void startForcingForegroundNotification() {
+ mForceForegroundService.set(true);
+ toggleForegroundService();
+ }
+
+ public void stopForcingForegroundNotification() {
+ mForceForegroundService.set(false);
+ toggleForegroundService();
+ }
+
private OpenPgpServiceConnection pgpServiceConnection;
private PgpEngine mPgpEngine = null;
private PowerManager pm;
@@ -489,107 +493,8 @@ public class XmppConnectionService extends Service {
}
message.setCounterpart(conversation.getNextCounterpart());
message.setType(Message.TYPE_FILE);
- mFileAddingExecutor.execute(new Runnable() {
- private void processAsFile() {
- final String path = getFileBackend().getOriginalPath(uri);
- if (path != null) {
- message.setRelativeFilePath(path);
- getFileBackend().updateFileParams(message);
- if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
- getPgpEngine().encrypt(message, callback);
- } else {
- callback.success(message);
- }
- } else {
- try {
- getFileBackend().copyFileToPrivateStorage(message, uri);
- getFileBackend().updateFileParams(message);
- if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
- final PgpEngine pgpEngine = getPgpEngine();
- if (pgpEngine != null) {
- pgpEngine.encrypt(message, callback);
- } else if (callback != null) {
- callback.error(R.string.unable_to_connect_to_keychain, null);
- }
- } else {
- callback.success(message);
- }
- } catch (FileBackend.FileCopyException e) {
- callback.error(e.getResId(), message);
- }
- }
- }
-
- private void processAsVideo() throws FileNotFoundException {
- Log.d(Config.LOGTAG, "processing file as video");
- SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
- message.setRelativeFilePath(fileDateFormat.format(new Date(message.getTimeSent())) + "_" + message.getUuid().substring(0, 4) + "_komp.mp4");
- final DownloadableFile file = getFileBackend().getFile(message);
- file.getParentFile().mkdirs();
- ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
- FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
- final ArrayList<Integer> progressTracker = new ArrayList<>();
- final UiInformableCallback<Message> informableCallback;
- if (callback instanceof UiInformableCallback) {
- informableCallback = (UiInformableCallback<Message>) callback;
- } else {
- informableCallback = null;
- }
- MediaTranscoder.Listener listener = new MediaTranscoder.Listener() {
- @Override
- public void onTranscodeProgress(double progress) {
- int p = ((int) Math.round(progress * 100) / 5) * 5;
- if (!progressTracker.contains(p) && p != 100 && p != 0) {
- progressTracker.add(p);
- if (informableCallback != null) {
- informableCallback.inform(getString(R.string.transcoding_video_progress, String.valueOf(p)));
- }
- }
- }
-
- @Override
- public void onTranscodeCompleted() {
- getFileBackend().updateFileParams(message);
- if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
- getPgpEngine().encrypt(message, callback);
- } else {
- callback.success(message);
- }
- }
-
- @Override
- public void onTranscodeCanceled() {
- processAsFile();
- }
-
- @Override
- public void onTranscodeFailed(Exception e) {
- Log.d(Config.LOGTAG, "video transcoding failed " + e.getMessage());
- processAsFile();
- }
- };
- MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(),
- MediaFormatStrategyPresets.createAndroidStandardStrategy(getCompressVideoBitratePreference(), getCompressVideoResolutionPreference()), listener);
- }
-
- @Override
- public void run() {
- final String mimeType = MimeUtils.guessMimeTypeFromUri(XmppConnectionService.this, uri);
- if (mimeType != null && mimeType.startsWith("video/") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- if (getFileBackend().useFileAsIs(uri)) {
- processAsFile();
- } else {
- try {
- processAsVideo();
- } catch (Throwable e) {
- processAsFile();
- }
- }
- } else {
- processAsFile();
- }
- }
- });
+ AttachFileToConversationRunnable runnable = new AttachFileToConversationRunnable(this,uri,message,callback);
+ mFileAddingExecutor.execute(runnable);
}
public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) {
@@ -1208,20 +1113,22 @@ public class XmppConnectionService extends Service {
}
public void toggleForegroundService() {
- if (showForegroundService()) {
+ if (mForceForegroundService.get() || (showForegroundService())) {
startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, this.mNotificationService.createForegroundNotification());
+ Log.d(Config.LOGTAG, "started foreground service");
} else {
stopForeground(true);
+ Log.d(Config.LOGTAG, "stopped foreground service");
}
}
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
- if (!showForegroundService()) {
- this.logoutAndSave(false);
+ if (showForegroundService() || mForceForegroundService.get()) {
+ Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated");
} else {
- Log.d(Config.LOGTAG,"ignoring onTaskRemoved because foreground service is activated");
+ this.logoutAndSave(false);
}
}
@@ -4231,6 +4138,8 @@ public class XmppConnectionService extends Service {
return mShortcutService;
}
+
+
public interface OnMamPreferencesFetched {
void onPreferencesFetched(Element prefs);
diff --git a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
index 6b60a424f..b4ecf6e5e 100644
--- a/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
+++ b/src/main/java/de/pixart/messenger/utils/SerialSingleThreadExecutor.java
@@ -3,15 +3,14 @@ package de.pixart.messenger.utils;
import android.os.Looper;
import java.util.ArrayDeque;
-import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class SerialSingleThreadExecutor implements Executor {
final Executor executor = Executors.newSingleThreadExecutor();
- protected final Queue<Runnable> tasks = new ArrayDeque();
- Runnable active;
+ protected final ArrayDeque<Runnable> tasks = new ArrayDeque<>();
+ private Runnable active;
public SerialSingleThreadExecutor() {
this(false);
diff --git a/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png b/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 000000000..5b8b6841d
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_hourglass_empty_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png b/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 000000000..616df098d
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_hourglass_empty_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png b/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 000000000..35b7eef2a
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_hourglass_empty_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png b/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 000000000..8f67bc62b
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_hourglass_empty_white_24dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png b/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png
new file mode 100644
index 000000000..b0bda2606
--- /dev/null
+++ b/src/main/res/drawable-xxxhdpi/ic_hourglass_empty_white_24dp.png
Binary files differ
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index 7e593dd12..986a31c60 100644
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -669,7 +669,7 @@
<string name="show_inactive_devices">Zeige inaktive Geräte</string>
<string name="distrust_omemo_key">Gerät misstrauen</string>
<string name="distrust_omemo_key_text">Bist du sicher, dass du die Verifizierung dieses Gerätes misstrauen möchtest? Dieses Gerät und Nachrichten von dem Gerät werden als unverifiziert markiert.</string>
- <string name="transcoding_video_progress">Video wird komprimiert (%s%%)</string>
+ <string name="transcoding_video">Video wird komprimiert</string>
<string name="encrypting_message">Nachricht wird verschlüsselt</string>
<string name="pref_automatically_delete_messages">Nachrichten automatisch löschen</string>
<string name="pref_automatically_delete_messages_description">Nachrichten von diesel Gerät nach dem eingestellten Zeitfenster automatisch löschen.</string>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 3fb0c39e2..86502dac1 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -729,7 +729,7 @@
<string name="hide_inactive_devices">Hide inactive devices</string>
<string name="reply">Reply</string>
<string name="encrypting_message">Encrypting message</string>
- <string name="transcoding_video_progress">Compressing video (%s%%)</string>
+ <string name="transcoding_video">Compressing video</string>
<string name="pref_automatically_delete_messages_description">Automatically delete messages from this device that are older than the configured time frame.</string>
<string name="pref_automatically_delete_messages">Automatic message deletion</string>
<string name="not_fetching_history_retention_period">Not fetching messages due to local retention period.</string>