ContactChooserTargetService.java

  1package eu.siacs.conversations.services;
  2
  3import android.annotation.SuppressLint;
  4import android.annotation.TargetApi;
  5import android.content.ComponentName;
  6import android.content.Context;
  7import android.content.Intent;
  8import android.content.IntentFilter;
  9import android.content.ServiceConnection;
 10import android.graphics.drawable.Icon;
 11import android.os.Build;
 12import android.os.Bundle;
 13import android.os.IBinder;
 14import android.service.chooser.ChooserTarget;
 15import android.service.chooser.ChooserTargetService;
 16import android.util.Log;
 17
 18import java.util.ArrayList;
 19import java.util.Collections;
 20import java.util.List;
 21
 22import eu.siacs.conversations.Config;
 23import eu.siacs.conversations.entities.Conversation;
 24import eu.siacs.conversations.persistance.FileBackend;
 25import eu.siacs.conversations.ui.ConversationsActivity;
 26import eu.siacs.conversations.utils.Compatibility;
 27
 28@SuppressLint("Deprecated")
 29@TargetApi(Build.VERSION_CODES.M)
 30public class ContactChooserTargetService extends ChooserTargetService implements ServiceConnection {
 31
 32    private final Object lock = new Object();
 33    private static final int MAX_TARGETS = 5;
 34    private XmppConnectionService mXmppConnectionService;
 35
 36    private static boolean textOnly(IntentFilter filter) {
 37        for (int i = 0; i < filter.countDataTypes(); ++i) {
 38            if (!"text/plain".equals(filter.getDataType(i))) {
 39                return false;
 40            }
 41        }
 42        return true;
 43    }
 44
 45    @Override
 46    public List<ChooserTarget> onGetChooserTargets(
 47            final ComponentName targetActivityName, final IntentFilter matchedFilter) {
 48        if (!EventReceiver.hasEnabledAccounts(this)) {
 49            return Collections.emptyList();
 50        }
 51        final Intent intent = new Intent(this, XmppConnectionService.class);
 52        intent.setAction("contact_chooser");
 53        Compatibility.startService(this, intent);
 54        bindService(intent, this, Context.BIND_AUTO_CREATE);
 55        try {
 56            waitForService();
 57            if (!mXmppConnectionService.areMessagesInitialized()) {
 58                return Collections.emptyList();
 59            }
 60            final ArrayList<Conversation> conversations = new ArrayList<>();
 61            mXmppConnectionService.populateWithOrderedConversations(
 62                    conversations, textOnly(matchedFilter));
 63            final ComponentName componentName =
 64                    new ComponentName(this, ConversationsActivity.class);
 65            final int pixel = AvatarService.getSystemUiAvatarSize(this);
 66            final ArrayList<ChooserTarget> chooserTargets = new ArrayList<>();
 67            for (final Conversation conversation : conversations) {
 68                if (conversation.sentMessagesCount() == 0) {
 69                    continue;
 70                }
 71                final String name = conversation.getName().toString();
 72                final Icon icon =
 73                        Icon.createWithBitmap(FileBackend.drawDrawable(
 74                                mXmppConnectionService.getAvatarService().get(conversation, pixel)));
 75                final float score = 1 - (1.0f / MAX_TARGETS) * chooserTargets.size();
 76                final Bundle extras = new Bundle();
 77                extras.putString(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid());
 78                chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras));
 79                if (chooserTargets.size() >= MAX_TARGETS) {
 80                    return chooserTargets;
 81                }
 82            }
 83            return chooserTargets;
 84        } catch (final InterruptedException e) {
 85            Log.d(
 86                    Config.LOGTAG,
 87                    "Thread got interrupted before binding to XmppConnectionService",
 88                    e);
 89        } finally {
 90            unbindService(this);
 91        }
 92        return Collections.emptyList();
 93    }
 94
 95    @Override
 96    public void onServiceConnected(final ComponentName name, final IBinder service) {
 97        XmppConnectionService.XmppConnectionBinder binder =
 98                (XmppConnectionService.XmppConnectionBinder) service;
 99        mXmppConnectionService = binder.getService();
100        synchronized (this.lock) {
101            lock.notifyAll();
102        }
103    }
104
105    @Override
106    public void onServiceDisconnected(ComponentName name) {
107        mXmppConnectionService = null;
108    }
109
110    private void waitForService() throws InterruptedException {
111        if (mXmppConnectionService == null) {
112            synchronized (this.lock) {
113                lock.wait();
114            }
115        }
116    }
117}