put images into MessageStyle notifications

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java  |  8 
src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java  | 10 
src/main/java/eu/siacs/conversations/persistance/FileBackend.java      | 47 
src/main/java/eu/siacs/conversations/services/NotificationService.java | 25 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java |  5 
5 files changed, 80 insertions(+), 15 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/PgpDecryptionService.java 🔗

@@ -135,6 +135,7 @@ public class PgpDecryptionService {
 	}
 
 	private void executeApi(Message message) {
+		boolean skipNotificationPush = false;
 		synchronized (message) {
 			Intent params = userInteractionResult != null ? userInteractionResult : new Intent();
 			params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
@@ -209,8 +210,9 @@ public class PgpDecryptionService {
 							mXmppConnectionService.getFileBackend().updateFileParams(message, url);
 							message.setEncryption(Message.ENCRYPTION_DECRYPTED);
 							inputFile.delete();
-							mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile);
 							mXmppConnectionService.updateMessage(message);
+							skipNotificationPush = true;
+							mXmppConnectionService.getFileBackend().updateMediaScanner(outputFile, () -> notifyIfPending(message));
 							break;
 						case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 							synchronized (PgpDecryptionService.this) {
@@ -231,7 +233,9 @@ public class PgpDecryptionService {
 				}
 			}
 		}
-		notifyIfPending(message);
+		if (!skipNotificationPush) {
+			notifyIfPending(message);
+		}
 	}
 
 	private synchronized void notifyIfPending(Message message) {

src/main/java/eu/siacs/conversations/http/HttpDownloadConnection.java 🔗

@@ -140,7 +140,6 @@ public class HttpDownloadConnection implements Transferable {
 	}
 
 	private void finish() {
-		mXmppConnectionService.getFileBackend().updateMediaScanner(file);
 		message.setTransferable(null);
 		mHttpConnectionManager.finishConnection(this);
 		boolean notify = acceptedAutomatically && !message.isRead();
@@ -148,9 +147,12 @@ public class HttpDownloadConnection implements Transferable {
 			notify = message.getConversation().getAccount().getPgpDecryptionService().decrypt(message, notify);
 		}
 		mHttpConnectionManager.updateConversationUi(true);
-		if (notify) {
-			mXmppConnectionService.getNotificationService().push(message);
-		}
+		final boolean notifyAfterScan = notify;
+		mXmppConnectionService.getFileBackend().updateMediaScanner(file, () -> {
+			if (notifyAfterScan) {
+				mXmppConnectionService.getNotificationService().push(message);
+			}
+		});
 	}
 
 	private void changeStatus(int status) {

src/main/java/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -13,6 +13,7 @@ import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.RectF;
 import android.media.MediaMetadataRetriever;
+import android.media.MediaScannerConnection;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Environment;
@@ -406,14 +407,56 @@ public class FileBackend {
         }
     }
 
+    public static Uri getMediaUri(Context context, File file) {
+        final String filePath = file.getAbsolutePath();
+        final Cursor cursor = context.getContentResolver().query(
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                new String[] { MediaStore.Images.Media._ID },
+                MediaStore.Images.Media.DATA + "=? ",
+                new String[] { filePath }, null);
+        if (cursor != null && cursor.moveToFirst()) {
+            final int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
+            cursor.close();
+            return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));
+        } else {
+            return null;
+        }
+    }
+
     public void updateMediaScanner(File file) {
+        updateMediaScanner(file, null);
+    }
+
+    public void updateMediaScanner(File file, final Runnable callback) {
         if (!isInDirectoryThatShouldNotBeScanned(mXmppConnectionService, file)) {
-            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+            MediaScannerConnection.scanFile(mXmppConnectionService, new String[]{file.getAbsolutePath()}, null, new MediaScannerConnection.MediaScannerConnectionClient() {
+                @Override
+                public void onMediaScannerConnected() {
+
+                }
+
+                @Override
+                public void onScanCompleted(String path, Uri uri) {
+                    if (callback != null && file.getAbsolutePath().equals(path)) {
+                        callback.run();
+                    } else {
+                        Log.d(Config.LOGTAG,"media scanner scanned wrong file");
+                        if (callback != null) {
+                            callback.run();
+                        }
+                    }
+                }
+            });
+            return;
+            /*Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
             intent.setData(Uri.fromFile(file));
-            mXmppConnectionService.sendBroadcast(intent);
+            mXmppConnectionService.sendBroadcast(intent);*/
         } else if (file.getAbsolutePath().startsWith(getAppMediaDirectory(mXmppConnectionService))) {
             createNoMedia(file.getParentFile());
         }
+        if (callback != null) {
+            callback.run();
+        }
     }
 
     public boolean deleteFile(Message message) {

src/main/java/eu/siacs/conversations/services/NotificationService.java 🔗

@@ -519,7 +519,7 @@ public class NotificationService {
             } else {
                 Message message;
                 //TODO starting with Android 9 we might want to put images in MessageStyle
-                if ((message = getImage(messages)) != null) {
+                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P && (message = getImage(messages)) != null) {
                     modifyForImage(mBuilder, mUnreadBuilder, message, messages);
                 } else {
                     modifyForTextOnly(mBuilder, mUnreadBuilder, messages);
@@ -656,7 +656,16 @@ public class NotificationService {
             }
             for (Message message : messages) {
                 final Person sender = message.getStatus() == Message.STATUS_RECEIVED ? getPerson(message) : null;
-                messagingStyle.addMessage(UIHelper.getMessagePreview(mXmppConnectionService, message).first, message.getTimeSent(), sender);
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && isImageMessage(message)) {
+                    final Uri dataUri = FileBackend.getMediaUri(mXmppConnectionService,mXmppConnectionService.getFileBackend().getFile(message));
+                    NotificationCompat.MessagingStyle.Message imageMessage = new NotificationCompat.MessagingStyle.Message(UIHelper.getMessagePreview(mXmppConnectionService, message).first, message.getTimeSent(), sender);
+                    if (dataUri != null) {
+                        imageMessage.setData(message.getMimeType(), dataUri);
+                    }
+                    messagingStyle.addMessage(imageMessage);
+                } else {
+                    messagingStyle.addMessage(UIHelper.getMessagePreview(mXmppConnectionService, message).first, message.getTimeSent(), sender);
+                }
             }
             messagingStyle.setGroupConversation(multiple);
             builder.setStyle(messagingStyle);
@@ -703,16 +712,20 @@ public class NotificationService {
             if (message.getStatus() != Message.STATUS_RECEIVED) {
                 return null;
             }
-            if (message.getType() != Message.TYPE_TEXT
-                    && message.getTransferable() == null
-                    && message.getEncryption() != Message.ENCRYPTION_PGP
-                    && message.getFileParams().height > 0) {
+            if (isImageMessage(message)) {
                 image = message;
             }
         }
         return image;
     }
 
+    private static boolean isImageMessage(Message message) {
+        return message.getType() != Message.TYPE_TEXT
+                && message.getTransferable() == null
+                && message.getEncryption() != Message.ENCRYPTION_PGP
+                && message.getFileParams().height > 0;
+    }
+
     private Message getFirstDownloadableMessage(final Iterable<Message> messages) {
         for (final Message message : messages) {
             if (message.getTransferable() != null || (message.getType() == Message.TYPE_TEXT && message.treatAsDownloadable())) {

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java 🔗

@@ -122,8 +122,11 @@ public class JingleConnection implements Transferable {
 					if (message.getEncryption() == Message.ENCRYPTION_PGP) {
 						account.getPgpDecryptionService().decrypt(message, true);
 					} else {
-						JingleConnection.this.mXmppConnectionService.getNotificationService().push(message);
+						mXmppConnectionService.getFileBackend().updateMediaScanner(file, () -> JingleConnection.this.mXmppConnectionService.getNotificationService().push(message));
+
 					}
+					Log.d(Config.LOGTAG,"successfully transmitted file:" + file.getAbsolutePath()+" ("+ CryptoHelper.bytesToHex(file.getSha1Sum())+")");
+					return;
 				}
 			} else {
 				if (ftVersion == Content.Version.FT_5) { //older Conversations will break when receiving a session-info