diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3e9bb545ea..71e173e18f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -316,6 +316,14 @@
+
+
+
+
+
+
diff --git a/res/drawable-hdpi/ic_reply.png b/res/drawable-hdpi/ic_reply.png
new file mode 100644
index 0000000000..b3bae92895
Binary files /dev/null and b/res/drawable-hdpi/ic_reply.png differ
diff --git a/res/drawable-mdpi/ic_reply.png b/res/drawable-mdpi/ic_reply.png
new file mode 100644
index 0000000000..ce00dbc4b4
Binary files /dev/null and b/res/drawable-mdpi/ic_reply.png differ
diff --git a/res/drawable-xhdpi/ic_reply.png b/res/drawable-xhdpi/ic_reply.png
new file mode 100644
index 0000000000..31df111267
Binary files /dev/null and b/res/drawable-xhdpi/ic_reply.png differ
diff --git a/res/drawable-xxhdpi/ic_reply.png b/res/drawable-xxhdpi/ic_reply.png
new file mode 100644
index 0000000000..119006014d
Binary files /dev/null and b/res/drawable-xxhdpi/ic_reply.png differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4363536aa1..6704027544 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -982,6 +982,14 @@
Transport icon
+
+ Reply
+
+ - Yes
+ - No
+ - OK
+ - Thanks
+
diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
index ef3cf8cae8..ef82154ce0 100644
--- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
+++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
@@ -36,6 +36,7 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Action;
import android.support.v4.app.NotificationCompat.BigTextStyle;
import android.support.v4.app.NotificationCompat.InboxStyle;
+import android.support.v4.app.RemoteInput;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -86,6 +87,8 @@ public class MessageNotifier {
private volatile static long visibleThread = -1;
+ public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+
public static void setVisibleThread(long threadId) {
visibleThread = threadId;
}
@@ -222,9 +225,22 @@ public class MessageNotifier {
Action markAsReadAction = new Action(R.drawable.check,
context.getString(R.string.MessageNotifier_mark_read),
notificationState.getMarkAsReadIntent(context, masterSecret));
+
+ Action replyAction = new Action(R.drawable.ic_reply_white_36dp,
+ context.getString(R.string.MessageNotifier_reply),
+ notifications.get(0).getReplyIntent(context));
+
+ Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
+ context.getString(R.string.wear_reply_label),
+ notificationState.getReplyIntent(context, masterSecret, recipient.getRecipientId()))
+ .addRemoteInput(new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(context.getString(R.string.wear_reply_label)).build())
+ .build();
+
builder.addAction(markAsReadAction);
- builder.addAction(new Action(R.drawable.ic_reply_white_36dp, context.getString(R.string.MessageNotifier_reply), notifications.get(0).getReplyIntent(context)));
- builder.extend(new NotificationCompat.WearableExtender().addAction(markAsReadAction));
+ builder.addAction(replyAction);
+
+ builder.extend(new NotificationCompat.WearableExtender().addAction(markAsReadAction)
+ .addAction(wearableReplyAction));
}
SpannableStringBuilder content = new SpannableStringBuilder();
diff --git a/src/org/thoughtcrime/securesms/notifications/NotificationState.java b/src/org/thoughtcrime/securesms/notifications/NotificationState.java
index 3fc3bc15d9..52ac5563bb 100644
--- a/src/org/thoughtcrime/securesms/notifications/NotificationState.java
+++ b/src/org/thoughtcrime/securesms/notifications/NotificationState.java
@@ -4,11 +4,11 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
import org.thoughtcrime.securesms.recipients.Recipients;
@@ -71,6 +71,19 @@ public class NotificationState {
}
public PendingIntent getMarkAsReadIntent(Context context, MasterSecret masterSecret) {
+ Bundle extras = new Bundle();
+ extras.putParcelable("master_secret", masterSecret);
+ return craftIntent(context, MarkReadReceiver.CLEAR_ACTION, extras);
+ }
+
+ public PendingIntent getReplyIntent(Context context, MasterSecret masterSecret, long recipientId) {
+ Bundle extras = new Bundle();
+ extras.putParcelable("master_secret", masterSecret);
+ extras.putLong("recipient_id", recipientId);
+ return craftIntent(context, WearReplyReceiver.REPLY_ACTION, extras);
+ }
+
+ private PendingIntent craftIntent(Context context, String intentAction, Bundle extras) {
long[] threadArray = new long[threads.size()];
int index = 0;
@@ -79,16 +92,16 @@ public class NotificationState {
threadArray[index++] = thread;
}
- Intent intent = new Intent(MarkReadReceiver.CLEAR_ACTION);
+ Intent intent = new Intent(intentAction);
intent.putExtra("thread_ids", threadArray);
- intent.putExtra("master_secret", masterSecret);
+ intent.putExtras(extras);
intent.setPackage(context.getPackageName());
// XXX : This is an Android bug. If we don't pull off the extra
// once before handing off the PendingIntent, the array will be
// truncated to one element when the PendingIntent fires. Thanks guys!
Log.w("NotificationState", "Pending array off intent length: " +
- intent.getLongArrayExtra("thread_ids").length);
+ intent.getLongArrayExtra("thread_ids").length);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
diff --git a/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java b/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java
new file mode 100644
index 0000000000..6929c81f11
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/notifications/WearReplyReceiver.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (C) 2011 Whisper Systems
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.thoughtcrime.securesms.notifications;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.RemoteInput;
+import android.util.Log;
+
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.recipients.RecipientFactory;
+import org.thoughtcrime.securesms.recipients.RecipientProvider;
+import org.thoughtcrime.securesms.recipients.Recipients;
+import org.thoughtcrime.securesms.sms.MessageSender;
+import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
+
+/**
+ * Get the response text from the Wearable Device and sends an message as a reply
+ *
+ * @author Alix Ducros (Ported to TextSecure-Codebase by Christoph Haefner)
+ */
+public class WearReplyReceiver extends BroadcastReceiver {
+
+ public static final String TAG = WearReplyReceiver.class.getSimpleName();
+ public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ if (!intent.getAction().equals(REPLY_ACTION))
+ return;
+
+ Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+ if (remoteInput == null)
+ return;
+
+ final long[] threadIds = intent.getLongArrayExtra("thread_ids");
+ final MasterSecret masterSecret = intent.getParcelableExtra("master_secret");
+ final long recipientId = intent.getLongExtra("recipient_id", -1);
+ final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_VOICE_REPLY);
+
+ final Recipients recipients = RecipientFactory.getRecipientsForIds(context, new long[]{recipientId}, false);
+
+ if (threadIds != null && masterSecret != null) {
+
+ ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
+ .cancel(MessageNotifier.NOTIFICATION_ID);
+
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ for (long threadId : threadIds) {
+ Log.w(TAG, "Marking as read: " + threadId);
+ DatabaseFactory.getThreadDatabase(context).setRead(threadId);
+ }
+
+ OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString());
+ MessageSender.send(context, masterSecret, reply, threadIds[0], false);
+
+ MessageNotifier.updateNotification(context, masterSecret);
+ return null;
+ }
+ }.execute();
+ }
+ }
+}