diff --git a/app/build.gradle b/app/build.gradle index d3c92f448..8fbf0454c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -312,6 +312,7 @@ dependencies { implementation "androidx.camera:camera-view:1.0.0-alpha18" implementation "androidx.concurrent:concurrent-futures:1.0.0" implementation "androidx.autofill:autofill:1.0.0" + implementation "androidx.biometric:biometric:1.1.0" implementation ('com.google.firebase:firebase-messaging:20.2.0') { exclude group: 'com.google.firebase', module: 'firebase-core' diff --git a/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java b/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java index 5509d40ab..6e646a5d0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java @@ -17,7 +17,6 @@ package org.thoughtcrime.securesms; import android.animation.Animator; -import android.annotation.SuppressLint; import android.app.KeyguardManager; import android.content.Context; import android.content.Intent; @@ -46,9 +45,11 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.widget.Toolbar; -import androidx.core.hardware.fingerprint.FingerprintManagerCompat; -import androidx.core.os.CancellationSignal; +import androidx.biometric.BiometricManager; +import androidx.biometric.BiometricManager.Authenticators; +import androidx.biometric.BiometricPrompt; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.animation.AnimationCompleteListener; @@ -70,7 +71,10 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; */ public class PassphrasePromptActivity extends PassphraseActivity { - private static final String TAG = PassphrasePromptActivity.class.getSimpleName(); + private static final String TAG = Log.tag(PassphrasePromptActivity.class); + private static final int BIOMETRIC_AUTHENTICATORS = Authenticators.BIOMETRIC_STRONG | Authenticators.BIOMETRIC_WEAK; + private static final int ALLOWED_AUTHENTICATORS = BIOMETRIC_AUTHENTICATORS | Authenticators.DEVICE_CREDENTIAL; + private static final short AUTHENTICATE_REQUEST_CODE = 1007; private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme(); private DynamicLanguage dynamicLanguage = new DynamicLanguage(); @@ -84,12 +88,12 @@ public class PassphrasePromptActivity extends PassphraseActivity { private ImageButton hideButton; private AnimatingToggle visibilityToggle; - private FingerprintManagerCompat fingerprintManager; - private CancellationSignal fingerprintCancellationSignal; - private FingerprintListener fingerprintListener; + private BiometricManager biometricManager; + private BiometricPrompt biometricPrompt; + private BiometricPrompt.PromptInfo biometricPromptInfo; private boolean authenticated; - private boolean failure; + private boolean hadFailure; @Override public void onCreate(Bundle savedInstanceState) { @@ -112,20 +116,11 @@ public class PassphrasePromptActivity extends PassphraseActivity { setLockTypeVisibility(); - if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !failure) { + if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !hadFailure) { resumeScreenLock(); } - failure = false; - } - - @Override - public void onPause() { - super.onPause(); - - if (TextSecurePreferences.isScreenLockEnabled(this)) { - pauseScreenLock(); - } + hadFailure = false; } @Override @@ -160,15 +155,16 @@ public class PassphrasePromptActivity extends PassphraseActivity { } @Override - @SuppressLint("MissingSuperCall") // no fragments to dispatch to - public void onActivityResult(int requestCode, int resultcode, Intent data) { - if (requestCode != 1) return; + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); - if (resultcode == RESULT_OK) { + if (requestCode != AUTHENTICATE_REQUEST_CODE) return; + + if (resultCode == RESULT_OK) { handleAuthenticated(); } else { Log.w(TAG, "Authentication failed"); - failure = true; + hadFailure = true; } } @@ -219,16 +215,20 @@ public class PassphrasePromptActivity extends PassphraseActivity { ImageButton okButton = findViewById(R.id.ok_button); Toolbar toolbar = findViewById(R.id.toolbar); - showButton = findViewById(R.id.passphrase_visibility); - hideButton = findViewById(R.id.passphrase_visibility_off); - visibilityToggle = findViewById(R.id.button_toggle); - passphraseText = findViewById(R.id.passphrase_edit); - passphraseAuthContainer = findViewById(R.id.password_auth_container); - fingerprintPrompt = findViewById(R.id.fingerprint_auth_container); - lockScreenButton = findViewById(R.id.lock_screen_auth_container); - fingerprintManager = FingerprintManagerCompat.from(this); - fingerprintCancellationSignal = new CancellationSignal(); - fingerprintListener = new FingerprintListener(); + showButton = findViewById(R.id.passphrase_visibility); + hideButton = findViewById(R.id.passphrase_visibility_off); + visibilityToggle = findViewById(R.id.button_toggle); + passphraseText = findViewById(R.id.passphrase_edit); + passphraseAuthContainer = findViewById(R.id.password_auth_container); + fingerprintPrompt = findViewById(R.id.fingerprint_auth_container); + lockScreenButton = findViewById(R.id.lock_screen_auth_container); + biometricManager = BiometricManager.from(this); + biometricPrompt = new BiometricPrompt(this, new BiometricAuthenticationListener()); + biometricPromptInfo = new BiometricPrompt.PromptInfo + .Builder() + .setAllowedAuthenticators(ALLOWED_AUTHENTICATORS) + .setTitle(getString(R.string.PassphrasePromptActivity_unlock_signal)) + .build(); setSupportActionBar(toolbar); getSupportActionBar().setTitle(""); @@ -254,14 +254,9 @@ public class PassphrasePromptActivity extends PassphraseActivity { private void setLockTypeVisibility() { if (TextSecurePreferences.isScreenLockEnabled(this)) { passphraseAuthContainer.setVisibility(View.GONE); - - if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { - fingerprintPrompt.setVisibility(View.VISIBLE); - lockScreenButton.setVisibility(View.GONE); - } else { - fingerprintPrompt.setVisibility(View.GONE); - lockScreenButton.setVisibility(View.VISIBLE); - } + fingerprintPrompt.setVisibility(biometricManager.canAuthenticate(BIOMETRIC_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS ? View.VISIBLE + : View.GONE); + lockScreenButton.setVisibility(View.VISIBLE); } else { passphraseAuthContainer.setVisibility(View.VISIBLE); fingerprintPrompt.setVisibility(View.GONE); @@ -280,26 +275,19 @@ public class PassphrasePromptActivity extends PassphraseActivity { return; } - if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { - Log.i(TAG, "Listening for fingerprints..."); - fingerprintCancellationSignal = new CancellationSignal(); - fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null); + if (biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS) { + Log.i(TAG, "Listening for biometric authentication..."); + biometricPrompt.authenticate(biometricPromptInfo); } else if (Build.VERSION.SDK_INT >= 21){ Log.i(TAG, "firing intent..."); Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(getString(R.string.PassphrasePromptActivity_unlock_signal), ""); - startActivityForResult(intent, 1); + startActivityForResult(intent, AUTHENTICATE_REQUEST_CODE); } else { Log.w(TAG, "Not compatible..."); handleAuthenticated(); } } - private void pauseScreenLock() { - if (fingerprintCancellationSignal != null) { - fingerprintCancellationSignal.cancel(); - } - } - private void sendEmailToSupport() { String body = SupportEmailUtil.generateSupportEmailBody(this, R.string.PassphrasePromptActivity_signal_android_lock_screen, @@ -359,15 +347,19 @@ public class PassphrasePromptActivity extends PassphraseActivity { System.gc(); } - private class FingerprintListener extends FingerprintManagerCompat.AuthenticationCallback { + private class BiometricAuthenticationListener extends BiometricPrompt.AuthenticationCallback { @Override - public void onAuthenticationError(int errMsgId, CharSequence errString) { - Log.w(TAG, "Authentication error: " + errMsgId + " " + errString); - onAuthenticationFailed(); + public void onAuthenticationError(int errorCode, @NonNull CharSequence errorString) { + Log.w(TAG, "Authentication error: " + errorCode); + hadFailure = true; + + if (errorCode != BiometricPrompt.ERROR_CANCELED && errorCode != BiometricPrompt.ERROR_USER_CANCELED) { + onAuthenticationFailed(); + } } @Override - public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) { + public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { Log.i(TAG, "onAuthenticationSucceeded"); fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN); @@ -384,8 +376,7 @@ public class PassphrasePromptActivity extends PassphraseActivity { @Override public void onAuthenticationFailed() { - Log.w(TAG, "onAuthenticatoinFailed()"); - FingerprintManagerCompat.AuthenticationCallback callback = this; + Log.w(TAG, "onAuthenticationFailed()"); fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN); @@ -409,6 +400,5 @@ public class PassphrasePromptActivity extends PassphraseActivity { fingerprintPrompt.startAnimation(shake); } - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java index e24c98100..e864f636d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/VerifyIdentityActivity.java @@ -301,6 +301,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActivity implement byte[] localId; byte[] remoteId; + //noinspection WrongThread Recipient resolved = recipient.resolve(); if (FeatureFlags.verifyV2() && resolved.getUuid().isPresent()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 1c935cdf1..baaca784d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -260,16 +260,16 @@ public class ConversationFragment extends LoggingFragment { this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class); this.conversationViewModel = ViewModelProviders.of(requireActivity(), new ConversationViewModel.Factory()).get(ConversationViewModel.class); - conversationViewModel.getMessages().observe(this, messages -> { + conversationViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> { ConversationAdapter adapter = getListAdapter(); if (adapter != null) { getListAdapter().submitList(messages); } }); - conversationViewModel.getConversationMetadata().observe(this, this::presentConversationMetadata); + conversationViewModel.getConversationMetadata().observe(getViewLifecycleOwner(), this::presentConversationMetadata); - conversationViewModel.getShowMentionsButton().observe(this, shouldShow -> { + conversationViewModel.getShowMentionsButton().observe(getViewLifecycleOwner(), shouldShow -> { if (shouldShow) { ViewUtil.animateIn(scrollToMentionButton, mentionButtonInAnimation); } else { @@ -277,7 +277,7 @@ public class ConversationFragment extends LoggingFragment { } }); - conversationViewModel.getShowScrollToBottom().observe(this, shouldShow -> { + conversationViewModel.getShowScrollToBottom().observe(getViewLifecycleOwner(), shouldShow -> { if (shouldShow) { ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation); } else { @@ -367,7 +367,7 @@ public class ConversationFragment extends LoggingFragment { @Override public void onStop() { super.onStop(); - ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(this); + ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(getViewLifecycleOwner()); } @Override @@ -542,7 +542,7 @@ public class ConversationFragment extends LoggingFragment { list.addOnScrollListener(new ShadowScrollListener()); if (oldThreadId != threadId) { - ApplicationDependencies.getTypingStatusRepository().getTypists(oldThreadId).removeObservers(this); + ApplicationDependencies.getTypingStatusRepository().getTypists(oldThreadId).removeObservers(getViewLifecycleOwner()); } } @@ -580,8 +580,8 @@ public class ConversationFragment extends LoggingFragment { LiveData typists = ApplicationDependencies.getTypingStatusRepository().getTypists(threadId); - typists.removeObservers(this); - typists.observe(this, typingState -> { + typists.removeObservers(getViewLifecycleOwner()); + typists.observe(getViewLifecycleOwner(), typingState -> { List recipients; boolean replacedByIncomingMessage; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index d956b28ec..74d55777e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -532,7 +532,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode } private void initializeTypingObserver() { - ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(this, threadIds -> { + ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(getViewLifecycleOwner(), threadIds -> { if (threadIds == null) { threadIds = Collections.emptySet(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/help/HelpFragment.java b/app/src/main/java/org/thoughtcrime/securesms/help/HelpFragment.java index c49d2bdd6..1ab749800 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/help/HelpFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/help/HelpFragment.java @@ -127,7 +127,7 @@ public class HelpFragment extends LoggingFragment { setSpinning(next); problem.setEnabled(false); - helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(this, result -> { + helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(getViewLifecycleOwner(), result -> { if (result.getDebugLogUrl().isPresent()) { submitFormWithDebugLog(result.getDebugLogUrl().get()); } else if (result.isError()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsDashboardDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsDashboardDialogFragment.java index c279b8c56..c0a2ce8b0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsDashboardDialogFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsDashboardDialogFragment.java @@ -127,7 +127,7 @@ public final class InsightsDashboardDialogFragment extends DialogFragment { viewModel = ViewModelProviders.of(this, factory).get(InsightsDashboardViewModel.class); - viewModel.getState().observe(this, state -> { + viewModel.getState().observe(getViewLifecycleOwner(), state -> { updateInsecurePercent(state.getData()); updateInsecureRecipients(state.getInsecureRecipients()); updateUserAvatar(state.getUserAvatar()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsModalDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsModalDialogFragment.java index 0fbc2d9bd..3f4e31d06 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsModalDialogFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/insights/InsightsModalDialogFragment.java @@ -79,7 +79,7 @@ public final class InsightsModalDialogFragment extends DialogFragment { final InsightsModalViewModel.Factory factory = new InsightsModalViewModel.Factory(repository); final InsightsModalViewModel viewModel = ViewModelProviders.of(this, factory).get(InsightsModalViewModel.class); - viewModel.getState().observe(this, state -> { + viewModel.getState().observe(getViewLifecycleOwner(), state -> { updateInsecurePercent(state.getData()); updateUserAvatar(state.getUserAvatar()); }); diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediaoverview/MediaOverviewPageFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediaoverview/MediaOverviewPageFragment.java index 7f78668a3..c59d556f0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediaoverview/MediaOverviewPageFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediaoverview/MediaOverviewPageFragment.java @@ -128,7 +128,7 @@ public final class MediaOverviewPageFragment extends Fragment MediaOverviewViewModel viewModel = MediaOverviewViewModel.getMediaOverviewViewModel(requireActivity()); viewModel.getSortOrder() - .observe(this, sorting -> { + .observe(getViewLifecycleOwner(), sorting -> { if (sorting != null) { this.sorting = sorting; adapter.setShowFileSizes(sorting.isRelatedToFileSize()); @@ -139,7 +139,7 @@ public final class MediaOverviewPageFragment extends Fragment if (gridMode == GridMode.FOLLOW_MODEL) { viewModel.getDetailLayout() - .observe(this, this::setDetailView); + .observe(getViewLifecycleOwner(), this::setDetailView); } else { setDetailView(gridMode == GridMode.FIXED_DETAIL); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java index 2586e992b..e3d49c29e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java @@ -111,8 +111,8 @@ public class Camera1Fragment extends LoggingFragment implements CameraFragment, GestureDetector gestureDetector = new GestureDetector(flipGestureListener); cameraPreview.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event)); - viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail); - viewModel.getHudState().observe(this, this::presentHud); + viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail); + viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java index 7679cbf4d..9ceb91312 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java @@ -122,8 +122,8 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment { onOrientationChanged(getResources().getConfiguration().orientation); - viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail); - viewModel.getHudState().observe(this, this::presentHud); + viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail); + viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java index 8bd54bccf..3d47e47d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java @@ -104,7 +104,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo list.setLayoutManager(layoutManager); list.setAdapter(adapter); - viewModel.getFolders(requireContext()).observe(this, adapter::setFolders); + viewModel.getFolders(requireContext()).observe(getViewLifecycleOwner(), adapter::setFolders); initToolbar(view.findViewById(R.id.mediapicker_toolbar)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java index 123b85826..8e9bb06d7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerItemFragment.java @@ -110,8 +110,8 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem initToolbar(view.findViewById(R.id.mediapicker_toolbar)); onScreenWidthChanged(getScreenWidth()); - viewModel.getSelectedMedia().observe(this, adapter::setSelected); - viewModel.getMediaInBucket(requireContext(), bucketId).observe(this, adapter::setMedia); + viewModel.getSelectedMedia().observe(getViewLifecycleOwner(), adapter::setSelected); + viewModel.getMediaInBucket(requireContext(), bucketId).observe(getViewLifecycleOwner(), adapter::setMedia); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java index 0cfcac53c..cfb1b9f45 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaSendFragment.java @@ -115,7 +115,7 @@ public class MediaSendFragment extends Fragment { private void initViewModel() { viewModel = ViewModelProviders.of(requireActivity(), new MediaSendViewModel.Factory(requireActivity().getApplication(), new MediaRepository())).get(MediaSendViewModel.class); - viewModel.getSelectedMedia().observe(this, media -> { + viewModel.getSelectedMedia().observe(getViewLifecycleOwner(), media -> { if (Util.isEmpty(media)) { return; } @@ -123,7 +123,7 @@ public class MediaSendFragment extends Fragment { fragmentPagerAdapter.setMedia(media); }); - viewModel.getPosition().observe(this, position -> { + viewModel.getPosition().observe(getViewLifecycleOwner(), position -> { if (position == null || position < 0) return; fragmentPager.setCurrentItem(position, true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java b/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java index 401f0da81..8408c0408 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java @@ -110,8 +110,8 @@ public class PinRestoreEntryFragment extends LoggingFragment { private void initViewModel() { viewModel = ViewModelProviders.of(this).get(PinRestoreViewModel.class); - viewModel.getTriesRemaining().observe(this, this::presentTriesRemaining); - viewModel.getEvent().observe(this, this::presentEvent); + viewModel.getTriesRemaining().observe(getViewLifecycleOwner(), this::presentTriesRemaining); + viewModel.getEvent().observe(getViewLifecycleOwner(), this::presentEvent); } private void presentTriesRemaining(PinRestoreViewModel.TriesRemaining triesRemaining) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterCodeFragment.java b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterCodeFragment.java index 73edfce0c..469498d89 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterCodeFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterCodeFragment.java @@ -97,7 +97,7 @@ public final class EnterCodeFragment extends BaseRegistrationFragment noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport()); RegistrationViewModel model = getModel(); - model.getSuccessfulCodeRequestAttempts().observe(this, (attempts) -> { + model.getSuccessfulCodeRequestAttempts().observe(getViewLifecycleOwner(), (attempts) -> { if (attempts >= 3) { noCodeReceivedHelp.setVisibility(View.VISIBLE); scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000); @@ -328,9 +328,9 @@ public final class EnterCodeFragment extends BaseRegistrationFragment super.onResume(); RegistrationViewModel model = getModel(); - model.getLiveNumber().observe(this, (s) -> header.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, s.getFullFormattedNumber()))); + model.getLiveNumber().observe(getViewLifecycleOwner(), (s) -> header.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, s.getFullFormattedNumber()))); - model.getCanCallAtTime().observe(this, callAtTime -> callMeCountDown.startCountDownTo(callAtTime)); + model.getCanCallAtTime().observe(getViewLifecycleOwner(), callAtTime -> callMeCountDown.startCountDownTo(callAtTime)); } private void sendEmailToSupport() { diff --git a/app/witness-verifications.gradle b/app/witness-verifications.gradle index 7ed8cc44e..4c6ef0ee1 100644 --- a/app/witness-verifications.gradle +++ b/app/witness-verifications.gradle @@ -3,8 +3,8 @@ dependencyVerification { verify = [ - ['androidx.activity:activity:1.0.0', - 'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'], + ['androidx.activity:activity:1.1.0', + '4f2b35916768032f7d0c20e250e28b29037ed4ce9ebf3da4fcd51bcb0c6067ef'], ['androidx.annotation:annotation-experimental:1.0.0', 'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'], @@ -30,6 +30,9 @@ dependencyVerification { ['androidx.autofill:autofill:1.0.0', 'c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd'], + ['androidx.biometric:biometric:1.1.0', + '270c7b7d99942d5ec1dd88594e4648feb33d8e31d8c3c2ab2321d49d9abdfc1f'], + ['androidx.camera:camera-camera2:1.0.0-beta11', '54d7c975ea7387f0d7c65faf531005fc543fe8e8d826eb696bb2c7f950041a9c'], @@ -60,8 +63,8 @@ dependencyVerification { ['androidx.coordinatorlayout:coordinatorlayout:1.1.0', '44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'], - ['androidx.core:core:1.3.1', - 'e92ea65a37d589943d405a6a54d1be9d12a225948f26c4e41e511dd55e81efb6'], + ['androidx.core:core:1.3.2', + '94de196cd67950cff6ef3e1ac59015f8eaaf61840bdc238f2cf54ddef8dd0be9'], ['androidx.cursoradapter:cursoradapter:1.0.0', 'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'], @@ -78,8 +81,8 @@ dependencyVerification { ['androidx.exifinterface:exifinterface:1.0.0', 'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'], - ['androidx.fragment:fragment:1.1.0', - 'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'], + ['androidx.fragment:fragment:1.2.5', + 'd19e82d142def6c4e136da70bf92f194c0ecc61d14ab4e84567b2ced0920fa93'], ['androidx.gridlayout:gridlayout:1.0.0', 'a7e5dc6f39dbc3dc6ac6d57b02a9c6fd792e80f0e45ddb3bb08e8f03d23c8755'], @@ -105,14 +108,14 @@ dependencyVerification { ['androidx.lifecycle:lifecycle-common-java8:2.1.0', 'a1ec63c1bb973443cb731d78ec336c5e20e7ee35c89cbb32d36f92c55bb02542'], - ['androidx.lifecycle:lifecycle-common:2.2.0-alpha05', + ['androidx.lifecycle:lifecycle-common:2.2.0', '63898dabf7cfe5ec5d7ed8b8c2564c1427be876e1496ead95c2703cf59d3734b'], ['androidx.lifecycle:lifecycle-extensions:2.1.0', 'bd53c64b038585215b4959c1a388437a3ad525608a31c58e4283c3e371727d4d'], - ['androidx.lifecycle:lifecycle-livedata-core:2.2.0-alpha05', - '6df2bcbf3be50a5fa29e9aa09d39437f2d61d17c2c46ef618d65bbac4a4a99fc'], + ['androidx.lifecycle:lifecycle-livedata-core:2.2.0', + '556c1f3af90aa9d7d0d330565adbf6da71b2429148bac91e07c485f4f9abf614'], ['androidx.lifecycle:lifecycle-livedata:2.1.0', '242e446bed3db36f0df0aab0cb7f91060bd2dab7adcad1117adf54e724cd1d26'], @@ -120,17 +123,17 @@ dependencyVerification { ['androidx.lifecycle:lifecycle-process:2.1.0', '8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac'], - ['androidx.lifecycle:lifecycle-runtime:2.1.0', - 'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'], + ['androidx.lifecycle:lifecycle-runtime:2.2.0', + '2f866c07a1f33a8c9bb69a9545d4f20b4f0628cd0a155432386d7cb081e1e0bc'], ['androidx.lifecycle:lifecycle-service:2.1.0', '23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69'], - ['androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha05', - 'f503b53f50c4e6c1f9a3d698c4733df6e7a44049fe477ad0b85cc2f460401fbc'], + ['androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0', + '3ce866fb822b20fe2f188f974992869a0a6233fe40acbefcff090d6def5e7f33'], - ['androidx.lifecycle:lifecycle-viewmodel:2.2.0-alpha05', - '7725715491963440ee483e46526cd4f83af1c758e072e97b3eab2115c6f4db35'], + ['androidx.lifecycle:lifecycle-viewmodel:2.2.0', + '967efab24d6c49dd414a8c0ac4a1cd09b018f0b8bb43b739ad360c4158ebde27'], ['androidx.loader:loader:1.0.0', '11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'],