diff --git a/build.gradle b/build.gradle
index d92c161dd..7a8ccfef3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -48,11 +48,11 @@ dependencies {
android {
compileSdkVersion 23
- buildToolsVersion "23.0.1"
+ buildToolsVersion "23.0.2"
defaultConfig {
minSdkVersion 14
- targetSdkVersion 21
+ targetSdkVersion 23
versionCode 109
versionName "1.8.0"
project.ext.set(archivesBaseName, archivesBaseName + "-" + versionName);
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 9f434a626..2f93480e3 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -136,6 +136,9 @@
+
+
+
+
+
+
diff --git a/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java b/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java
new file mode 100644
index 000000000..c2a45bf28
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java
@@ -0,0 +1,87 @@
+package eu.siacs.conversations.services;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.graphics.drawable.Icon;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.service.chooser.ChooserTarget;
+import android.service.chooser.ChooserTargetService;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.ui.ShareWithActivity;
+
+@TargetApi(Build.VERSION_CODES.M)
+public class ContactChooserTargetService extends ChooserTargetService implements ServiceConnection {
+
+ private final Object lock = new Object();
+
+ private XmppConnectionService mXmppConnectionService;
+
+ private final int MAX_TARGETS = 5;
+
+ @Override
+ public List onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
+ Intent intent = new Intent(this, XmppConnectionService.class);
+ intent.setAction("contact_chooser");
+ startService(intent);
+ bindService(intent, this, Context.BIND_AUTO_CREATE);
+ ArrayList chooserTargets = new ArrayList<>();
+ try {
+ waitForService();
+ final ArrayList conversations = new ArrayList<>();
+ if (!mXmppConnectionService.areMessagesInitialized()) {
+ return chooserTargets;
+ }
+ mXmppConnectionService.populateWithOrderedConversations(conversations, false);
+ final ComponentName componentName = new ComponentName(this, ShareWithActivity.class);
+ final int pixel = (int) (48 * getResources().getDisplayMetrics().density);
+ for(int i = 0; i < Math.min(conversations.size(),MAX_TARGETS); ++i) {
+ final Conversation conversation = conversations.get(i);
+ final String name = conversation.getName();
+ final Icon icon = Icon.createWithBitmap(mXmppConnectionService.getAvatarService().get(conversation, pixel));
+ final float score = (1.0f / MAX_TARGETS) * i;
+ final Bundle extras = new Bundle();
+ extras.putString("uuid", conversation.getUuid());
+ chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras));
+ }
+ } catch (InterruptedException e) {
+ }
+ unbindService(this);
+ return chooserTargets;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ XmppConnectionService.XmppConnectionBinder binder = (XmppConnectionService.XmppConnectionBinder) service;
+ mXmppConnectionService = binder.getService();
+ synchronized (this.lock) {
+ lock.notifyAll();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mXmppConnectionService = null;
+ }
+
+ private void waitForService() throws InterruptedException {
+ if (mXmppConnectionService == null) {
+ synchronized (this.lock) {
+ lock.wait();
+ }
+ }
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
index 35f1ff359..3cd2f384f 100644
--- a/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java
@@ -4,6 +4,7 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -17,6 +18,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
@@ -33,6 +35,7 @@ public class ShareWithActivity extends XmppActivity {
public String account;
public String contact;
public String text;
+ public String uuid;
}
private Share share;
@@ -40,6 +43,7 @@ public class ShareWithActivity extends XmppActivity {
private static final int REQUEST_START_NEW_CONVERSATION = 0x0501;
private ListView mListView;
private List mConversations = new ArrayList<>();
+ private Toast mToast;
private UiCallback attachFileCallback = new UiCallback() {
@@ -50,8 +54,22 @@ public class ShareWithActivity extends XmppActivity {
}
@Override
- public void success(Message message) {
+ public void success(final Message message) {
xmppConnectionService.sendMessage(message);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ if (share.uuid != null) {
+ mToast = Toast.makeText(getApplicationContext(),
+ getString(share.image ? R.string.shared_image_with_x : R.string.shared_file_with_x,message.getConversation().getName()),
+ Toast.LENGTH_SHORT);
+ mToast.show();
+ }
+ }
+ });
}
@Override
@@ -128,6 +146,8 @@ public class ShareWithActivity extends XmppActivity {
return;
}
final String type = intent.getType();
+ Log.d(Config.LOGTAG, "action: "+intent.getAction()+ ", type:"+type);
+ share.uuid = intent.getStringExtra("uuid");
if (Intent.ACTION_SEND.equals(intent.getAction())) {
final Uri uri = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
if (type != null && uri != null && !type.equalsIgnoreCase("text/plain")) {
@@ -146,7 +166,11 @@ public class ShareWithActivity extends XmppActivity {
this.share.uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
}
if (xmppConnectionServiceBound) {
- xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0);
+ if (share.uuid != null) {
+ share();
+ } else {
+ xmppConnectionService.populateWithOrderedConversations(mConversations, this.share.uris.size() == 0);
+ }
}
}
@@ -163,7 +187,7 @@ public class ShareWithActivity extends XmppActivity {
@Override
void onBackendConnected() {
if (xmppConnectionServiceBound && share != null
- && share.contact != null && share.account != null) {
+ && ((share.contact != null && share.account != null) || share.uuid != null)) {
share();
return;
}
@@ -172,28 +196,41 @@ public class ShareWithActivity extends XmppActivity {
}
private void share() {
- Account account;
- try {
- account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account));
- } catch (final InvalidJidException e) {
- account = null;
- }
- if (account == null) {
- return;
- }
final Conversation conversation;
- try {
- conversation = xmppConnectionService
- .findOrCreateConversation(account, Jid.fromString(share.contact), false);
- } catch (final InvalidJidException e) {
- return;
+ if (share.uuid != null) {
+ conversation = xmppConnectionService.findConversationByUuid(share.uuid);
+ if (conversation == null) {
+ return;
+ }
+ }else{
+ Account account;
+ try {
+ account = xmppConnectionService.findAccountByJid(Jid.fromString(share.account));
+ } catch (final InvalidJidException e) {
+ account = null;
+ }
+ if (account == null) {
+ return;
+ }
+
+ try {
+ conversation = xmppConnectionService
+ .findOrCreateConversation(account, Jid.fromString(share.contact), false);
+ } catch (final InvalidJidException e) {
+ return;
+ }
}
share(conversation);
}
private void share(final Conversation conversation) {
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP && !hasPgp()) {
- showInstallPgpDialog();
+ if (share.uuid == null) {
+ showInstallPgpDialog();
+ } else {
+ Toast.makeText(this,R.string.openkeychain_not_installed,Toast.LENGTH_SHORT).show();
+ finish();
+ }
return;
}
if (share.uris.size() != 0) {
@@ -201,23 +238,27 @@ public class ShareWithActivity extends XmppActivity {
@Override
public void onPresenceSelected() {
if (share.image) {
- Toast.makeText(getApplicationContext(),
+ mToast = Toast.makeText(getApplicationContext(),
getText(R.string.preparing_image),
- Toast.LENGTH_LONG).show();
+ Toast.LENGTH_LONG);
+ mToast.show();
for (Iterator i = share.uris.iterator(); i.hasNext(); i.remove()) {
ShareWithActivity.this.xmppConnectionService
.attachImageToConversation(conversation, i.next(),
attachFileCallback);
}
} else {
- Toast.makeText(getApplicationContext(),
+ mToast = Toast.makeText(getApplicationContext(),
getText(R.string.preparing_file),
- Toast.LENGTH_LONG).show();
+ Toast.LENGTH_LONG);
+ mToast.show();
ShareWithActivity.this.xmppConnectionService
.attachFileToConversation(conversation, share.uris.get(0),
attachFileCallback);
}
- switchToConversation(conversation, null, true);
+ if (share.uuid == null) {
+ switchToConversation(conversation, null, true);
+ }
finish();
}
};
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 584b419f5..ffbb69ce1 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -91,6 +91,7 @@
Conversations utilizes a third party app called OpenKeychain to encrypt and decrypt messages and to manage your public keys.\n\nOpenKeychain is licensed under GPLv3 and available on F-Droid and Google Play.\n\n(Please restart Conversations afterwards.)
Restart
Install
+ Please install OpenKeychain
offering…
waiting…
No OpenPGP Key found
@@ -554,4 +555,6 @@
- %d message
- %d messages
+ Shared file with %s
+ Shared image with %s