diff options
author | Daniel Gultsch <daniel@gultsch.de> | 2015-12-06 11:55:37 +0100 |
---|---|---|
committer | Daniel Gultsch <daniel@gultsch.de> | 2015-12-06 11:57:31 +0100 |
commit | 70c8a9d241b824e684aa0579c07a7971470ae42f (patch) | |
tree | 8dce948e0295d6e856fcc85dd091e68520812bc4 | |
parent | 904edf5d59072058b324e7f80ab1201a1535f64e (diff) |
implement direct sharing in android 6.0. fixes #1321
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | src/main/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/services/ContactChooserTargetService.java | 87 | ||||
-rw-r--r-- | src/main/java/eu/siacs/conversations/ui/ShareWithActivity.java | 87 | ||||
-rw-r--r-- | src/main/res/values/strings.xml | 3 |
5 files changed, 164 insertions, 24 deletions
diff --git a/build.gradle b/build.gradle index 48bf2ed3..cc8b61a2 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ android { defaultConfig { minSdkVersion 14 - targetSdkVersion 21 + targetSdkVersion 23 versionCode 108 versionName "1.8.0-beta" project.ext.set(archivesBaseName, archivesBaseName + "-" + versionName); diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 9f434a62..2f93480e 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -136,6 +136,9 @@ <data android:mimeType="image/*"/> </intent-filter> + <meta-data + android:name="android.service.chooser.chooser_target_service" + android:value=".services.ContactChooserTargetService" /> </activity> <activity android:name=".ui.TrustKeysActivity" @@ -155,6 +158,12 @@ </activity> <activity android:name="com.soundcloud.android.crop.CropImageActivity" /> <service android:name=".services.ExportLogsService"/> + <service android:name=".services.ContactChooserTargetService" + android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE"> + <intent-filter> + <action android:name="android.service.chooser.ChooserTargetService" /> + </intent-filter> + </service> </application> </manifest> 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 00000000..c2a45bf2 --- /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<ChooserTarget> 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<ChooserTarget> chooserTargets = new ArrayList<>(); + try { + waitForService(); + final ArrayList<Conversation> 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 35f1ff35..3cd2f384 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<Conversation> mConversations = new ArrayList<>(); + private Toast mToast; private UiCallback<Message> attachFileCallback = new UiCallback<Message>() { @@ -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<Uri> 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 584b419f..ffbb69ce 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -91,6 +91,7 @@ <string name="openkeychain_required_long">Conversations utilizes a third party app called <b>OpenKeychain</b> 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<small>(Please restart Conversations afterwards.)</small></string> <string name="restart">Restart</string> <string name="install">Install</string> + <string name="openkeychain_not_installed">Please install OpenKeychain</string> <string name="offering">offering…</string> <string name="waiting">waiting…</string> <string name="no_pgp_key">No OpenPGP Key found</string> @@ -554,4 +555,6 @@ <item quantity="one">%d message</item> <item quantity="other">%d messages</item> </plurals> + <string name="shared_file_with_x">Shared file with %s</string> + <string name="shared_image_with_x">Shared image with %s</string> </resources> |