diff options
author | Christian Schneppe <christian@pix-art.de> | 2017-05-31 21:49:40 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2017-05-31 21:49:40 +0200 |
commit | c741b33bc22fc87eb75dbc448898ebeba88dbe0c (patch) | |
tree | cb7935fba0e0b7c19550e1ceb93b02ea26442f95 /src/main/java/de/pixart/messenger/services | |
parent | 21bf06c064554c406a6b769160c36a471da45e07 (diff) |
add the 4 most frequently contacted contacts as app shortcuts
Diffstat (limited to '')
3 files changed, 164 insertions, 4 deletions
diff --git a/src/main/java/de/pixart/messenger/services/AvatarService.java b/src/main/java/de/pixart/messenger/services/AvatarService.java index 15c49940f..3d3af8d26 100644 --- a/src/main/java/de/pixart/messenger/services/AvatarService.java +++ b/src/main/java/de/pixart/messenger/services/AvatarService.java @@ -3,9 +3,12 @@ package de.pixart.messenger.services; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Typeface; import android.net.Uri; +import android.util.DisplayMetrics; import android.util.Log; import java.util.ArrayList; @@ -69,6 +72,24 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { return avatar; } + public Bitmap getRoundedShortcut(final Contact contact) { + DisplayMetrics metrics = mXmppConnectionService.getResources().getDisplayMetrics(); + int size = Math.round(metrics.density * 48); + Bitmap bitmap = get(contact, size); + Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(output); + + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + return output; + } + public Bitmap get(final MucOptions.User user, final int size, boolean cachedOnly) { Contact c = user.getContact(); if (c != null && (c.getProfilePhoto() != null || c.getAvatar() != null || user.getAvatar() == null)) { diff --git a/src/main/java/de/pixart/messenger/services/ShortcutService.java b/src/main/java/de/pixart/messenger/services/ShortcutService.java new file mode 100644 index 000000000..56345c663 --- /dev/null +++ b/src/main/java/de/pixart/messenger/services/ShortcutService.java @@ -0,0 +1,131 @@ +package de.pixart.messenger.services; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import android.graphics.drawable.Icon; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import de.pixart.messenger.Config; +import de.pixart.messenger.entities.Account; +import de.pixart.messenger.entities.Contact; +import de.pixart.messenger.ui.StartConversationActivity; +import de.pixart.messenger.utils.ReplacingSerialSingleThreadExecutor; +import de.pixart.messenger.xmpp.jid.Jid; + +public class ShortcutService { + private final XmppConnectionService xmppConnectionService; + private final ReplacingSerialSingleThreadExecutor replacingSerialSingleThreadExecutor = new ReplacingSerialSingleThreadExecutor(false); + + public ShortcutService(XmppConnectionService xmppConnectionService) { + this.xmppConnectionService = xmppConnectionService; + } + + public void refresh() { + refresh(false); + } + + public void refresh(final boolean forceUpdate) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + final Runnable r = new Runnable() { + @Override + public void run() { + refreshImpl(forceUpdate); + } + }; + replacingSerialSingleThreadExecutor.execute(r); + } + } + + @TargetApi(25) + public void report(Contact contact) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class); + shortcutManager.reportShortcutUsed(getShortcutId(contact)); + } + } + + @TargetApi(25) + private void refreshImpl(boolean forceUpdate) { + List<FrequentContact> frequentContacts = xmppConnectionService.databaseBackend.getFrequentContacts(30); + HashMap<String, Account> accounts = new HashMap<>(); + for (Account account : xmppConnectionService.getAccounts()) { + accounts.put(account.getUuid(), account); + } + List<Contact> contacts = new ArrayList<>(); + for (FrequentContact frequentContact : frequentContacts) { + Account account = accounts.get(frequentContact.account); + if (account != null) { + contacts.add(account.getRoster().getContact(frequentContact.contact)); + } + } + ShortcutManager shortcutManager = xmppConnectionService.getSystemService(ShortcutManager.class); + boolean needsUpdate = forceUpdate || contactsChanged(contacts, shortcutManager.getDynamicShortcuts()); + if (!needsUpdate) { + Log.d(Config.LOGTAG, "skipping shortcut update"); + return; + } + List<ShortcutInfo> newDynamicShortCuts = new ArrayList<>(); + for (Contact contact : contacts) { + ShortcutInfo shortcut = new ShortcutInfo.Builder(xmppConnectionService, getShortcutId(contact)) + .setShortLabel(contact.getDisplayName()) + .setIntent(getShortcutIntent(contact)) + .setIcon(Icon.createWithBitmap(xmppConnectionService.getAvatarService().getRoundedShortcut(contact))) + .build(); + newDynamicShortCuts.add(shortcut); + } + if (shortcutManager.setDynamicShortcuts(newDynamicShortCuts)) { + Log.d(Config.LOGTAG, "updated dynamic shortcuts"); + } else { + Log.d(Config.LOGTAG, "unable to update dynamic shortcuts"); + } + } + + private static boolean contactsChanged(List<Contact> needles, List<ShortcutInfo> haystack) { + for (Contact needle : needles) { + if (!contactExists(needle, haystack)) { + return true; + } + } + return needles.size() != haystack.size(); + } + + @TargetApi(25) + private static boolean contactExists(Contact needle, List<ShortcutInfo> haystack) { + for (ShortcutInfo shortcutInfo : haystack) { + if (getShortcutId(needle).equals(shortcutInfo.getId()) && needle.getDisplayName().equals(shortcutInfo.getShortLabel())) { + return true; + } + } + return false; + } + + private static String getShortcutId(Contact contact) { + return contact.getAccount().getJid().toBareJid().toPreppedString() + "#" + contact.getJid().toBareJid().toPreppedString(); + } + + private Intent getShortcutIntent(Contact contact) { + Intent intent = new Intent(xmppConnectionService, StartConversationActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse("xmpp:" + contact.getJid().toBareJid().toString())); + intent.putExtra("account", contact.getAccount().getJid().toBareJid().toString()); + return intent; + } + + public static class FrequentContact { + private final String account; + private final Jid contact; + + public FrequentContact(String account, Jid contact) { + this.account = account; + this.contact = contact; + } + } +} diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 61a9d2318..27412e1ea 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -70,6 +70,7 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import de.duenndns.ssl.MemorizingTrustManager; @@ -189,8 +190,9 @@ public class XmppConnectionService extends Service { }; private FileBackend fileBackend = new FileBackend(this); private MemorizingTrustManager mMemorizingTrustManager; - private NotificationService mNotificationService = new NotificationService( - this); + private NotificationService mNotificationService = new NotificationService(this); + private ShortcutService mShortcutService = new ShortcutService(this); + private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false); private OnMessagePacketReceived mMessageParser = new MessageParser(this); private OnPresencePacketReceived mPresenceParser = new PresenceParser(this); private IqParser mIqParser = new IqParser(this); @@ -1663,6 +1665,7 @@ public class XmppConnectionService extends Service { } } Log.d(Config.LOGTAG, "finished merging phone contacts"); + mShortcutService.refresh(mInitialAddressbookSyncCompleted.compareAndSet(false, true)); updateAccountUi(); } }); @@ -3788,10 +3791,11 @@ public class XmppConnectionService extends Service { return this.mMessageArchiveService; } - public List<Contact> findContacts(Jid jid) { + public List<Contact> findContacts(Jid jid, String accountJid) { ArrayList<Contact> contacts = new ArrayList<>(); for (Account account : getAccounts()) { - if (!account.isOptionSet(Account.OPTION_DISABLED)) { + if (!account.isOptionSet(Account.OPTION_DISABLED) + && (accountJid == null || accountJid.equals(account.getJid().toBareJid().toString()))) { Contact contact = account.getRoster().getContactFromRoster(jid); if (contact != null) { contacts.add(contact); @@ -4176,6 +4180,10 @@ public class XmppConnectionService extends Service { } } + public ShortcutService getShortcutService() { + return mShortcutService; + } + public interface OnMamPreferencesFetched { void onPreferencesFetched(Element prefs); |