ShortcutService.java

  1package eu.siacs.conversations.services;
  2
  3import android.annotation.TargetApi;
  4import android.content.Intent;
  5import android.content.pm.ShortcutInfo;
  6import android.content.pm.ShortcutManager;
  7import android.graphics.drawable.Icon;
  8import android.net.Uri;
  9import android.os.Build;
 10import android.util.Log;
 11
 12import java.util.ArrayList;
 13import java.util.HashMap;
 14import java.util.List;
 15
 16import eu.siacs.conversations.Config;
 17import eu.siacs.conversations.entities.Account;
 18import eu.siacs.conversations.entities.Contact;
 19import eu.siacs.conversations.ui.StartConversationActivity;
 20import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
 21import rocks.xmpp.addr.Jid;
 22
 23public class ShortcutService {
 24
 25    private final XmppConnectionService xmppConnectionService;
 26    private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor = new ReplacingSerialSingleThreadExecutor(false);
 27
 28    public ShortcutService(XmppConnectionService xmppConnectionService) {
 29        this.xmppConnectionService = xmppConnectionService;
 30    }
 31
 32    public void refresh() {
 33        refresh(false);
 34    }
 35
 36    public void refresh(final boolean forceUpdate) {
 37        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
 38            final Runnable r = new Runnable() {
 39                @Override
 40                public void run() {
 41                    refreshImpl(forceUpdate);
 42                }
 43            };
 44            replacingSerialSingleThreadExecutor.execute(r);
 45        }
 46    }
 47
 48    @TargetApi(25)
 49    public void report(Contact contact) {
 50        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
 51            ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class);
 52            shortcutManager.reportShortcutUsed(getShortcutId(contact));
 53        }
 54    }
 55
 56    @TargetApi(25)
 57    private void refreshImpl(boolean forceUpdate) {
 58        List<FrequentContact> frequentContacts = xmppConnectionService.databaseBackend.getFrequentContacts(30);
 59        HashMap<String,Account> accounts = new HashMap<>();
 60        for(Account account : xmppConnectionService.getAccounts()) {
 61            accounts.put(account.getUuid(),account);
 62        }
 63        List<Contact> contacts = new ArrayList<>();
 64        for(FrequentContact frequentContact : frequentContacts) {
 65            Account account = accounts.get(frequentContact.account);
 66            if (account != null) {
 67                contacts.add(account.getRoster().getContact(frequentContact.contact));
 68            }
 69        }
 70        ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class);
 71        boolean needsUpdate = forceUpdate || contactsChanged(contacts,shortcutManager.getDynamicShortcuts());
 72        if (!needsUpdate) {
 73            Log.d(Config.LOGTAG,"skipping shortcut update");
 74            return;
 75        }
 76        List<ShortcutInfo> newDynamicShortCuts = new ArrayList<>();
 77        for (Contact contact : contacts) {
 78            ShortcutInfo shortcut = new ShortcutInfo.Builder(xmppConnectionService, getShortcutId(contact))
 79                    .setShortLabel(contact.getDisplayName())
 80                    .setIntent(getShortcutIntent(contact))
 81                    .setIcon(Icon.createWithBitmap(xmppConnectionService.getAvatarService().getRoundedShortcut(contact)))
 82                    .build();
 83            newDynamicShortCuts.add(shortcut);
 84        }
 85        if (shortcutManager.setDynamicShortcuts(newDynamicShortCuts)) {
 86            Log.d(Config.LOGTAG,"updated dynamic shortcuts");
 87        } else {
 88            Log.d(Config.LOGTAG, "unable to update dynamic shortcuts");
 89        }
 90    }
 91
 92    private static boolean contactsChanged(List<Contact> needles, List<ShortcutInfo> haystack) {
 93        for(Contact needle : needles) {
 94            if(!contactExists(needle,haystack)) {
 95                return true;
 96            }
 97        }
 98        return needles.size() != haystack.size();
 99    }
100
101    @TargetApi(25)
102    private static boolean contactExists(Contact needle, List<ShortcutInfo> haystack) {
103        for(ShortcutInfo shortcutInfo : haystack) {
104            if (getShortcutId(needle).equals(shortcutInfo.getId()) && needle.getDisplayName().equals(shortcutInfo.getShortLabel())) {
105                return true;
106            }
107        }
108        return false;
109    }
110
111    private static String getShortcutId(Contact contact) {
112        return contact.getAccount().getJid().asBareJid().toString()+"#"+contact.getJid().asBareJid().toString();
113    }
114
115    private Intent getShortcutIntent(Contact contact) {
116        Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class);
117        intent.setAction(Intent.ACTION_VIEW);
118        intent.setData(Uri.parse("xmpp:"+contact.getJid().asBareJid().toString()));
119        intent.putExtra("account",contact.getAccount().getJid().asBareJid().toString());
120        return intent;
121    }
122
123    public static class FrequentContact {
124        private final String account;
125        private final Jid contact;
126
127        public FrequentContact(String account, Jid contact) {
128            this.account = account;
129            this.contact = contact;
130        }
131    }
132
133}