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 b3db0acfb2..20f32853cd 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 @@ -1,6 +1,8 @@ package org.thoughtcrime.securesms.registration.fragments; +import android.animation.Animator; import android.os.Bundle; +import android.telephony.PhoneStateListener; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,7 +38,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public final class EnterCodeFragment extends BaseRegistrationFragment { +public final class EnterCodeFragment extends BaseRegistrationFragment + implements SignalStrengthPhoneStateListener.Callback +{ private static final String TAG = Log.tag(EnterCodeFragment.class); @@ -47,8 +51,11 @@ public final class EnterCodeFragment extends BaseRegistrationFragment { private CallMeCountDownView callMeCountDown; private View wrongNumber; private View noCodeReceivedHelp; + private View serviceWarning; private boolean autoCompleting; + private PhoneStateListener signalStrengthListener; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_registration_enter_code, container, false); @@ -67,6 +74,9 @@ public final class EnterCodeFragment extends BaseRegistrationFragment { callMeCountDown = view.findViewById(R.id.call_me_count_down); wrongNumber = view.findViewById(R.id.wrong_number); noCodeReceivedHelp = view.findViewById(R.id.no_code); + serviceWarning = view.findViewById(R.id.cell_service_warning); + + signalStrengthListener = new SignalStrengthPhoneStateListener(this, this); connectKeyboard(verificationCodeView, keyboard); @@ -319,4 +329,40 @@ public final class EnterCodeFragment extends BaseRegistrationFragment { getString(R.string.RegistrationActivity_code_support_subject), body); } + + @Override + public void onNoCellSignalPresent() { + if (serviceWarning.getVisibility() == View.VISIBLE) { + return; + } + serviceWarning.setVisibility(View.VISIBLE); + serviceWarning.animate() + .alpha(1) + .setListener(null) + .start(); + + scrollView.postDelayed(() -> { + if (serviceWarning.getVisibility() == View.VISIBLE) { + scrollView.smoothScrollTo(0, serviceWarning.getBottom()); + } + }, 1000); + } + + @Override + public void onCellSignalPresent() { + if (serviceWarning.getVisibility() != View.VISIBLE) { + return; + } + serviceWarning.animate() + .alpha(0) + .setListener(new Animator.AnimatorListener() { + @Override public void onAnimationEnd(Animator animation) { + serviceWarning.setVisibility(View.GONE); + } + @Override public void onAnimationStart(Animator animation) {} + @Override public void onAnimationCancel(Animator animation) {} + @Override public void onAnimationRepeat(Animator animation) {} + }) + .start(); + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/SignalStrengthPhoneStateListener.java b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/SignalStrengthPhoneStateListener.java new file mode 100644 index 0000000000..fded5f0aaf --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/SignalStrengthPhoneStateListener.java @@ -0,0 +1,73 @@ +package org.thoughtcrime.securesms.registration.fragments; + +import android.content.Context; +import android.os.Build; +import android.telephony.PhoneStateListener; +import android.telephony.SignalStrength; +import android.telephony.TelephonyManager; + +import androidx.annotation.NonNull; +import androidx.lifecycle.DefaultLifecycleObserver; +import androidx.lifecycle.LifecycleOwner; + +import org.signal.core.util.logging.Log; +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.util.Debouncer; + +final class SignalStrengthPhoneStateListener extends PhoneStateListener + implements DefaultLifecycleObserver +{ + private static final String TAG = Log.tag(SignalStrengthPhoneStateListener.class); + + private final Callback callback; + private final Debouncer debouncer = new Debouncer(1000); + + SignalStrengthPhoneStateListener(@NonNull LifecycleOwner lifecycleOwner, @NonNull Callback callback) { + this.callback = callback; + + lifecycleOwner.getLifecycle().addObserver(this); + } + + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (signalStrength == null) return; + + if (isLowLevel(signalStrength)) { + Log.w(TAG, "No cell signal detected"); + debouncer.publish(callback::onNoCellSignalPresent); + } else { + Log.i(TAG, "Cell signal detected"); + debouncer.clear(); + callback.onCellSignalPresent(); + } + } + + private boolean isLowLevel(@NonNull SignalStrength signalStrength) { + if (Build.VERSION.SDK_INT >= 23) { + return signalStrength.getLevel() == 0; + } else { + //noinspection deprecation: False lint warning, deprecated by 29, but this else block is for < 23 + return signalStrength.getGsmSignalStrength() == 0; + } + } + + interface Callback { + void onNoCellSignalPresent(); + + void onCellSignalPresent(); + } + + @Override + public void onResume(@NonNull LifecycleOwner owner) { + TelephonyManager telephonyManager = (TelephonyManager) ApplicationDependencies.getApplication().getSystemService(Context.TELEPHONY_SERVICE); + telephonyManager.listen(this, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); + Log.i(TAG, "Listening to cell phone signal strength changes"); + } + + @Override + public void onPause(@NonNull LifecycleOwner owner) { + TelephonyManager telephonyManager = (TelephonyManager) ApplicationDependencies.getApplication().getSystemService(Context.TELEPHONY_SERVICE); + telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); + Log.i(TAG, "Stopped listening to cell phone signal strength changes"); + } +} diff --git a/app/src/main/res/drawable/ic_error_outline_14_ultramarine.xml b/app/src/main/res/drawable/ic_error_outline_14_ultramarine.xml new file mode 100644 index 0000000000..66049ea07b --- /dev/null +++ b/app/src/main/res/drawable/ic_error_outline_14_ultramarine.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/registration_no_cell_service_warning_border.xml b/app/src/main/res/drawable/registration_no_cell_service_warning_border.xml new file mode 100644 index 0000000000..f447a27c6b --- /dev/null +++ b/app/src/main/res/drawable/registration_no_cell_service_warning_border.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_registration_enter_code.xml b/app/src/main/res/layout/fragment_registration_enter_code.xml index 3e86fbc525..81b24681ab 100644 --- a/app/src/main/res/layout/fragment_registration_enter_code.xml +++ b/app/src/main/res/layout/fragment_registration_enter_code.xml @@ -88,6 +88,48 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/verify_header" /> + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 453d624599..0b60a4c122 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1509,6 +1509,7 @@ Enter your phone number to get started You will receive a verification code. Carrier rates may apply. Enter the code we sent to %s + Make sure your phone has a cellular signal to receive your SMS or call Phone number Country code