From 3f53abedab1ab294dfa2c05256984d6b709c79d3 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 9 Jul 2021 12:59:26 -0300 Subject: [PATCH] Migrate to new Share APIs. --- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 9 +- .../conversation/ConversationActivity.java | 9 +- .../jobs/ConversationShortcutUpdateJob.java | 5 +- .../keyboard/emoji/KeyboardPageSearchView.kt | 4 +- .../notifications/NotificationChannels.java | 1 + .../securesms/service/DirectShareService.java | 149 ------------------ .../securesms/util/AvatarUtil.java | 16 -- .../securesms/util/ConversationUtil.java | 129 +++++++-------- .../securesms/util/ServiceUtil.java | 6 - app/witness-verifications.gradle | 15 +- 11 files changed, 70 insertions(+), 275 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/service/DirectShareService.java diff --git a/app/build.gradle b/app/build.gradle index fdec552b0b..bb863380b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -363,6 +363,7 @@ android { } dependencies { + implementation 'androidx.core:core-ktx:1.5.0' implementation 'androidx.fragment:fragment-ktx:1.2.5' lintChecks project(':lintchecks') @@ -393,6 +394,7 @@ dependencies { implementation "androidx.concurrent:concurrent-futures:1.0.0" implementation "androidx.autofill:autofill:1.0.0" implementation "androidx.biometric:biometric:1.1.0" + implementation "androidx.sharetarget:sharetarget:1.1.0" implementation ('com.google.firebase:firebase-messaging:22.0.0') { exclude group: 'com.google.firebase', module: 'firebase-core' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6fa0306e68..695e0e5f5e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -198,7 +198,7 @@ + android:value="androidx.sharetarget.ChooserTargetServiceCompat" /> @@ -651,13 +651,6 @@ - - - - - - diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 71632b9b5c..b2ccc31e9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -824,14 +824,7 @@ public class ConversationActivity extends PassphraseRequiredActivity } private void reportShortcutLaunch(@NonNull RecipientId recipientId) { - if (Build.VERSION.SDK_INT < ConversationUtil.CONVERSATION_SUPPORT_VERSION) { - return; - } - - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(this); - if (shortcutManager != null) { - shortcutManager.reportShortcutUsed(ConversationUtil.getShortcutId(recipientId)); - } + ShortcutManagerCompat.reportShortcutUsed(this, ConversationUtil.getShortcutId(recipientId)); } private void handleImageFromDeviceCameraApp() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ConversationShortcutUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ConversationShortcutUpdateJob.java index 1736c0f5d9..fa5cd97aca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ConversationShortcutUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ConversationShortcutUpdateJob.java @@ -35,9 +35,7 @@ public class ConversationShortcutUpdateJob extends BaseJob { public static final String KEY = "ConversationShortcutUpdateJob"; public static void enqueue() { - if (Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION) { - ApplicationDependencies.getJobManager().add(new ConversationShortcutUpdateJob()); - } + ApplicationDependencies.getJobManager().add(new ConversationShortcutUpdateJob()); } private ConversationShortcutUpdateJob() { @@ -63,7 +61,6 @@ public class ConversationShortcutUpdateJob extends BaseJob { } @Override - @RequiresApi(CONVERSATION_SUPPORT_VERSION) protected void onRun() throws Exception { if (TextSecurePreferences.isScreenLockEnabled(context)) { Log.i(TAG, "Screen lock enabled. Clearing shortcuts."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt index 7c39017af5..0e3b175e70 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt @@ -13,7 +13,7 @@ import androidx.core.content.ContextCompat import androidx.core.content.res.use import androidx.core.view.ViewCompat import androidx.core.widget.ImageViewCompat -import androidx.core.widget.addTextChangedListener +import androidx.core.widget.doAfterTextChanged import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.animation.AnimationCompleteListener import org.thoughtcrime.securesms.animation.ResizeAnimation @@ -47,7 +47,7 @@ class KeyboardPageSearchView @JvmOverloads constructor( clearButton = findViewById(R.id.emoji_search_clear_icon) input = findViewById(R.id.emoji_search_entry) - input.addTextChangedListener { + input.doAfterTextChanged { if (it.isNullOrEmpty()) { clearButton.setImageDrawable(null) clearButton.isClickable = false diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java index 13b572eb8a..1c5a37fa47 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java @@ -19,6 +19,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; +import androidx.core.app.NotificationChannelCompat; import com.annimon.stream.Collectors; import com.annimon.stream.Stream; diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/DirectShareService.java b/app/src/main/java/org/thoughtcrime/securesms/service/DirectShareService.java deleted file mode 100644 index b15f4400ae..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/service/DirectShareService.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.thoughtcrime.securesms.service; - - -import android.content.ComponentName; -import android.content.Context; -import android.content.IntentFilter; -import android.content.pm.ShortcutInfo; -import android.content.pm.ShortcutManager; -import android.graphics.Bitmap; -import android.graphics.drawable.Icon; -import android.os.Build; -import android.os.Bundle; -import android.service.chooser.ChooserTarget; -import android.service.chooser.ChooserTargetService; - -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; -import androidx.appcompat.view.ContextThemeWrapper; - -import com.annimon.stream.Stream; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.ThreadDatabase; -import org.thoughtcrime.securesms.database.model.ThreadRecord; -import org.thoughtcrime.securesms.mms.GlideApp; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.sharing.ShareActivity; -import org.thoughtcrime.securesms.util.AvatarUtil; -import org.thoughtcrime.securesms.util.BitmapUtil; -import org.thoughtcrime.securesms.util.ConversationUtil; -import org.thoughtcrime.securesms.util.FeatureFlags; -import org.thoughtcrime.securesms.util.ServiceUtil; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -@RequiresApi(api = Build.VERSION_CODES.M) -public class DirectShareService extends ChooserTargetService { - - - private static final String TAG = Log.tag(DirectShareService.class); - private static final int MAX_TARGETS = 10; - - @Override - public List onGetChooserTargets(ComponentName targetActivityName, - IntentFilter matchedFilter) - { - Map results = new LinkedHashMap<>(); - - if (Build.VERSION.SDK_INT >= ConversationUtil.CONVERSATION_SUPPORT_VERSION) { - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(this); - if (shortcutManager != null && !shortcutManager.getDynamicShortcuts().isEmpty()) { - addChooserTargetsFromDynamicShortcuts(results, shortcutManager.getDynamicShortcuts()); - } - - if (results.size() >= MAX_TARGETS) { - return new ArrayList<>(results.values()); - } - } - - ComponentName componentName = new ComponentName(this, ShareActivity.class); - ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(this); - - try (ThreadDatabase.Reader reader = threadDatabase.readerFor(threadDatabase.getRecentConversationList(MAX_TARGETS, false, true))) { - ThreadRecord record; - - while ((record = reader.getNext()) != null) { - if (results.containsKey(record.getRecipient().getId())) { - continue; - } - - Recipient recipient = Recipient.resolved(record.getRecipient().getId()); - String name = recipient.getDisplayName(this); - - Bitmap avatar; - - if (recipient.getContactPhoto() != null) { - try { - avatar = GlideApp.with(this) - .asBitmap() - .load(recipient.getContactPhoto()) - .circleCrop() - .submit(getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width), - getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width)) - .get(); - } catch (InterruptedException | ExecutionException e) { - Log.w(TAG, e); - avatar = getFallbackDrawable(recipient); - } - } else { - avatar = getFallbackDrawable(recipient); - } - - Bundle bundle = buildExtras(record); - - results.put(recipient.getId(), new ChooserTarget(name, Icon.createWithBitmap(avatar), 1.0f, componentName, bundle)); - } - - return new ArrayList<>(results.values()); - } - } - - private @NonNull Bundle buildExtras(@NonNull ThreadRecord threadRecord) { - Bundle bundle = new Bundle(); - - bundle.putLong(ShareActivity.EXTRA_THREAD_ID, threadRecord.getThreadId()); - bundle.putString(ShareActivity.EXTRA_RECIPIENT_ID, threadRecord.getRecipient().getId().serialize()); - bundle.putInt(ShareActivity.EXTRA_DISTRIBUTION_TYPE, threadRecord.getDistributionType()); - - return bundle; - } - - private Bitmap getFallbackDrawable(@NonNull Recipient recipient) { - Context themedContext = new ContextThemeWrapper(this, R.style.TextSecure_LightTheme); - return BitmapUtil.createFromDrawable(recipient.getFallbackContactPhotoDrawable(themedContext, false), - getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width), - getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height)); - } - - @RequiresApi(ConversationUtil.CONVERSATION_SUPPORT_VERSION) - private void addChooserTargetsFromDynamicShortcuts(@NonNull Map targetMap, @NonNull List shortcutInfos) { - Stream.of(shortcutInfos) - .sorted((lhs, rhs) -> Integer.compare(lhs.getRank(), rhs.getRank())) - .takeWhileIndexed((idx, info) -> idx < MAX_TARGETS) - .forEach(info -> { - Recipient recipient = Recipient.resolved(RecipientId.from(info.getId())); - ChooserTarget target = buildChooserTargetFromShortcutInfo(info, recipient); - - targetMap.put(RecipientId.from(info.getId()), target); - }); - } - - @RequiresApi(ConversationUtil.CONVERSATION_SUPPORT_VERSION) - private @NonNull ChooserTarget buildChooserTargetFromShortcutInfo(@NonNull ShortcutInfo info, @NonNull Recipient recipient) { - ThreadRecord threadRecord = DatabaseFactory.getThreadDatabase(this).getThreadRecordFor(recipient); - - return new ChooserTarget(info.getShortLabel(), - AvatarUtil.getIconForShortcut(this, recipient), - info.getRank() / ((float) MAX_TARGETS), - new ComponentName(this, ShareActivity.class), - buildExtras(threadRecord)); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/AvatarUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/AvatarUtil.java index fc82c5e452..105071ff87 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/AvatarUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/AvatarUtil.java @@ -3,13 +3,11 @@ package org.thoughtcrime.securesms.util; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; import android.view.View; import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.WorkerThread; import androidx.appcompat.widget.AppCompatImageView; import androidx.core.content.ContextCompat; @@ -100,20 +98,6 @@ public final class AvatarUtil { } } - @RequiresApi(ConversationUtil.CONVERSATION_SUPPORT_VERSION) - @WorkerThread - public static @NonNull Icon getIconForShortcut(@NonNull Context context, @NonNull Recipient recipient) { - try { - GlideRequest glideRequest = GlideApp.with(context).asBitmap().load(new ConversationShortcutPhoto(recipient)); - if (recipient.shouldBlurAvatar()) { - glideRequest = glideRequest.transform(new BlurTransformation(context, 0.25f, BlurTransformation.MAX_RADIUS)); - } - return Icon.createWithAdaptiveBitmap(glideRequest.submit().get()); - } catch (ExecutionException | InterruptedException e) { - throw new AssertionError("This call should not fail.", e); - } - } - @WorkerThread public static @NonNull IconCompat getIconCompatForShortcut(@NonNull Context context, @NonNull Recipient recipient) { try { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java index c145e8f8df..fa37473671 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java @@ -1,16 +1,15 @@ package org.thoughtcrime.securesms.util; -import android.app.Person; import android.content.ComponentName; import android.content.Context; -import android.content.pm.ShortcutInfo; -import android.content.pm.ShortcutManager; -import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.WorkerThread; +import androidx.core.app.Person; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.content.pm.ShortcutManagerCompat; import com.annimon.stream.Stream; @@ -37,7 +36,7 @@ import java.util.Set; */ public final class ConversationUtil { - public static final int CONVERSATION_SUPPORT_VERSION = 30; + public static final int CONVERSATION_SUPPORT_VERSION = 30; private static final String TAG = Log.tag(ConversationUtil.class); @@ -49,7 +48,7 @@ public final class ConversationUtil { */ @WorkerThread public static @NonNull String getChannelId(@NonNull Context context, @NonNull Recipient recipient) { - Recipient resolved = recipient.resolve(); + Recipient resolved = recipient.resolve(); return resolved.getNotificationChannel() != null ? resolved.getNotificationChannel() : NotificationChannels.getMessagesChannel(context); } @@ -63,24 +62,21 @@ public final class ConversationUtil { /** * Synchronously pushes a new dynamic shortcut for the given recipient if one does not already exist. - * + *

* If added, this recipient is given a high ranking with the intention of not appearing immediately in results. */ @WorkerThread public static void pushShortcutForRecipientIfNeededSync(@NonNull Context context, @NonNull Recipient recipient) { - if (Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION) { - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); - String shortcutId = getShortcutId(recipient); - List shortcuts = shortcutManager.getDynamicShortcuts(); + String shortcutId = getShortcutId(recipient); + List shortcuts = ShortcutManagerCompat.getDynamicShortcuts(context); - boolean hasPushedRecipientShortcut = Stream.of(shortcuts) - .filter(info -> Objects.equals(shortcutId, info.getId())) - .findFirst() - .isPresent(); + boolean hasPushedRecipientShortcut = Stream.of(shortcuts) + .filter(info -> Objects.equals(shortcutId, info.getId())) + .findFirst() + .isPresent(); - if (!hasPushedRecipientShortcut) { - pushShortcutForRecipientInternal(context, recipient, shortcuts.size()); - } + if (!hasPushedRecipientShortcut) { + pushShortcutForRecipientInternal(context, recipient, shortcuts.size()); } } @@ -88,33 +84,26 @@ public final class ConversationUtil { * Clears all currently set dynamic shortcuts */ public static void clearAllShortcuts(@NonNull Context context) { - if (Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION) { - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); - List shortcutInfos = shortcutManager.getDynamicShortcuts(); + List shortcutInfos = ShortcutManagerCompat.getDynamicShortcuts(context); - shortcutManager.removeLongLivedShortcuts(Stream.of(shortcutInfos).map(ShortcutInfo::getId).toList()); - } + ShortcutManagerCompat.removeLongLivedShortcuts(context, Stream.of(shortcutInfos).map(ShortcutInfoCompat::getId).toList()); } /** * Clears the shortcuts tied to a given thread. */ public static void clearShortcuts(@NonNull Context context, @NonNull Set threadIds) { - if (Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION) { - SignalExecutors.BOUNDED.execute(() -> { - List recipientIds = DatabaseFactory.getThreadDatabase(context).getRecipientIdsForThreadIds(threadIds); - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); + SignalExecutors.BOUNDED.execute(() -> { + List recipientIds = DatabaseFactory.getThreadDatabase(context).getRecipientIdsForThreadIds(threadIds); - shortcutManager.removeLongLivedShortcuts(Stream.of(recipientIds).map(ConversationUtil::getShortcutId).toList()); - }); - } + ShortcutManagerCompat.removeLongLivedShortcuts(context, Stream.of(recipientIds).map(ConversationUtil::getShortcutId).toList()); + }); } /** * Returns an ID that is unique between all recipients. * * @param recipientId The recipient ID to get a shortcut ID for - * * @return A unique identifier that is stable for a given recipient id */ public static @NonNull String getShortcutId(@NonNull RecipientId recipientId) { @@ -125,7 +114,6 @@ public final class ConversationUtil { * Returns an ID that is unique between all recipients. * * @param recipient The recipient to get a shortcut for. - * * @return A unique identifier that is stable for a given recipient id */ public static @NonNull String getShortcutId(@NonNull Recipient recipient) { @@ -148,10 +136,8 @@ public final class ConversationUtil { } } - @RequiresApi(CONVERSATION_SUPPORT_VERSION) public static int getMaxShortcuts(@NonNull Context context) { - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); - return Math.min(shortcutManager.getMaxShortcutCountPerActivity(), 150); + return Math.min(ShortcutManagerCompat.getMaxShortcutCountPerActivity(context), 150); } /** @@ -162,42 +148,37 @@ public final class ConversationUtil { * recipient should be first in the list. * @return True if the update was successful, false if we were rate-limited. */ - @RequiresApi(CONVERSATION_SUPPORT_VERSION) @WorkerThread public static boolean setActiveShortcuts(@NonNull Context context, @NonNull List rankedRecipients) { - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); - - if (shortcutManager.isRateLimitingActive()) { + if (ShortcutManagerCompat.isRateLimitingActive(context)) { return false; } - int maxShortcuts = shortcutManager.getMaxShortcutCountPerActivity(); + int maxShortcuts = ShortcutManagerCompat.getMaxShortcutCountPerActivity(context); if (rankedRecipients.size() > maxShortcuts) { Log.w(TAG, "Too many recipients provided! Provided: " + rankedRecipients.size() + ", Max: " + maxShortcuts); rankedRecipients = rankedRecipients.subList(0, maxShortcuts); } - List shortcuts = new ArrayList<>(rankedRecipients.size()); + List shortcuts = new ArrayList<>(rankedRecipients.size()); for (int i = 0; i < rankedRecipients.size(); i++) { - ShortcutInfo info = buildShortcutInfo(context, rankedRecipients.get(i), i); + ShortcutInfoCompat info = buildShortcutInfo(context, rankedRecipients.get(i), i); shortcuts.add(info); } - return shortcutManager.setDynamicShortcuts(shortcuts); + return ShortcutManagerCompat.setDynamicShortcuts(context, shortcuts); } /** * Pushes a dynamic shortcut for a given recipient to the shortcut manager */ - @RequiresApi(CONVERSATION_SUPPORT_VERSION) @WorkerThread private static void pushShortcutForRecipientInternal(@NonNull Context context, @NonNull Recipient recipient, int rank) { - ShortcutInfo shortcutInfo = buildShortcutInfo(context, recipient, rank); - ShortcutManager shortcutManager = ServiceUtil.getShortcutManager(context); + ShortcutInfoCompat shortcutInfo = buildShortcutInfo(context, recipient, rank); - shortcutManager.pushDynamicShortcut(shortcutInfo); + ShortcutManagerCompat.pushDynamicShortcut(context, shortcutInfo); } /** @@ -206,13 +187,12 @@ public final class ConversationUtil { * @param context The Context under which we are operating * @param recipient The Recipient to generate a ShortcutInfo for * @param rank The rank that should be assigned to this recipient - * @return The new ShortcutInfo + * @return The new ShortcutInfo */ - @RequiresApi(CONVERSATION_SUPPORT_VERSION) @WorkerThread - private static @NonNull ShortcutInfo buildShortcutInfo(@NonNull Context context, - @NonNull Recipient recipient, - int rank) + private static @NonNull ShortcutInfoCompat buildShortcutInfo(@NonNull Context context, + @NonNull Recipient recipient, + int rank) { Recipient resolved = recipient.resolve(); Person[] persons = buildPersons(context, resolved); @@ -220,49 +200,46 @@ public final class ConversationUtil { String shortName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getShortDisplayName(context); String longName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getDisplayName(context); - return new ShortcutInfo.Builder(context, getShortcutId(resolved)) - .setLongLived(true) - .setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId).build()) - .setShortLabel(shortName) - .setLongLabel(longName) - .setIcon(AvatarUtil.getIconForShortcut(context, resolved)) - .setPersons(persons) - .setCategories(Collections.singleton(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION)) - .setActivity(new ComponentName(context, "org.thoughtcrime.securesms.RoutingActivity")) - .setRank(rank) - .build(); + return new ShortcutInfoCompat.Builder(context, getShortcutId(resolved)) + .setLongLived(true) + .setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId).build()) + .setShortLabel(shortName) + .setLongLabel(longName) + .setIcon(AvatarUtil.getIconCompatForShortcut(context, resolved)) + .setPersons(persons) + .setCategories(Collections.singleton("android.shortcut.conversation")) + .setActivity(new ComponentName(context, "org.thoughtcrime.securesms.RoutingActivity")) + .setRank(rank) + .build(); } /** * @return an array of Person objects correlating to members of a conversation (other than self) */ - @RequiresApi(CONVERSATION_SUPPORT_VERSION) @WorkerThread private static @NonNull Person[] buildPersons(@NonNull Context context, @NonNull Recipient recipient) { if (recipient.isGroup()) { return buildPersonsForGroup(context, recipient.getGroupId().get()); } else { - return new Person[]{buildPerson(context, recipient)}; + return new Person[] { buildPerson(context, recipient) }; } } /** * @return an array of Person objects correlating to members of a group (other than self) */ - @RequiresApi(CONVERSATION_SUPPORT_VERSION) @WorkerThread private static @NonNull Person[] buildPersonsForGroup(@NonNull Context context, @NonNull GroupId groupId) { List members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF); - return Stream.of(members).map(member -> buildPerson(context, member.resolve())).toArray(Person[]::new); + return Stream.of(members).map(member -> buildPersonWithoutIcon(context, member.resolve())).toArray(Person[]::new); } /** * @return A Person object representing the given Recipient */ - @RequiresApi(28) @WorkerThread - public static @NonNull Person buildPerson(@NonNull Context context, @NonNull Recipient recipient) { + public static @NonNull Person buildPersonWithoutIcon(@NonNull Context context, @NonNull Recipient recipient) { return new Person.Builder() .setKey(getShortcutId(recipient.getId())) .setName(recipient.getDisplayName(context)) @@ -274,12 +251,12 @@ public final class ConversationUtil { * @return A Compat Library Person object representing the given Recipient */ @WorkerThread - public static @NonNull androidx.core.app.Person buildPersonCompat(@NonNull Context context, @NonNull Recipient recipient) { - return new androidx.core.app.Person.Builder() - .setKey(getShortcutId(recipient.getId())) - .setName(recipient.getDisplayName(context)) - .setIcon(AvatarUtil.getIconForNotification(context, recipient)) - .setUri(recipient.isSystemContact() ? recipient.getContactUri().toString() : null) - .build(); + public static @NonNull Person buildPerson(@NonNull Context context, @NonNull Recipient recipient) { + return new Person.Builder() + .setKey(getShortcutId(recipient.getId())) + .setName(recipient.getDisplayName(context)) + .setIcon(AvatarUtil.getIconForNotification(context, recipient)) + .setUri(recipient.isSystemContact() ? recipient.getContactUri().toString() : null) + .build(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ServiceUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ServiceUtil.java index 86b2158a1c..e5294a025f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ServiceUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ServiceUtil.java @@ -8,7 +8,6 @@ import android.app.NotificationManager; import android.app.job.JobScheduler; import android.content.ClipboardManager; import android.content.Context; -import android.content.pm.ShortcutManager; import android.hardware.SensorManager; import android.hardware.display.DisplayManager; import android.location.LocationManager; @@ -35,11 +34,6 @@ public class ServiceUtil { return (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); } - @RequiresApi(25) - public static @Nullable ShortcutManager getShortcutManager(@NonNull Context context) { - return ContextCompat.getSystemService(context, ShortcutManager.class); - } - public static WindowManager getWindowManager(Context context) { return (WindowManager) context.getSystemService(Activity.WINDOW_SERVICE); } diff --git a/app/witness-verifications.gradle b/app/witness-verifications.gradle index a1ee83fbdc..f00b164160 100644 --- a/app/witness-verifications.gradle +++ b/app/witness-verifications.gradle @@ -69,11 +69,11 @@ dependencyVerification { ['androidx.coordinatorlayout:coordinatorlayout:1.1.0', '44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'], - ['androidx.core:core-ktx:1.1.0', - '070cc5f8864f449128a2f4b25ca5b67aa3adca3ee1bd611e2eaf1a18fad83178'], + ['androidx.core:core-ktx:1.5.0', + '5964cfe7a4882da2a00fb6ca3d3a072d04139208186f7bc4b3cb66022764fc42'], - ['androidx.core:core:1.3.2', - '94de196cd67950cff6ef3e1ac59015f8eaaf61840bdc238f2cf54ddef8dd0be9'], + ['androidx.core:core:1.5.0', + '2b279712795689069cfb63e48b3ab63c32a5649bdda44c482eb8f81ca1a72161'], ['androidx.cursoradapter:cursoradapter:1.0.0', 'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'], @@ -195,6 +195,9 @@ dependencyVerification { ['androidx.savedstate:savedstate:1.0.0', '2510a5619c37579c9ce1a04574faaf323cd0ffe2fc4e20fa8f8f01e5bb402e83'], + ['androidx.sharetarget:sharetarget:1.1.0', + '618574dca0dcfc644282c1ec65c159fc349e6c500dc77444ada39b42638a3824'], + ['androidx.slidingpanelayout:slidingpanelayout:1.0.0', '76bffb7cefbf780794d8817002dad1562f3e27c0a9f746d62401c8edb30aeede'], @@ -213,8 +216,8 @@ dependencyVerification { ['androidx.vectordrawable:vectordrawable:1.1.0', '46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26'], - ['androidx.versionedparcelable:versionedparcelable:1.1.0', - '9a1d77140ac222b7866b5054ee7d159bc1800987ed2d46dd6afdd145abb710c1'], + ['androidx.versionedparcelable:versionedparcelable:1.1.1', + '57e8d93260d18d5b9007c9eed3c64ad159de90c8609ebfc74a347cbd514535a4'], ['androidx.viewpager2:viewpager2:1.0.0', 'e95c0031d4cc247cd48196c6287e58d2cee54d9c79b85afea7c90920330275af'],