Enable lock screen fallback when biometric authentications may not work.

Fixes #9407
Fixes #10166
fork-5.53.8
Fumiaki Yoshimatsu 2020-10-25 18:22:28 -04:00 zatwierdzone przez Cody Henthorne
rodzic be4b687e48
commit 3c4252a933
17 zmienionych plików z 99 dodań i 104 usunięć

Wyświetl plik

@ -312,6 +312,7 @@ dependencies {
implementation "androidx.camera:camera-view:1.0.0-alpha18" implementation "androidx.camera:camera-view:1.0.0-alpha18"
implementation "androidx.concurrent:concurrent-futures:1.0.0" implementation "androidx.concurrent:concurrent-futures:1.0.0"
implementation "androidx.autofill:autofill: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') { implementation ('com.google.firebase:firebase-messaging:20.2.0') {
exclude group: 'com.google.firebase', module: 'firebase-core' exclude group: 'com.google.firebase', module: 'firebase-core'

Wyświetl plik

@ -17,7 +17,6 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.animation.Animator; import android.animation.Animator;
import android.annotation.SuppressLint;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -46,9 +45,11 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.hardware.fingerprint.FingerprintManagerCompat; import androidx.biometric.BiometricManager;
import androidx.core.os.CancellationSignal; import androidx.biometric.BiometricManager.Authenticators;
import androidx.biometric.BiometricPrompt;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener; import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
@ -70,7 +71,10 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
*/ */
public class PassphrasePromptActivity extends PassphraseActivity { 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 DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
private DynamicLanguage dynamicLanguage = new DynamicLanguage(); private DynamicLanguage dynamicLanguage = new DynamicLanguage();
@ -84,12 +88,12 @@ public class PassphrasePromptActivity extends PassphraseActivity {
private ImageButton hideButton; private ImageButton hideButton;
private AnimatingToggle visibilityToggle; private AnimatingToggle visibilityToggle;
private FingerprintManagerCompat fingerprintManager; private BiometricManager biometricManager;
private CancellationSignal fingerprintCancellationSignal; private BiometricPrompt biometricPrompt;
private FingerprintListener fingerprintListener; private BiometricPrompt.PromptInfo biometricPromptInfo;
private boolean authenticated; private boolean authenticated;
private boolean failure; private boolean hadFailure;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -112,20 +116,11 @@ public class PassphrasePromptActivity extends PassphraseActivity {
setLockTypeVisibility(); setLockTypeVisibility();
if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !failure) { if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !hadFailure) {
resumeScreenLock(); resumeScreenLock();
} }
failure = false; hadFailure = false;
}
@Override
public void onPause() {
super.onPause();
if (TextSecurePreferences.isScreenLockEnabled(this)) {
pauseScreenLock();
}
} }
@Override @Override
@ -160,15 +155,16 @@ public class PassphrasePromptActivity extends PassphraseActivity {
} }
@Override @Override
@SuppressLint("MissingSuperCall") // no fragments to dispatch to public void onActivityResult(int requestCode, int resultCode, Intent data) {
public void onActivityResult(int requestCode, int resultcode, Intent data) { super.onActivityResult(requestCode, resultCode, data);
if (requestCode != 1) return;
if (resultcode == RESULT_OK) { if (requestCode != AUTHENTICATE_REQUEST_CODE) return;
if (resultCode == RESULT_OK) {
handleAuthenticated(); handleAuthenticated();
} else { } else {
Log.w(TAG, "Authentication failed"); 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); ImageButton okButton = findViewById(R.id.ok_button);
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
showButton = findViewById(R.id.passphrase_visibility); showButton = findViewById(R.id.passphrase_visibility);
hideButton = findViewById(R.id.passphrase_visibility_off); hideButton = findViewById(R.id.passphrase_visibility_off);
visibilityToggle = findViewById(R.id.button_toggle); visibilityToggle = findViewById(R.id.button_toggle);
passphraseText = findViewById(R.id.passphrase_edit); passphraseText = findViewById(R.id.passphrase_edit);
passphraseAuthContainer = findViewById(R.id.password_auth_container); passphraseAuthContainer = findViewById(R.id.password_auth_container);
fingerprintPrompt = findViewById(R.id.fingerprint_auth_container); fingerprintPrompt = findViewById(R.id.fingerprint_auth_container);
lockScreenButton = findViewById(R.id.lock_screen_auth_container); lockScreenButton = findViewById(R.id.lock_screen_auth_container);
fingerprintManager = FingerprintManagerCompat.from(this); biometricManager = BiometricManager.from(this);
fingerprintCancellationSignal = new CancellationSignal(); biometricPrompt = new BiometricPrompt(this, new BiometricAuthenticationListener());
fingerprintListener = new FingerprintListener(); biometricPromptInfo = new BiometricPrompt.PromptInfo
.Builder()
.setAllowedAuthenticators(ALLOWED_AUTHENTICATORS)
.setTitle(getString(R.string.PassphrasePromptActivity_unlock_signal))
.build();
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
getSupportActionBar().setTitle(""); getSupportActionBar().setTitle("");
@ -254,14 +254,9 @@ public class PassphrasePromptActivity extends PassphraseActivity {
private void setLockTypeVisibility() { private void setLockTypeVisibility() {
if (TextSecurePreferences.isScreenLockEnabled(this)) { if (TextSecurePreferences.isScreenLockEnabled(this)) {
passphraseAuthContainer.setVisibility(View.GONE); passphraseAuthContainer.setVisibility(View.GONE);
fingerprintPrompt.setVisibility(biometricManager.canAuthenticate(BIOMETRIC_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS ? View.VISIBLE
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { : View.GONE);
fingerprintPrompt.setVisibility(View.VISIBLE); lockScreenButton.setVisibility(View.VISIBLE);
lockScreenButton.setVisibility(View.GONE);
} else {
fingerprintPrompt.setVisibility(View.GONE);
lockScreenButton.setVisibility(View.VISIBLE);
}
} else { } else {
passphraseAuthContainer.setVisibility(View.VISIBLE); passphraseAuthContainer.setVisibility(View.VISIBLE);
fingerprintPrompt.setVisibility(View.GONE); fingerprintPrompt.setVisibility(View.GONE);
@ -280,26 +275,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
return; return;
} }
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { if (biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS) {
Log.i(TAG, "Listening for fingerprints..."); Log.i(TAG, "Listening for biometric authentication...");
fingerprintCancellationSignal = new CancellationSignal(); biometricPrompt.authenticate(biometricPromptInfo);
fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null);
} else if (Build.VERSION.SDK_INT >= 21){ } else if (Build.VERSION.SDK_INT >= 21){
Log.i(TAG, "firing intent..."); Log.i(TAG, "firing intent...");
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(getString(R.string.PassphrasePromptActivity_unlock_signal), ""); Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(getString(R.string.PassphrasePromptActivity_unlock_signal), "");
startActivityForResult(intent, 1); startActivityForResult(intent, AUTHENTICATE_REQUEST_CODE);
} else { } else {
Log.w(TAG, "Not compatible..."); Log.w(TAG, "Not compatible...");
handleAuthenticated(); handleAuthenticated();
} }
} }
private void pauseScreenLock() {
if (fingerprintCancellationSignal != null) {
fingerprintCancellationSignal.cancel();
}
}
private void sendEmailToSupport() { private void sendEmailToSupport() {
String body = SupportEmailUtil.generateSupportEmailBody(this, String body = SupportEmailUtil.generateSupportEmailBody(this,
R.string.PassphrasePromptActivity_signal_android_lock_screen, R.string.PassphrasePromptActivity_signal_android_lock_screen,
@ -359,15 +347,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
System.gc(); System.gc();
} }
private class FingerprintListener extends FingerprintManagerCompat.AuthenticationCallback { private class BiometricAuthenticationListener extends BiometricPrompt.AuthenticationCallback {
@Override @Override
public void onAuthenticationError(int errMsgId, CharSequence errString) { public void onAuthenticationError(int errorCode, @NonNull CharSequence errorString) {
Log.w(TAG, "Authentication error: " + errMsgId + " " + errString); Log.w(TAG, "Authentication error: " + errorCode);
onAuthenticationFailed(); hadFailure = true;
if (errorCode != BiometricPrompt.ERROR_CANCELED && errorCode != BiometricPrompt.ERROR_USER_CANCELED) {
onAuthenticationFailed();
}
} }
@Override @Override
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) { public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
Log.i(TAG, "onAuthenticationSucceeded"); Log.i(TAG, "onAuthenticationSucceeded");
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
@ -384,8 +376,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
@Override @Override
public void onAuthenticationFailed() { public void onAuthenticationFailed() {
Log.w(TAG, "onAuthenticatoinFailed()"); Log.w(TAG, "onAuthenticationFailed()");
FingerprintManagerCompat.AuthenticationCallback callback = this;
fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN); 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); fingerprintPrompt.startAnimation(shake);
} }
} }
} }

Wyświetl plik

@ -301,6 +301,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActivity implement
byte[] localId; byte[] localId;
byte[] remoteId; byte[] remoteId;
//noinspection WrongThread
Recipient resolved = recipient.resolve(); Recipient resolved = recipient.resolve();
if (FeatureFlags.verifyV2() && resolved.getUuid().isPresent()) { if (FeatureFlags.verifyV2() && resolved.getUuid().isPresent()) {

Wyświetl plik

@ -260,16 +260,16 @@ public class ConversationFragment extends LoggingFragment {
this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class); this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class);
this.conversationViewModel = ViewModelProviders.of(requireActivity(), new ConversationViewModel.Factory()).get(ConversationViewModel.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(); ConversationAdapter adapter = getListAdapter();
if (adapter != null) { if (adapter != null) {
getListAdapter().submitList(messages); 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) { if (shouldShow) {
ViewUtil.animateIn(scrollToMentionButton, mentionButtonInAnimation); ViewUtil.animateIn(scrollToMentionButton, mentionButtonInAnimation);
} else { } else {
@ -277,7 +277,7 @@ public class ConversationFragment extends LoggingFragment {
} }
}); });
conversationViewModel.getShowScrollToBottom().observe(this, shouldShow -> { conversationViewModel.getShowScrollToBottom().observe(getViewLifecycleOwner(), shouldShow -> {
if (shouldShow) { if (shouldShow) {
ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation); ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation);
} else { } else {
@ -367,7 +367,7 @@ public class ConversationFragment extends LoggingFragment {
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(this); ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(getViewLifecycleOwner());
} }
@Override @Override
@ -542,7 +542,7 @@ public class ConversationFragment extends LoggingFragment {
list.addOnScrollListener(new ShadowScrollListener()); list.addOnScrollListener(new ShadowScrollListener());
if (oldThreadId != threadId) { 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<TypingStatusRepository.TypingState> typists = ApplicationDependencies.getTypingStatusRepository().getTypists(threadId); LiveData<TypingStatusRepository.TypingState> typists = ApplicationDependencies.getTypingStatusRepository().getTypists(threadId);
typists.removeObservers(this); typists.removeObservers(getViewLifecycleOwner());
typists.observe(this, typingState -> { typists.observe(getViewLifecycleOwner(), typingState -> {
List<Recipient> recipients; List<Recipient> recipients;
boolean replacedByIncomingMessage; boolean replacedByIncomingMessage;

Wyświetl plik

@ -532,7 +532,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
} }
private void initializeTypingObserver() { private void initializeTypingObserver() {
ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(this, threadIds -> { ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(getViewLifecycleOwner(), threadIds -> {
if (threadIds == null) { if (threadIds == null) {
threadIds = Collections.emptySet(); threadIds = Collections.emptySet();
} }

Wyświetl plik

@ -127,7 +127,7 @@ public class HelpFragment extends LoggingFragment {
setSpinning(next); setSpinning(next);
problem.setEnabled(false); problem.setEnabled(false);
helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(this, result -> { helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(getViewLifecycleOwner(), result -> {
if (result.getDebugLogUrl().isPresent()) { if (result.getDebugLogUrl().isPresent()) {
submitFormWithDebugLog(result.getDebugLogUrl().get()); submitFormWithDebugLog(result.getDebugLogUrl().get());
} else if (result.isError()) { } else if (result.isError()) {

Wyświetl plik

@ -127,7 +127,7 @@ public final class InsightsDashboardDialogFragment extends DialogFragment {
viewModel = ViewModelProviders.of(this, factory).get(InsightsDashboardViewModel.class); viewModel = ViewModelProviders.of(this, factory).get(InsightsDashboardViewModel.class);
viewModel.getState().observe(this, state -> { viewModel.getState().observe(getViewLifecycleOwner(), state -> {
updateInsecurePercent(state.getData()); updateInsecurePercent(state.getData());
updateInsecureRecipients(state.getInsecureRecipients()); updateInsecureRecipients(state.getInsecureRecipients());
updateUserAvatar(state.getUserAvatar()); updateUserAvatar(state.getUserAvatar());

Wyświetl plik

@ -79,7 +79,7 @@ public final class InsightsModalDialogFragment extends DialogFragment {
final InsightsModalViewModel.Factory factory = new InsightsModalViewModel.Factory(repository); final InsightsModalViewModel.Factory factory = new InsightsModalViewModel.Factory(repository);
final InsightsModalViewModel viewModel = ViewModelProviders.of(this, factory).get(InsightsModalViewModel.class); final InsightsModalViewModel viewModel = ViewModelProviders.of(this, factory).get(InsightsModalViewModel.class);
viewModel.getState().observe(this, state -> { viewModel.getState().observe(getViewLifecycleOwner(), state -> {
updateInsecurePercent(state.getData()); updateInsecurePercent(state.getData());
updateUserAvatar(state.getUserAvatar()); updateUserAvatar(state.getUserAvatar());
}); });

Wyświetl plik

@ -128,7 +128,7 @@ public final class MediaOverviewPageFragment extends Fragment
MediaOverviewViewModel viewModel = MediaOverviewViewModel.getMediaOverviewViewModel(requireActivity()); MediaOverviewViewModel viewModel = MediaOverviewViewModel.getMediaOverviewViewModel(requireActivity());
viewModel.getSortOrder() viewModel.getSortOrder()
.observe(this, sorting -> { .observe(getViewLifecycleOwner(), sorting -> {
if (sorting != null) { if (sorting != null) {
this.sorting = sorting; this.sorting = sorting;
adapter.setShowFileSizes(sorting.isRelatedToFileSize()); adapter.setShowFileSizes(sorting.isRelatedToFileSize());
@ -139,7 +139,7 @@ public final class MediaOverviewPageFragment extends Fragment
if (gridMode == GridMode.FOLLOW_MODEL) { if (gridMode == GridMode.FOLLOW_MODEL) {
viewModel.getDetailLayout() viewModel.getDetailLayout()
.observe(this, this::setDetailView); .observe(getViewLifecycleOwner(), this::setDetailView);
} else { } else {
setDetailView(gridMode == GridMode.FIXED_DETAIL); setDetailView(gridMode == GridMode.FIXED_DETAIL);
} }

Wyświetl plik

@ -111,8 +111,8 @@ public class Camera1Fragment extends LoggingFragment implements CameraFragment,
GestureDetector gestureDetector = new GestureDetector(flipGestureListener); GestureDetector gestureDetector = new GestureDetector(flipGestureListener);
cameraPreview.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event)); cameraPreview.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail); viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail);
viewModel.getHudState().observe(this, this::presentHud); viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud);
} }
@Override @Override

Wyświetl plik

@ -122,8 +122,8 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment {
onOrientationChanged(getResources().getConfiguration().orientation); onOrientationChanged(getResources().getConfiguration().orientation);
viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail); viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail);
viewModel.getHudState().observe(this, this::presentHud); viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud);
} }
@Override @Override

Wyświetl plik

@ -104,7 +104,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo
list.setLayoutManager(layoutManager); list.setLayoutManager(layoutManager);
list.setAdapter(adapter); list.setAdapter(adapter);
viewModel.getFolders(requireContext()).observe(this, adapter::setFolders); viewModel.getFolders(requireContext()).observe(getViewLifecycleOwner(), adapter::setFolders);
initToolbar(view.findViewById(R.id.mediapicker_toolbar)); initToolbar(view.findViewById(R.id.mediapicker_toolbar));
} }

Wyświetl plik

@ -110,8 +110,8 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
initToolbar(view.findViewById(R.id.mediapicker_toolbar)); initToolbar(view.findViewById(R.id.mediapicker_toolbar));
onScreenWidthChanged(getScreenWidth()); onScreenWidthChanged(getScreenWidth());
viewModel.getSelectedMedia().observe(this, adapter::setSelected); viewModel.getSelectedMedia().observe(getViewLifecycleOwner(), adapter::setSelected);
viewModel.getMediaInBucket(requireContext(), bucketId).observe(this, adapter::setMedia); viewModel.getMediaInBucket(requireContext(), bucketId).observe(getViewLifecycleOwner(), adapter::setMedia);
} }
@Override @Override

Wyświetl plik

@ -115,7 +115,7 @@ public class MediaSendFragment extends Fragment {
private void initViewModel() { private void initViewModel() {
viewModel = ViewModelProviders.of(requireActivity(), new MediaSendViewModel.Factory(requireActivity().getApplication(), new MediaRepository())).get(MediaSendViewModel.class); 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)) { if (Util.isEmpty(media)) {
return; return;
} }
@ -123,7 +123,7 @@ public class MediaSendFragment extends Fragment {
fragmentPagerAdapter.setMedia(media); fragmentPagerAdapter.setMedia(media);
}); });
viewModel.getPosition().observe(this, position -> { viewModel.getPosition().observe(getViewLifecycleOwner(), position -> {
if (position == null || position < 0) return; if (position == null || position < 0) return;
fragmentPager.setCurrentItem(position, true); fragmentPager.setCurrentItem(position, true);

Wyświetl plik

@ -110,8 +110,8 @@ public class PinRestoreEntryFragment extends LoggingFragment {
private void initViewModel() { private void initViewModel() {
viewModel = ViewModelProviders.of(this).get(PinRestoreViewModel.class); viewModel = ViewModelProviders.of(this).get(PinRestoreViewModel.class);
viewModel.getTriesRemaining().observe(this, this::presentTriesRemaining); viewModel.getTriesRemaining().observe(getViewLifecycleOwner(), this::presentTriesRemaining);
viewModel.getEvent().observe(this, this::presentEvent); viewModel.getEvent().observe(getViewLifecycleOwner(), this::presentEvent);
} }
private void presentTriesRemaining(PinRestoreViewModel.TriesRemaining triesRemaining) { private void presentTriesRemaining(PinRestoreViewModel.TriesRemaining triesRemaining) {

Wyświetl plik

@ -97,7 +97,7 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport()); noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport());
RegistrationViewModel model = getModel(); RegistrationViewModel model = getModel();
model.getSuccessfulCodeRequestAttempts().observe(this, (attempts) -> { model.getSuccessfulCodeRequestAttempts().observe(getViewLifecycleOwner(), (attempts) -> {
if (attempts >= 3) { if (attempts >= 3) {
noCodeReceivedHelp.setVisibility(View.VISIBLE); noCodeReceivedHelp.setVisibility(View.VISIBLE);
scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000); scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000);
@ -328,9 +328,9 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
super.onResume(); super.onResume();
RegistrationViewModel model = getModel(); 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() { private void sendEmailToSupport() {

Wyświetl plik

@ -3,8 +3,8 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
['androidx.activity:activity:1.0.0', ['androidx.activity:activity:1.1.0',
'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'], '4f2b35916768032f7d0c20e250e28b29037ed4ce9ebf3da4fcd51bcb0c6067ef'],
['androidx.annotation:annotation-experimental:1.0.0', ['androidx.annotation:annotation-experimental:1.0.0',
'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'], 'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'],
@ -30,6 +30,9 @@ dependencyVerification {
['androidx.autofill:autofill:1.0.0', ['androidx.autofill:autofill:1.0.0',
'c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd'], 'c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd'],
['androidx.biometric:biometric:1.1.0',
'270c7b7d99942d5ec1dd88594e4648feb33d8e31d8c3c2ab2321d49d9abdfc1f'],
['androidx.camera:camera-camera2:1.0.0-beta11', ['androidx.camera:camera-camera2:1.0.0-beta11',
'54d7c975ea7387f0d7c65faf531005fc543fe8e8d826eb696bb2c7f950041a9c'], '54d7c975ea7387f0d7c65faf531005fc543fe8e8d826eb696bb2c7f950041a9c'],
@ -60,8 +63,8 @@ dependencyVerification {
['androidx.coordinatorlayout:coordinatorlayout:1.1.0', ['androidx.coordinatorlayout:coordinatorlayout:1.1.0',
'44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'], '44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'],
['androidx.core:core:1.3.1', ['androidx.core:core:1.3.2',
'e92ea65a37d589943d405a6a54d1be9d12a225948f26c4e41e511dd55e81efb6'], '94de196cd67950cff6ef3e1ac59015f8eaaf61840bdc238f2cf54ddef8dd0be9'],
['androidx.cursoradapter:cursoradapter:1.0.0', ['androidx.cursoradapter:cursoradapter:1.0.0',
'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'], 'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'],
@ -78,8 +81,8 @@ dependencyVerification {
['androidx.exifinterface:exifinterface:1.0.0', ['androidx.exifinterface:exifinterface:1.0.0',
'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'], 'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'],
['androidx.fragment:fragment:1.1.0', ['androidx.fragment:fragment:1.2.5',
'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'], 'd19e82d142def6c4e136da70bf92f194c0ecc61d14ab4e84567b2ced0920fa93'],
['androidx.gridlayout:gridlayout:1.0.0', ['androidx.gridlayout:gridlayout:1.0.0',
'a7e5dc6f39dbc3dc6ac6d57b02a9c6fd792e80f0e45ddb3bb08e8f03d23c8755'], 'a7e5dc6f39dbc3dc6ac6d57b02a9c6fd792e80f0e45ddb3bb08e8f03d23c8755'],
@ -105,14 +108,14 @@ dependencyVerification {
['androidx.lifecycle:lifecycle-common-java8:2.1.0', ['androidx.lifecycle:lifecycle-common-java8:2.1.0',
'a1ec63c1bb973443cb731d78ec336c5e20e7ee35c89cbb32d36f92c55bb02542'], 'a1ec63c1bb973443cb731d78ec336c5e20e7ee35c89cbb32d36f92c55bb02542'],
['androidx.lifecycle:lifecycle-common:2.2.0-alpha05', ['androidx.lifecycle:lifecycle-common:2.2.0',
'63898dabf7cfe5ec5d7ed8b8c2564c1427be876e1496ead95c2703cf59d3734b'], '63898dabf7cfe5ec5d7ed8b8c2564c1427be876e1496ead95c2703cf59d3734b'],
['androidx.lifecycle:lifecycle-extensions:2.1.0', ['androidx.lifecycle:lifecycle-extensions:2.1.0',
'bd53c64b038585215b4959c1a388437a3ad525608a31c58e4283c3e371727d4d'], 'bd53c64b038585215b4959c1a388437a3ad525608a31c58e4283c3e371727d4d'],
['androidx.lifecycle:lifecycle-livedata-core:2.2.0-alpha05', ['androidx.lifecycle:lifecycle-livedata-core:2.2.0',
'6df2bcbf3be50a5fa29e9aa09d39437f2d61d17c2c46ef618d65bbac4a4a99fc'], '556c1f3af90aa9d7d0d330565adbf6da71b2429148bac91e07c485f4f9abf614'],
['androidx.lifecycle:lifecycle-livedata:2.1.0', ['androidx.lifecycle:lifecycle-livedata:2.1.0',
'242e446bed3db36f0df0aab0cb7f91060bd2dab7adcad1117adf54e724cd1d26'], '242e446bed3db36f0df0aab0cb7f91060bd2dab7adcad1117adf54e724cd1d26'],
@ -120,17 +123,17 @@ dependencyVerification {
['androidx.lifecycle:lifecycle-process:2.1.0', ['androidx.lifecycle:lifecycle-process:2.1.0',
'8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac'], '8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac'],
['androidx.lifecycle:lifecycle-runtime:2.1.0', ['androidx.lifecycle:lifecycle-runtime:2.2.0',
'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'], '2f866c07a1f33a8c9bb69a9545d4f20b4f0628cd0a155432386d7cb081e1e0bc'],
['androidx.lifecycle:lifecycle-service:2.1.0', ['androidx.lifecycle:lifecycle-service:2.1.0',
'23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69'], '23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69'],
['androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha05', ['androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0',
'f503b53f50c4e6c1f9a3d698c4733df6e7a44049fe477ad0b85cc2f460401fbc'], '3ce866fb822b20fe2f188f974992869a0a6233fe40acbefcff090d6def5e7f33'],
['androidx.lifecycle:lifecycle-viewmodel:2.2.0-alpha05', ['androidx.lifecycle:lifecycle-viewmodel:2.2.0',
'7725715491963440ee483e46526cd4f83af1c758e072e97b3eab2115c6f4db35'], '967efab24d6c49dd414a8c0ac4a1cd09b018f0b8bb43b739ad360c4158ebde27'],
['androidx.loader:loader:1.0.0', ['androidx.loader:loader:1.0.0',
'11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'], '11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'],