diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 38f83051f5..a67bcf266c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -290,10 +290,6 @@ android:name="org.thoughtcrime.securesms.scribbles.StickerSelectActivity" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:theme="@style/Theme.Session.ForceDark" /> - = Build.VERSION_CODES.LOLLIPOP) { - Window window = getActivity().getWindow(); - originalStatusBarColor = window.getStatusBarColor(); - window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar)); - } + FragmentActivity activity = getActivity(); + if (activity == null) return false; + + Window window = activity.getWindow(); + originalStatusBarColor = window.getStatusBarColor(); + window.setStatusBarColor(ContextCompat.getColor(activity, R.color.action_mode_status_bar)); + return true; } @@ -469,11 +473,12 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { public void onDestroyActionMode(ActionMode mode) { actionMode = null; getListAdapter().clearSelection(); - ((MediaOverviewActivity) getActivity()).onExitMultiSelect(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - getActivity().getWindow().setStatusBarColor(originalStatusBarColor); - } + MediaOverviewActivity activity = ((MediaOverviewActivity) getActivity()); + if(activity == null) return; + + activity.onExitMultiSelect(); + activity.getWindow().setStatusBarColor(originalStatusBarColor); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index b88e6a66ba..85cb64bf0b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -55,6 +55,8 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; import com.squareup.phrase.Phrase; import java.io.IOException; import java.util.Locale; @@ -76,8 +78,6 @@ import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel; import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter; -import com.bumptech.glide.Glide; -import com.bumptech.glide.RequestManager; import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.util.AttachmentUtil; diff --git a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt index cb97b3787f..13de1a0750 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt @@ -1,5 +1,7 @@ package org.thoughtcrime.securesms +import android.content.ClipData +import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.graphics.Typeface @@ -31,7 +33,6 @@ import androidx.fragment.app.Fragment import com.squareup.phrase.Phrase import network.loki.messenger.R import org.session.libsession.utilities.StringSubstitutionConstants.URL_KEY -import org.thoughtcrime.securesms.conversation.v2.Util.writeTextToClipboard import org.thoughtcrime.securesms.util.toPx @DslMarker @@ -171,6 +172,12 @@ class SessionDialogBuilder(val context: Context) { fun Context.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog = SessionDialogBuilder(this).apply { build() }.show() +public fun Context.copyURLToClipboard(url: String) { + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText(url, url) + clipboard.setPrimaryClip(clip) +} + // Method to show a dialog used to open or copy a URL fun Context.showOpenUrlDialog(url: String, showCloseButton: Boolean = true): AlertDialog { return SessionDialogBuilder(this).apply { @@ -281,7 +288,7 @@ fun Context.showOpenUrlDialog(url: String, showCloseButton: Boolean = true): Ale // Note: The text and contentDescription are set on the `copyUrlButton` by the function. contentView.addView(scrollView) dangerButton(R.string.open, R.string.AccessibilityId_urlOpenBrowser) { openUrl(url) } - copyUrlButton { writeTextToClipboard(context, url) } + copyUrlButton { context.copyURLToClipboard(url) } }.show() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioCodec.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioCodec.java index 699e9ba973..64c7ac3df2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioCodec.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioCodec.java @@ -1,22 +1,19 @@ package org.thoughtcrime.securesms.audio; -import android.annotation.TargetApi; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.media.MediaRecorder; -import android.os.Build; -import org.session.libsignal.utilities.Log; import org.session.libsession.utilities.Util; +import org.session.libsignal.utilities.Log; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) public class AudioCodec { private static final String TAG = AudioCodec.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioSlidePlayer.java b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioSlidePlayer.java index 3a07eba357..c1a4046947 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/audio/AudioSlidePlayer.java +++ b/app/src/main/java/org/thoughtcrime/securesms/audio/AudioSlidePlayer.java @@ -43,7 +43,7 @@ public class AudioSlidePlayer implements SensorEventListener { private final @NonNull Handler progressEventHandler; private final @NonNull AudioManager audioManager; private final @NonNull SensorManager sensorManager; - private final @NonNull Sensor proximitySensor; + private final Sensor proximitySensor; private final @Nullable WakeLock wakeLock; private @NonNull WeakReference listener; @@ -129,7 +129,9 @@ public class AudioSlidePlayer implements SensorEventListener { mediaPlayer.seekTo((long) (mediaPlayer.getDuration() * progress)); } - sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); + if(proximitySensor != null) { + sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); + } setPlaying(AudioSlidePlayer.this); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ComposeText.java b/app/src/main/java/org/thoughtcrime/securesms/components/ComposeText.java index 42825360c0..2365bc843b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ComposeText.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ComposeText.java @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms.components; import android.content.Context; -import android.os.Build; import android.os.Bundle; import android.text.InputType; import android.text.Spannable; @@ -16,15 +15,14 @@ import android.view.inputmethod.InputConnection; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.core.os.BuildCompat; import androidx.core.view.inputmethod.EditorInfoCompat; import androidx.core.view.inputmethod.InputConnectionCompat; import androidx.core.view.inputmethod.InputContentInfoCompat; -import org.thoughtcrime.securesms.components.emoji.EmojiEditText; -import org.session.libsignal.utilities.Log; import org.session.libsession.utilities.TextSecurePreferences; +import org.session.libsignal.utilities.Log; +import org.thoughtcrime.securesms.components.emoji.EmojiEditText; public class ComposeText extends EmojiEditText { @@ -136,7 +134,6 @@ public class ComposeText extends EmojiEditText { editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; } - if (Build.VERSION.SDK_INT < 21) return inputConnection; if (mediaListener == null) return inputConnection; if (inputConnection == null) return null; @@ -154,7 +151,6 @@ public class ComposeText extends EmojiEditText { } } - @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR2) private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener { private static final String TAG = CommitContentListener.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemAlertView.java b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemAlertView.java index 88bd1718a1..2a8de38d33 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemAlertView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemAlertView.java @@ -1,9 +1,7 @@ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; -import android.os.Build.VERSION_CODES; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; @@ -27,7 +25,6 @@ public class ConversationItemAlertView extends LinearLayout { initialize(attrs); } - @TargetApi(VERSION_CODES.HONEYCOMB) public ConversationItemAlertView(final Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initialize(attrs); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/HidingLinearLayout.java b/app/src/main/java/org/thoughtcrime/securesms/components/HidingLinearLayout.java index 980735aa48..bdb7c2fdf0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/HidingLinearLayout.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/HidingLinearLayout.java @@ -1,9 +1,6 @@ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; -import android.os.Build; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; @@ -11,6 +8,8 @@ import android.view.animation.AnimationSet; import android.view.animation.ScaleAnimation; import android.widget.LinearLayout; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; + public class HidingLinearLayout extends LinearLayout { public HidingLinearLayout(Context context) { @@ -21,7 +20,6 @@ public class HidingLinearLayout extends LinearLayout { super(context, attrs); } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) public HidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java b/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java index e81757026c..ad375c0992 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/InputPanel.java @@ -1,13 +1,12 @@ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; import android.net.Uri; -import android.os.Build; -import androidx.annotation.NonNull; import android.util.AttributeSet; import android.widget.LinearLayout; +import androidx.annotation.NonNull; + public class InputPanel extends LinearLayout { public InputPanel(Context context) { @@ -18,7 +17,6 @@ public class InputPanel extends LinearLayout { super(context, attrs); } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) public InputPanel(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java b/app/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java index 338b801770..bebc12a7e5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java @@ -16,26 +16,25 @@ */ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Rect; -import android.os.Build; -import android.os.Build.VERSION_CODES; import android.preference.PreferenceManager; -import androidx.appcompat.widget.LinearLayoutCompat; import android.util.AttributeSet; -import org.session.libsignal.utilities.Log; import android.view.Surface; import android.view.View; -import network.loki.messenger.R; +import androidx.appcompat.widget.LinearLayoutCompat; + import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.Util; +import org.session.libsignal.utilities.Log; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; +import network.loki.messenger.R; + /** * LinearLayout that, when a view container, will report back when it thinks a soft keyboard * has been opened and what its height would be. @@ -95,7 +94,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat { } private void updateKeyboardState() { - if (viewInset == 0 && Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) viewInset = getViewInset(); + if (viewInset == 0) viewInset = getViewInset(); getWindowVisibleDisplayFrame(rect); @@ -118,7 +117,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat { } } - @TargetApi(VERSION_CODES.LOLLIPOP) private int getViewInset() { try { Field attachInfoField = View.class.getDeclaredField("mAttachInfo"); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/MediaView.java b/app/src/main/java/org/thoughtcrime/securesms/components/MediaView.java index bb973c23ff..cdce4b7260 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/MediaView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/MediaView.java @@ -3,24 +3,24 @@ package org.thoughtcrime.securesms.components; import android.content.Context; import android.net.Uri; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import android.util.AttributeSet; import android.view.View; import android.view.Window; import android.widget.FrameLayout; -import network.loki.messenger.R; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bumptech.glide.RequestManager; + +import org.session.libsession.utilities.Stub; import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.video.VideoPlayer; -import org.session.libsession.utilities.Stub; - import java.io.IOException; +import network.loki.messenger.R; + public class MediaView extends FrameLayout { private ZoomingImageView imageView; @@ -41,12 +41,6 @@ public class MediaView extends FrameLayout { initialize(); } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - initialize(); - } - private void initialize() { inflate(getContext(), R.layout.media_view, this); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java b/app/src/main/java/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java index e1d3236a96..98bce61010 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/RecentPhotoViewRail.java @@ -1,19 +1,11 @@ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.loader.app.LoaderManager; -import androidx.loader.content.Loader; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -21,16 +13,24 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.loader.app.LoaderManager; +import androidx.loader.content.Loader; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; import com.bumptech.glide.load.Key; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.signature.MediaStoreSignature; -import network.loki.messenger.R; +import org.session.libsession.utilities.ViewUtil; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader; -import com.bumptech.glide.Glide; -import org.session.libsession.utilities.ViewUtil; +import network.loki.messenger.R; public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks { @@ -130,14 +130,12 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo } - @TargetApi(16) @SuppressWarnings("SuspiciousNameCombination") private String getWidthColumn(int orientation) { if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH; else return MediaStore.Images.ImageColumns.HEIGHT; } - @TargetApi(16) @SuppressWarnings("SuspiciousNameCombination") private String getHeightColumn(int orientation) { if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT; diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SearchToolbar.java b/app/src/main/java/org/thoughtcrime/securesms/components/SearchToolbar.java index 4655622ed2..37d5cfad05 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/SearchToolbar.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/SearchToolbar.java @@ -93,15 +93,11 @@ public class SearchToolbar extends LinearLayout { searchItem.expandActionView(); - if (Build.VERSION.SDK_INT >= 21) { - Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth()); - animator.setDuration(400); + Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth()); + animator.setDuration(400); - setVisibility(View.VISIBLE); - animator.start(); - } else { - setVisibility(View.VISIBLE); - } + setVisibility(View.VISIBLE); + animator.start(); } } @@ -115,19 +111,15 @@ public class SearchToolbar extends LinearLayout { if (listener != null) listener.onSearchClosed(); - if (Build.VERSION.SDK_INT >= 21) { - Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0); - animator.setDuration(400); - animator.addListener(new AnimationCompleteListener() { - @Override - public void onAnimationEnd(Animator animation) { - setVisibility(View.INVISIBLE); - } - }); - animator.start(); - } else { - setVisibility(View.INVISIBLE); - } + Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0); + animator.setDuration(400); + animator.addListener(new AnimationCompleteListener() { + @Override + public void onAnimationEnd(Animator animation) { + setVisibility(View.INVISIBLE); + } + }); + animator.start(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SquareFrameLayout.java b/app/src/main/java/org/thoughtcrime/securesms/components/SquareFrameLayout.java index 3bf15fb272..5d369de3b3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/SquareFrameLayout.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/SquareFrameLayout.java @@ -1,10 +1,7 @@ package org.thoughtcrime.securesms.components; -import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; -import android.graphics.BitmapFactory; -import android.os.Build.VERSION_CODES; import android.util.AttributeSet; import android.widget.FrameLayout; @@ -24,7 +21,7 @@ public class SquareFrameLayout extends FrameLayout { this(context, attrs, 0); } - @TargetApi(VERSION_CODES.HONEYCOMB) @SuppressWarnings("unused") + @SuppressWarnings("unused") public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java b/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java index 11f6c4104b..5b04e39289 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/camera/CameraView.java @@ -15,7 +15,6 @@ package org.thoughtcrime.securesms.components.camera; -import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; @@ -28,26 +27,26 @@ import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.os.AsyncTask; import android.os.Build; -import android.os.Build.VERSION; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.util.AttributeSet; -import org.session.libsignal.utilities.Log; import android.view.OrientationEventListener; import android.view.ViewGroup; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.util.BitmapUtil; -import org.session.libsignal.utilities.guava.Optional; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.Util; +import org.session.libsignal.utilities.Log; +import org.session.libsignal.utilities.guava.Optional; +import org.thoughtcrime.securesms.util.BitmapUtil; import java.io.IOException; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import network.loki.messenger.R; + @SuppressWarnings("deprecation") public class CameraView extends ViewGroup { private static final String TAG = CameraView.class.getSimpleName(); @@ -91,7 +90,6 @@ public class CameraView extends ViewGroup { addView(surface); } - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void onResume() { if (state != State.PAUSED) return; state = State.RESUMED; @@ -255,33 +253,15 @@ public class CameraView extends ViewGroup { return Camera.getNumberOfCameras() > 1; } - public boolean isRearCamera() { - return cameraId == CameraInfo.CAMERA_FACING_BACK; - } - - public void flipCamera() { - if (Camera.getNumberOfCameras() > 1) { - cameraId = cameraId == CameraInfo.CAMERA_FACING_BACK - ? CameraInfo.CAMERA_FACING_FRONT - : CameraInfo.CAMERA_FACING_BACK; - onPause(); - onResume(); - TextSecurePreferences.setDirectCaptureCameraId(getContext(), cameraId); - } - } - - @TargetApi(14) private void onCameraReady(final @NonNull Camera camera) { final Parameters parameters = camera.getParameters(); - if (VERSION.SDK_INT >= 14) { - parameters.setRecordingHint(true); - final List focusModes = parameters.getSupportedFocusModes(); - if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { - parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); - } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - } + parameters.setRecordingHint(true); + final List focusModes = parameters.getSupportedFocusModes(); + if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo()); @@ -465,7 +445,7 @@ public class CameraView extends ViewGroup { } final float newWidth = visibleRect.width() * scale; final float newHeight = visibleRect.height() * scale; - final float centerX = (VERSION.SDK_INT < 14 || isTroublemaker()) ? previewWidth - newWidth / 2 : previewWidth / 2; + final float centerX = (isTroublemaker()) ? previewWidth - newWidth / 2 : previewWidth / 2; final float centerY = previewHeight / 2; visibleRect.set((int) (centerX - newWidth / 2), diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/Util.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/Util.kt index 6a54919442..c025f64159 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/Util.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/Util.kt @@ -16,39 +16,19 @@ */ package org.thoughtcrime.securesms.conversation.v2 -import android.annotation.TargetApi -import android.app.ActivityManager -import android.content.ClipData -import android.content.ClipboardManager import android.content.Context -import android.graphics.Typeface import android.net.Uri -import android.os.Build.VERSION -import android.os.Build.VERSION_CODES -import android.text.Spannable -import android.text.SpannableString import android.text.TextUtils -import android.text.style.StyleSpan import android.view.View import com.annimon.stream.Stream -import com.google.android.mms.pdu_alt.CharacterSets import com.google.android.mms.pdu_alt.EncodedStringValue -import java.io.ByteArrayOutputStream -import java.io.IOException -import java.io.UnsupportedEncodingException import java.util.Collections -import java.util.concurrent.TimeUnit -import kotlin.math.max -import kotlin.math.min -import network.loki.messenger.R import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.components.ComposeText object Util { private val TAG: String = Log.tag(Util::class.java) - private val BUILD_LIFESPAN = TimeUnit.DAYS.toMillis(90) - fun asList(vararg elements: T): List { val result = mutableListOf() // LinkedList() Collections.addAll(result, *elements) @@ -104,19 +84,6 @@ object Util { return sb.toString() } - fun rightPad(value: String, length: Int): String { - if (value.length >= length) { - return value - } - - val out = StringBuilder(value) - while (out.length < length) { - out.append(" ") - } - - return out.toString() - } - fun isEmpty(value: Array?): Boolean { return value == null || value.size == 0 } @@ -130,65 +97,7 @@ object Util { } fun isEmpty(charSequence: CharSequence?): Boolean { - return charSequence == null || charSequence.length == 0 - } - - fun hasItems(collection: Collection<*>?): Boolean { - return collection != null && !collection.isEmpty() - } - - fun getOrDefault(map: Map, key: K, defaultValue: V): V? { - return if (map.containsKey(key)) map[key] else defaultValue - } - - fun getFirstNonEmpty(vararg values: String?): String { - for (value in values) { - if (!value.isNullOrEmpty()) { return value } - } - return "" - } - - fun emptyIfNull(value: String?): String { - return value ?: "" - } - - fun emptyIfNull(value: CharSequence?): CharSequence { - return value ?: "" - } - - fun getBoldedString(value: String?): CharSequence { - val spanned = SpannableString(value) - spanned.setSpan( - StyleSpan(Typeface.BOLD), 0, - spanned.length, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) - - return spanned - } - - fun toIsoString(bytes: ByteArray?): String { - try { - return String(bytes!!, charset(CharacterSets.MIMENAME_ISO_8859_1)) - } catch (e: UnsupportedEncodingException) { - throw AssertionError("ISO_8859_1 must be supported!") - } - } - - fun toIsoBytes(isoString: String): ByteArray { - try { - return isoString.toByteArray(charset(CharacterSets.MIMENAME_ISO_8859_1)) - } catch (e: UnsupportedEncodingException) { - throw AssertionError("ISO_8859_1 must be supported!") - } - } - - fun toUtf8Bytes(utf8String: String): ByteArray { - try { - return utf8String.toByteArray(charset(CharacterSets.MIMENAME_UTF_8)) - } catch (e: UnsupportedEncodingException) { - throw AssertionError("UTF_8 must be supported!") - } + return charSequence.isNullOrEmpty() } fun wait(lock: Any, timeout: Long) { @@ -225,20 +134,6 @@ object Util { return parts } - fun combine(vararg elements: ByteArray?): ByteArray { - try { - val baos = ByteArrayOutputStream() - - for (element in elements) { - baos.write(element) - } - - return baos.toByteArray() - } catch (e: IOException) { - throw AssertionError(e) - } - } - fun trim(input: ByteArray?, length: Int): ByteArray { val result = ByteArray(length) System.arraycopy(input, 0, result, 0, result.size) @@ -251,26 +146,6 @@ object Util { else Uri.parse(uri) } - @TargetApi(VERSION_CODES.KITKAT) - fun isLowMemory(context: Context): Boolean { - val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - - return (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice) || - activityManager.largeMemoryClass <= 64 - } - - fun clamp(value: Int, min: Int, max: Int): Int { - return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toInt() - } - - fun clamp(value: Long, min: Long, max: Long): Long { - return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toLong() - } - - fun clamp(value: Float, min: Float, max: Float): Float { - return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toFloat() - } - /** * Returns half of the difference between the given length, and the length when scaled by the * given scale. @@ -280,74 +155,6 @@ object Util { return (length - scaledLength) / 2 } - fun readTextFromClipboard(context: Context): String? { - run { - val clipboardManager = - context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - return if (clipboardManager.hasPrimaryClip() && clipboardManager.primaryClip!!.itemCount > 0) { - clipboardManager.primaryClip!!.getItemAt(0).text.toString() - } else { - null - } - } - } - - fun writeTextToClipboard(context: Context, text: String) { - writeTextToClipboard(context, context.getString(R.string.app_name), text) - } - - fun writeTextToClipboard(context: Context, label: String, text: String) { - val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText(label, text) - clipboard.setPrimaryClip(clip) - } - - fun toIntExact(value: Long): Int { - if (value.toInt().toLong() != value) { - throw ArithmeticException("integer overflow") - } - return value.toInt() - } - - fun isEquals(first: Long?, second: Long): Boolean { - return first != null && first == second - } - - @SafeVarargs - fun concatenatedList(vararg items: Collection): List { - val concat: MutableList = ArrayList( - Stream.of(*items).reduce(0) { sum: Int, list: Collection -> sum + list.size }) - - for (list in items) { - concat.addAll(list) - } - - return concat - } - - fun isLong(value: String): Boolean { - try { - value.toLong() - return true - } catch (e: NumberFormatException) { - return false - } - } - - fun parseInt(integer: String, defaultValue: Int): Int { - return try { - integer.toInt() - } catch (e: NumberFormatException) { - defaultValue - } - } - - // Method to determine if we're currently in a left-to-right or right-to-left language like Arabic - fun usingRightToLeftLanguage(context: Context): Boolean { - val config = context.resources.configuration - return config.layoutDirection == View.LAYOUT_DIRECTION_RTL - } - // Method to determine if we're currently in a left-to-right or right-to-left language like Arabic fun usingLeftToRightLanguage(context: Context): Boolean { val config = context.resources.configuration diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt index c88e05dbfb..d2ec4b2d69 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt @@ -148,11 +148,8 @@ class InputBarButton : RelativeLayout { private fun onDown(event: MotionEvent) { expand() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) - } else { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - } + performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) + longPressCallback?.let { gestureHandler.removeCallbacks(it) } val newLongPressCallback = Runnable { onLongPress?.invoke() } this.longPressCallback = newLongPressCallback diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt index a42222f412..449fe8cfd4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarEditText.kt @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.conversation.v2.input_bar import android.content.Context import android.content.res.Resources import android.net.Uri -import android.os.Build import android.util.AttributeSet import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputConnection @@ -57,7 +56,7 @@ class InputBarEditText : AppCompatEditText { InputConnectionCompat.OnCommitContentListener { inputContentInfo, flags, opts -> val lacksPermission = (flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0 // read and display inputContentInfo asynchronously - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && lacksPermission) { + if (lacksPermission) { try { inputContentInfo.requestPermission() } catch (e: Exception) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/AttachmentSecretProvider.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/AttachmentSecretProvider.java index 1602ab3fcf..844ba975f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/AttachmentSecretProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/AttachmentSecretProvider.java @@ -59,25 +59,17 @@ public class AttachmentSecretProvider { { AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return attachmentSecret; - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); - TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); - TextSecurePreferences.setAttachmentUnencryptedSecret(context, null); + TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); + TextSecurePreferences.setAttachmentUnencryptedSecret(context, null); - return attachmentSecret; - } + return attachmentSecret; } private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!"); - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); - return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret))); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); + return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret))); } private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) { @@ -91,12 +83,8 @@ public class AttachmentSecretProvider { } private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); - TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); - } else { - TextSecurePreferences.setAttachmentUnencryptedSecret(context, attachmentSecret.serialize()); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); + TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/BiometricSecretProvider.kt b/app/src/main/java/org/thoughtcrime/securesms/crypto/BiometricSecretProvider.kt index ac12a69bbe..1329ad0dc3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/BiometricSecretProvider.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/BiometricSecretProvider.kt @@ -42,9 +42,8 @@ class BiometricSecretProvider { builder.setUnlockedDeviceRequired(true) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - builder.setInvalidatedByBiometricEnrollment(true) - } + builder.setInvalidatedByBiometricEnrollment(true) + keyGenerator.initialize(builder.build()) keyGenerator.generateKeyPair() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSecretProvider.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSecretProvider.java index 44bb33161c..ab79f7ea55 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSecretProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSecretProvider.java @@ -36,28 +36,20 @@ public class DatabaseSecretProvider { try { DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return databaseSecret; - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); - TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); - TextSecurePreferences.setDatabaseUnencryptedSecret(context, null); + TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); + TextSecurePreferences.setDatabaseUnencryptedSecret(context, null); - return databaseSecret; - } + return databaseSecret; } catch (IOException e) { throw new AssertionError(e); } } private DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!"); - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); - return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret)); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); + return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret)); } private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) { @@ -66,12 +58,8 @@ public class DatabaseSecretProvider { DatabaseSecret databaseSecret = new DatabaseSecret(secret); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); - TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); - } else { - TextSecurePreferences.setDatabaseUnencryptedSecret(context, databaseSecret.asString()); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); + TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); return databaseSecret; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java index 62aaf58f1a..4db46a3abc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/IdentityKeyUtil.java @@ -129,27 +129,19 @@ public class IdentityKeyUtil { } private static String getUnencryptedSecret(String key, String unencryptedSecret, Context context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return unencryptedSecret; - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes()); + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes()); - // save the encrypted suffix secret "key_encrypted" - save(context,key+ENCRYPTED_SUFFIX,encryptedSecret.serialize()); - // delete the regular secret "key" - delete(context,key); + // save the encrypted suffix secret "key_encrypted" + save(context,key+ENCRYPTED_SUFFIX,encryptedSecret.serialize()); + // delete the regular secret "key" + delete(context,key); - return unencryptedSecret; - } + return unencryptedSecret; } private static String getEncryptedSecret(String encryptedSecret) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!"); - } else { - KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret); - return new String(KeyStoreHelper.unseal(sealedData)); - } + KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret); + return new String(KeyStoreHelper.unseal(sealedData)); } @@ -157,17 +149,14 @@ public class IdentityKeyUtil { SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); Editor preferencesEditor = preferences.edit(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX); - if (isEncryptedSuffix) { - preferencesEditor.putString(key, value); - } else { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); - preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); - } - } else { + boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX); + if (isEncryptedSuffix) { preferencesEditor.putString(key, value); + } else { + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); + preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); } + if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences"); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java index 45172e2f6f..5d7301261e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java @@ -966,11 +966,6 @@ public class AttachmentDatabase extends Database { @SuppressLint("NewApi") private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - Log.w(TAG, "Video thumbnails not supported..."); - return null; - } - DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA); if (dataInfo == null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 8d440fb5a4..abdc69072c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -256,11 +256,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { NotificationManager notificationManager = context.getSystemService(NotificationManager.class); String channelId = context.getString(R.string.failures); - if (NotificationChannels.supported()) { - NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH); - channel.enableVibration(true); - notificationManager.createNotificationChannel(channel); - } + NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH); + channel.enableVibration(true); + notificationManager.createNotificationChannel(channel); CharSequence errorTxt = Phrase.from(context, R.string.databaseErrorGeneric) .put(APP_NAME_KEY, R.string.app_name) @@ -274,10 +272,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { .setContentText(errorTxt) .setAutoCancel(true); - if (!NotificationChannels.supported()) { - builder.setPriority(NotificationCompat.PRIORITY_HIGH); - } - notificationManager.notify(5874, builder.build()); // Throw the error (app will crash but there is nothing else we can do unfortunately) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt index 191a92b800..72fb00aa1d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt @@ -15,6 +15,7 @@ import android.widget.RelativeLayout import android.widget.TextView import android.widget.Toast import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.squareup.phrase.Phrase import kotlinx.coroutines.Dispatchers @@ -40,7 +41,6 @@ import org.thoughtcrime.securesms.util.disableClipping import org.thoughtcrime.securesms.util.fadeIn import org.thoughtcrime.securesms.util.fadeOut import org.thoughtcrime.securesms.util.getAccentColor -import org.thoughtcrime.securesms.util.getColorWithID class PathActivity : PassphraseRequiredActionBarActivity() { private lateinit var binding: ActivityPathBinding @@ -292,7 +292,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() { private fun expand() { dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size) @ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black - val startColor = context.resources.getColorWithID(startColorID, context.theme) + val startColor = ContextCompat.getColor(context, startColorID) val endColor = context.getAccentColor() GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor) } @@ -301,7 +301,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() { dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size) @ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black val startColor = context.getAccentColor() - val endColor = context.resources.getColorWithID(endColorID, context.theme) + val endColor = ContextCompat.getColor(context, endColorID) GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt index 7ab7bfb508..1c31a2ee17 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt @@ -9,6 +9,7 @@ import android.graphics.Paint import android.util.AttributeSet import android.view.View import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat import androidx.lifecycle.coroutineScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import kotlinx.coroutines.Dispatchers @@ -17,7 +18,6 @@ import kotlinx.coroutines.withContext import network.loki.messenger.R import org.session.libsession.snode.OnionRequestAPI import org.thoughtcrime.securesms.conversation.v2.ViewUtil -import org.thoughtcrime.securesms.util.getColorWithID import org.thoughtcrime.securesms.util.toPx class PathStatusView : View { @@ -104,7 +104,7 @@ class PathStatusView : View { sessionShadowColor = hasPathsColor } else { setBackgroundResource(R.drawable.paths_building_dot) - val pathsBuildingColor = resources.getColorWithID(R.color.paths_building, context.theme) + val pathsBuildingColor = ContextCompat.getColor(context, R.color.paths_building) mainColor = pathsBuildingColor sessionShadowColor = pathsBuildingColor } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Constraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Constraint.java index 854804d746..dd766bbbb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Constraint.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Constraint.java @@ -8,11 +8,6 @@ public interface Constraint { boolean isMet(); - @NonNull String getFactoryKey(); - - @RequiresApi(26) - void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder); - interface Factory { T create(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraint.java index 1546883b85..7b128bf9fe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraint.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraint.java @@ -28,17 +28,6 @@ public class NetworkConstraint implements Constraint { return activeNetworkInfo != null && activeNetworkInfo.isConnected(); } - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @RequiresApi(26) - @Override - public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) { - jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); - } - public static final class Factory implements Constraint.Factory { private final Application application; diff --git a/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java b/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java index 763a2a430d..533e1a1d23 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logging/LogSecretProvider.java @@ -32,24 +32,16 @@ class LogSecretProvider { } private static byte[] parseEncryptedSecret(String secret) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret); - return KeyStoreHelper.unseal(encryptedSecret); - } else { - throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!"); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret); + return KeyStoreHelper.unseal(encryptedSecret); } private static byte[] createAndStoreSecret(@NonNull Context context) { byte[] secret = new byte[32]; SECURE_RANDOM.nextBytes(secret); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret); - TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize()); - } else { - TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeBytes(secret)); - } + KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret); + TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize()); return secret; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaRepository.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaRepository.java index 00c5c5cf00..f74910f870 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaRepository.java @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms.mediasend; -import android.annotation.TargetApi; import android.content.Context; import android.database.Cursor; import android.net.Uri; @@ -200,14 +199,12 @@ class MediaRepository { }).toList(); } - @TargetApi(16) @SuppressWarnings("SuspiciousNameCombination") private String getWidthColumn(int orientation) { if (orientation == 0 || orientation == 180) return Images.Media.WIDTH; else return Images.Media.HEIGHT; } - @TargetApi(16) @SuppressWarnings("SuspiciousNameCombination") private String getHeightColumn(int orientation) { if (orientation == 0 || orientation == 180) return Images.Media.HEIGHT; diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java index 9e33e5135d..e7e65fb453 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java @@ -50,8 +50,8 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui } public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) { - Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : TextSecurePreferences.getNotificationRingtone(context); - boolean defaultVibrate = NotificationChannels.supported() ? NotificationChannels.getMessageVibrate(context) : TextSecurePreferences.isNotificationVibrateEnabled(context); + Uri defaultRingtone = NotificationChannels.getMessageRingtone(context); + boolean defaultVibrate = NotificationChannels.getMessageVibrate(context); if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone); else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java index 4135faae9b..861d94edd1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/MultipleRecipientNotificationBuilder.java @@ -38,10 +38,6 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE)); setCategory(NotificationCompat.CATEGORY_MESSAGE); setGroupSummary(true); - - if (!NotificationChannels.supported()) { - setPriority(TextSecurePreferences.getNotificationPriority(context)); - } } public void setMessageCount(int messageCount, int threadCount) { 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 17fb8ee736..0c3422b757 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java @@ -1,15 +1,12 @@ package org.thoughtcrime.securesms.notifications; -import android.annotation.TargetApi; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.NotificationManager; import android.content.Context; -import android.content.Intent; import android.media.AudioAttributes; import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; import android.provider.Settings; import android.text.TextUtils; @@ -24,7 +21,6 @@ import org.session.libsession.utilities.Address; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.recipients.Recipient; -import org.session.libsession.utilities.recipients.Recipient.VibrateState; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.DatabaseComponent; @@ -63,10 +59,6 @@ public class NotificationChannels { * ignored for API < 26. */ public static synchronized void create(@NonNull Context context) { - if (!supported()) { - return; - } - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context); @@ -82,32 +74,6 @@ public class NotificationChannels { }); } - /** - * Recreates all notification channels for contacts with custom notifications enabled. Should be - * safe to call repeatedly. Needs to be executed on a background thread. - */ - @WorkerThread - public static synchronized void restoreContactNotificationChannels(@NonNull Context context) { - if (!NotificationChannels.supported()) { - return; - } - - RecipientDatabase db = DatabaseComponent.get(context).recipientDatabase(); - - try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) { - Recipient recipient; - while ((recipient = reader.getNext()) != null) { - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - if (!channelExists(notificationManager.getNotificationChannel(recipient.getNotificationChannel()))) { - String id = createChannelFor(context, recipient); - db.setNotificationChannel(recipient, id); - } - } - } - - ensureCustomChannelConsistency(context); - } - /** * @return The channel ID for the default messages channel. */ @@ -115,13 +81,6 @@ public class NotificationChannels { return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context)); } - /** - * @return Whether or not notification channels are supported. - */ - public static boolean supported() { - return Build.VERSION.SDK_INT >= 26; - } - /** * @return A name suitable to be displayed as the notification channel title. */ @@ -137,119 +96,18 @@ public class NotificationChannels { } } - /** - * Creates a channel for the specified recipient. - * @return The channel ID for the newly-created channel. - */ - public static synchronized String createChannelFor(@NonNull Context context, @NonNull Recipient recipient) { - VibrateState vibrateState = recipient.getMessageVibrate(); - boolean vibrationEnabled = vibrateState == VibrateState.DEFAULT ? TextSecurePreferences.isNotificationVibrateEnabled(context) : vibrateState == VibrateState.ENABLED; - Uri messageRingtone = recipient.getMessageRingtone() != null ? recipient.getMessageRingtone() : getMessageRingtone(context); - String displayName = getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress()); - return createChannelFor(context, recipient.getAddress(), displayName, messageRingtone, vibrationEnabled); - } - /** - * More verbose version of {@link #createChannelFor(Context, Recipient)}. - */ - public static synchronized @Nullable String createChannelFor(@NonNull Context context, - @NonNull Address address, - @NonNull String displayName, - @Nullable Uri messageSound, - boolean vibrationEnabled) - { - if (!supported()) { - return null; - } - - String channelId = generateChannelIdFor(address); - NotificationChannel channel = new NotificationChannel(channelId, displayName, NotificationManager.IMPORTANCE_HIGH); - - setLedPreference(channel, TextSecurePreferences.getNotificationLedColor(context)); - channel.setGroup(CATEGORY_MESSAGES); - channel.enableVibration(vibrationEnabled); - - if (messageSound != null) { - channel.setSound(messageSound, new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) - .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) - .build()); - } - - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - notificationManager.createNotificationChannel(channel); - - return channelId; - } - - /** - * Deletes the channel generated for the provided recipient. Safe to call even if there was never - * a channel made for that recipient. - */ - public static synchronized void deleteChannelFor(@NonNull Context context, @NonNull Recipient recipient) { - if (!supported()) { - return; - } - - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - String channel = recipient.getNotificationChannel(); - - if (channel != null) { - Log.i(TAG, "Deleting channel"); - notificationManager.deleteNotificationChannel(channel); - } - } - - /** - * Navigates the user to the system settings for the desired notification channel. - */ - public static void openChannelSettings(@NonNull Context context, @NonNull String channelId) { - if (!supported()) { - return; - } - - Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS); - intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId); - intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName()); - context.startActivity(intent); - } - - /** - * Updates the LED color for message notifications and all contact-specific message notification - * channels. Performs database operations and should therefore be invoked on a background thread. - */ - @WorkerThread - public static synchronized void updateMessagesLedColor(@NonNull Context context, @NonNull Integer color) { - if (!supported()) { - return; - } - Log.i(TAG, "Updating LED color."); - - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - - updateMessageChannel(context, channel -> setLedPreference(channel, color)); - updateAllRecipientChannelLedColors(context, notificationManager, color); - - ensureCustomChannelConsistency(context); - } /** * @return The message ringtone set for the default message channel. */ public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) { - if (!supported()) { - return Uri.EMPTY; - } - Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound(); return sound == null ? Uri.EMPTY : sound; } public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) { - if (!supported() || recipient.getNotificationChannel() == null) { - return null; - } - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel()); @@ -265,9 +123,6 @@ public class NotificationChannels { * Update the message ringtone for the default message channel. */ public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) { - if (!supported()) { - return; - } Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri)); updateMessageChannel(context, channel -> { @@ -275,121 +130,23 @@ public class NotificationChannels { }); } - /** - * Updates the message ringtone for a specific recipient. If that recipient has no channel, this - * does nothing. - * - * This has to update the database, and therefore should be run on a background thread. - */ - @WorkerThread - public static synchronized void updateMessageRingtone(@NonNull Context context, @NonNull Recipient recipient, @Nullable Uri uri) { - if (!supported() || recipient.getNotificationChannel() == null) { - return; - } - Log.i(TAG, "Updating recipient message ringtone with URI: " + String.valueOf(uri)); - - String newChannelId = generateChannelIdFor(recipient.getAddress()); - boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context), - recipient.getNotificationChannel(), - generateChannelIdFor(recipient.getAddress()), - channel -> channel.setSound(uri == null ? Settings.System.DEFAULT_NOTIFICATION_URI : uri, getRingtoneAudioAttributes())); - - DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null); - ensureCustomChannelConsistency(context); - } /** * @return The vibrate settings for the default message channel. */ public static synchronized boolean getMessageVibrate(@NonNull Context context) { - if (!supported()) { - return false; - } - return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate(); } - /** - * @return The vibrate setting for a specific recipient. If that recipient has no channel, this - * will return the setting for the default message channel. - */ - public static synchronized boolean getMessageVibrate(@NonNull Context context, @NonNull Recipient recipient) { - if (!supported()) { - return getMessageVibrate(context); - } - - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel()); - - if (!channelExists(channel)) { - Log.w(TAG, "Recipient didn't have a channel. Returning message default."); - return getMessageVibrate(context); - } - - return channel.shouldVibrate(); - } - /** * Sets the vibrate property for the default message channel. */ public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) { - if (!supported()) { - return; - } Log.i(TAG, "Updating default vibrate with value: " + enabled); updateMessageChannel(context, channel -> channel.enableVibration(enabled)); } - /** - * Updates the message ringtone for a specific recipient. If that recipient has no channel, this - * does nothing. - * - * This has to update the database and should therefore be run on a background thread. - */ - @WorkerThread - public static synchronized void updateMessageVibrate(@NonNull Context context, @NonNull Recipient recipient, VibrateState vibrateState) { - if (!supported() || recipient.getNotificationChannel() == null) { - return ; - } - Log.i(TAG, "Updating recipient vibrate with value: " + vibrateState); - - boolean enabled = vibrateState == VibrateState.DEFAULT ? getMessageVibrate(context) : vibrateState == VibrateState.ENABLED; - String newChannelId = generateChannelIdFor(recipient.getAddress()); - boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context), - recipient.getNotificationChannel(), - newChannelId, - channel -> channel.enableVibration(enabled)); - - DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null); - ensureCustomChannelConsistency(context); - } - - /** - * Updates the name of an existing channel to match the recipient's current name. Will have no - * effect if the recipient doesn't have an existing valid channel. - */ - public static synchronized void updateContactChannelName(@NonNull Context context, @NonNull Recipient recipient) { - if (!supported() || recipient.getNotificationChannel() == null) { - return; - } - Log.i(TAG, "Updating contact channel name"); - - NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - - if (notificationManager.getNotificationChannel(recipient.getNotificationChannel()) == null) { - Log.w(TAG, "Tried to update the name of a channel, but that channel doesn't exist."); - return; - } - - NotificationChannel channel = new NotificationChannel(recipient.getNotificationChannel(), - getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress()), - NotificationManager.IMPORTANCE_HIGH); - channel.setGroup(CATEGORY_MESSAGES); - notificationManager.createNotificationChannel(channel); - } - - @TargetApi(26) @WorkerThread public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) { NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); @@ -421,7 +178,6 @@ public class NotificationChannels { } } - @TargetApi(26) private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) { NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.messages)); notificationManager.createNotificationChannelGroup(messagesGroup); @@ -452,7 +208,6 @@ public class NotificationChannels { } } - @TargetApi(26) private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) { Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion); @@ -467,7 +222,6 @@ public class NotificationChannels { } } - @TargetApi(26) private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) { if ("none".equals(ledColor)) { channel.enableLights(false); @@ -482,7 +236,6 @@ public class NotificationChannels { return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis(); } - @TargetApi(26) private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) { NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance()); @@ -503,27 +256,7 @@ public class NotificationChannels { return MESSAGES_PREFIX + version; } - @WorkerThread - @TargetApi(26) - private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Integer color) { - RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase(); - try (RecipientDatabase.RecipientReader recipients = database.getRecipientsWithNotificationChannels()) { - Recipient recipient; - while ((recipient = recipients.getNext()) != null) { - assert recipient.getNotificationChannel() != null; - - String newChannelId = generateChannelIdFor(recipient.getAddress()); - boolean success = updateExistingChannel(notificationManager, recipient.getNotificationChannel(), newChannelId, channel -> setLedPreference(channel, color)); - - database.setNotificationChannel(recipient, success ? newChannelId : null); - } - } - - ensureCustomChannelConsistency(context); - } - - @TargetApi(26) private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) { NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context); @@ -537,7 +270,6 @@ public class NotificationChannels { } } - @TargetApi(26) private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager, @NonNull String channelId, @NonNull String newChannelId, @@ -557,20 +289,17 @@ public class NotificationChannels { return true; } - @TargetApi(21) private static AudioAttributes getRingtoneAudioAttributes() { return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) .build(); } - @TargetApi(26) private static boolean channelExists(@Nullable NotificationChannel channel) { return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId()); } private interface ChannelUpdater { - @TargetApi(26) void update(@NonNull NotificationChannel channel); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java index 108aa12c51..7bea5594ed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java @@ -51,8 +51,7 @@ public class NotificationState { Recipient recipient = notifications.getFirst().getRecipient(); if (recipient != null) { - return NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context, recipient) - : recipient.resolve().getMessageRingtone(); + return NotificationChannels.getMessageRingtone(context, recipient); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index 3a13f3f430..8ddc47584a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -13,7 +13,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Build; import android.text.SpannableStringBuilder; import androidx.annotation.NonNull; @@ -24,11 +23,10 @@ import androidx.core.app.NotificationCompat.Action; import androidx.core.app.RemoteInput; import androidx.core.content.ContextCompat; +import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; -import org.session.libsession.avatars.ContactColors; import org.session.libsession.avatars.ContactPhoto; -import org.session.libsession.avatars.ResourceContactPhoto; import org.session.libsession.messaging.contacts.Contact; import org.session.libsession.utilities.NotificationPrivacyPreference; import org.session.libsession.utilities.TextSecurePreferences; @@ -38,7 +36,6 @@ import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.database.SessionContactDatabase; import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; -import com.bumptech.glide.Glide; import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator; @@ -69,10 +66,6 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil setSmallIcon(R.drawable.ic_notification); setColor(ContextCompat.getColor(context, R.color.accent_green)); setCategory(NotificationCompat.CATEGORY_MESSAGE); - - if (!NotificationChannels.supported()) { - setPriority(TextSecurePreferences.getNotificationPriority(context)); - } } public void setThread(@NonNull Recipient recipient) { @@ -179,13 +172,11 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil Action replyAction = new Action(R.drawable.ic_reply_white_36dp, actionName, quickReplyIntent); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, - actionName, - wearableReplyIntent) - .addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build()) - .build(); - } + replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, + actionName, + wearableReplyIntent) + .addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build()) + .build(); Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply, actionName, diff --git a/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java b/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java index 9b6950bf7a..f38d4c8613 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java +++ b/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java @@ -210,15 +210,8 @@ public class Permissions { .toArray(new String[0]); } - public static boolean hasAny(@NonNull Context context, String... permissions) { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || - Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED); - - } - public static boolean hasAll(@NonNull Context context, String... permissions) { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || - Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED); + return Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt index 6af742838c..5614091473 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt @@ -56,14 +56,14 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() { true } - if (NotificationChannels.supported()) { - prefs.setNotificationRingtone( - NotificationChannels.getMessageRingtone(requireContext()).toString() - ) - prefs.setNotificationVibrateEnabled( - NotificationChannels.getMessageVibrate(requireContext()) - ) - } + + prefs.setNotificationRingtone( + NotificationChannels.getMessageRingtone(requireContext()).toString() + ) + prefs.setNotificationVibrateEnabled( + NotificationChannels.getMessageVibrate(requireContext()) + ) + findPreference(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceChangeListener = RingtoneSummaryListener() findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)!!.onPreferenceChangeListener = NotificationPrivacyListener() findPreference(TextSecurePreferences.VIBRATE_PREF)!!.onPreferenceChangeListener = @@ -100,18 +100,18 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() { true } initializeListSummary(findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) as ListPreference?) - if (NotificationChannels.supported()) { - findPreference(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener = - Preference.OnPreferenceClickListener { - val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) - intent.putExtra( - Settings.EXTRA_CHANNEL_ID, NotificationChannels.getMessagesChannel(requireContext()) - ) - intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) - startActivity(intent) - true - } - } + + findPreference(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener = + Preference.OnPreferenceClickListener { + val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + intent.putExtra( + Settings.EXTRA_CHANNEL_ID, NotificationChannels.getMessagesChannel(requireContext()) + ) + intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) + startActivity(intent) + true + } + initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF)) initializeMessageVibrateSummary(findPreference(TextSecurePreferences.VIBRATE_PREF) as SwitchPreferenceCompat?) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt index ad30b9f16b..4d8fad4b7f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt @@ -78,14 +78,9 @@ class PrivacySettingsPreferenceFragment : ListSummaryPreferenceFragment() { title(R.string.sessionNotifications) text(R.string.callsNotificationsRequired) button(R.string.sessionNotifications) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) - .putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) - } else { - Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID)) - } - .apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .takeIf { IntentUtils.isResolvable(requireContext(), it) }.let { startActivity(it) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index 32ddf827e0..e02a3eff70 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -7,7 +7,6 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.Parcelable import android.util.SparseArray @@ -215,7 +214,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.settings_general, menu) - if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (BuildConfig.DEBUG) { menu.findItem(R.id.action_qr_code)?.contentDescription = resources.getString(R.string.AccessibilityId_qrView) } return true diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/SignalListPreference.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/SignalListPreference.java index d8002c5cc6..1c483a43e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/SignalListPreference.java +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/SignalListPreference.java @@ -1,74 +1,70 @@ package org.thoughtcrime.securesms.preferences.widgets; import android.content.Context; -import androidx.preference.ListPreference; -import androidx.preference.PreferenceViewHolder; import android.util.AttributeSet; import android.widget.TextView; +import androidx.preference.ListPreference; +import androidx.preference.PreferenceViewHolder; import network.loki.messenger.R; public class SignalListPreference extends ListPreference { - private TextView rightSummaryTV; - private CharSequence summary; - private OnPreferenceClickListener clickListener; - private CharSequence summarySpecifiedInLayoutXML; + private TextView rightSummary; + private CharSequence summary; + private OnPreferenceClickListener clickListener; - public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - initialize(); + public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initialize(); + } + + public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(); + } + + public SignalListPreference(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(); + } + + public SignalListPreference(Context context) { + super(context); + initialize(); + } + + private void initialize() { + setWidgetLayoutResource(R.layout.preference_right_summary_widget); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder view) { + super.onBindViewHolder(view); + + this.rightSummary = (TextView)view.findViewById(R.id.right_summary); + setSummary(this.summary); + } + + @Override + public void setSummary(CharSequence summary) { + super.setSummary(null); + + this.summary = summary; + + if (this.rightSummary != null) { + this.rightSummary.setText(summary); } + } - public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(); - } - - public SignalListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(); - } - - public SignalListPreference(Context context) { - super(context); - initialize(); - } - - private void initialize() { - summarySpecifiedInLayoutXML = this.getSummary(); - if (summarySpecifiedInLayoutXML == null) { summarySpecifiedInLayoutXML = ""; } - setWidgetLayoutResource(R.layout.preference_right_summary_widget); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder view) { - super.onBindViewHolder(view); - this.rightSummaryTV = (TextView)view.findViewById(R.id.right_summary); - setSummary(this.summary); - } - - @Override - public void setSummary(CharSequence incomingSummary) { - // Set the left "subtitle" summary such as "The information shown in notifications." etc. - super.setSummary(summarySpecifiedInLayoutXML); - - // Then set the right summary to be the incoming drop-down selected option - this.summary = incomingSummary; - if (this.rightSummaryTV != null) { - this.rightSummaryTV.setText(incomingSummary); - } - } - - @Override - public void setOnPreferenceClickListener (OnPreferenceClickListener - onPreferenceClickListener){ - this.clickListener = onPreferenceClickListener; - } - - @Override - protected void onClick () { - if (clickListener == null || !clickListener.onPreferenceClick(this)) { - super.onClick(); - } + @Override + public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) { + this.clickListener = onPreferenceClickListener; + } + + @Override + protected void onClick() { + if (clickListener == null || !clickListener.onPreferenceClick(this)) { + super.onClick(); } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java b/app/src/main/java/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java index bd9afcadff..1cf46baf4c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/widget/VerticalSlideColorPicker.java @@ -23,7 +23,6 @@ package org.thoughtcrime.securesms.scribbles.widget; -import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -34,7 +33,6 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Shader; -import android.os.Build; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -98,12 +96,6 @@ public class VerticalSlideColorPicker extends View { init(); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); - } - private void init() { setWillNotDraw(false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FileProviderUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/FileProviderUtil.java index ed28c7c2e2..c05832352a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FileProviderUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FileProviderUtil.java @@ -14,10 +14,7 @@ public class FileProviderUtil { private static final String AUTHORITY = "network.loki.securesms.fileprovider"; public static Uri getUriFor(@NonNull Context context, @NonNull File file) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) - return FileProvider.getUriForFile(context, AUTHORITY, file); - else - return Uri.fromFile(file); + return FileProvider.getUriForFile(context, AUTHORITY, file); } public static boolean delete(@NonNull Context context, @NonNull Uri uri) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt index 9124765763..cc40e0cc92 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt @@ -1,20 +1,9 @@ package org.thoughtcrime.securesms.util import android.content.res.Resources -import android.os.Build -import androidx.annotation.ColorRes import androidx.recyclerview.widget.RecyclerView -import kotlin.math.max import kotlin.math.roundToInt -fun Resources.getColorWithID(@ColorRes id: Int, theme: Resources.Theme?): Int { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - getColor(id, theme) - } else { - @Suppress("DEPRECATION") getColor(id) - } -} - fun toPx(dp: Int, resources: Resources): Int { return toPx(dp.toFloat(), resources).roundToInt() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt b/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt index a0c0da24fe..46ad821233 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt @@ -11,7 +11,6 @@ import android.view.animation.AccelerateDecelerateInterpolator import android.widget.LinearLayout import android.widget.RelativeLayout import androidx.annotation.ColorInt -import androidx.annotation.ColorRes import network.loki.messenger.R import kotlin.math.roundToInt @@ -22,18 +21,6 @@ interface GlowView { object GlowViewUtilities { - fun animateColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) { - val startColor = context.resources.getColorWithID(startColorID, context.theme) - val endColor = context.resources.getColorWithID(endColorID, context.theme) - val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor) - animation.duration = 250 - animation.addUpdateListener { animator -> - val color = animator.animatedValue as Int - view.mainColor = color - } - animation.start() - } - fun animateColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) { val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor) animation.duration = 250 @@ -44,18 +31,6 @@ object GlowViewUtilities { animation.start() } - fun animateShadowColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) { - val startColor = context.resources.getColorWithID(startColorID, context.theme) - val endColor = context.resources.getColorWithID(endColorID, context.theme) - val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor) - animation.duration = 250 - animation.addUpdateListener { animator -> - val color = animator.animatedValue as Int - view.sessionShadowColor = color - } - animation.start() - } - fun animateShadowColorChange( view: GlowView, @ColorInt startColor: Int, diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java b/app/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java deleted file mode 100644 index 7172018116..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/util/LongClickCopySpan.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.thoughtcrime.securesms.util; - -import android.annotation.TargetApi; -import android.content.ClipData; -import android.content.Context; -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import android.text.TextPaint; -import android.text.style.URLSpan; - -import network.loki.messenger.R; - -public class LongClickCopySpan extends URLSpan { - private static final String PREFIX_MAILTO = "mailto:"; - private static final String PREFIX_TEL = "tel:"; - - private boolean isHighlighted; - @ColorInt - private int highlightColor; - - public LongClickCopySpan(String url) { - super(url); - } - - @Override - public void updateDrawState(@NonNull TextPaint ds) { - super.updateDrawState(ds); - ds.bgColor = highlightColor; - ds.setUnderlineText(!isHighlighted); - } - - void setHighlighted(boolean highlighted, @ColorInt int highlightColor) { - this.isHighlighted = highlighted; - this.highlightColor = highlightColor; - } - - private void copyUrl(Context context, String url) { - int sdk = android.os.Build.VERSION.SDK_INT; - if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) { - @SuppressWarnings("deprecation") android.text.ClipboardManager clipboard = - (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setText(url); - } else { - copyUriSdk11(context, url); - } - } - - @TargetApi(android.os.Build.VERSION_CODES.HONEYCOMB) - private void copyUriSdk11(Context context, String url) { - android.content.ClipboardManager clipboard = - (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(context.getString(R.string.app_name), url); - clipboard.setPrimaryClip(clip); - } - - private String prepareUrl(String url) { - if (url.startsWith(PREFIX_MAILTO)) { - return url.substring(PREFIX_MAILTO.length()); - } else if (url.startsWith(PREFIX_TEL)) { - return url.substring(PREFIX_TEL.length()); - } - return url; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/StickyHeaderDecoration.java b/app/src/main/java/org/thoughtcrime/securesms/util/StickyHeaderDecoration.java index 04435fde0f..0afe0192c0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/StickyHeaderDecoration.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/StickyHeaderDecoration.java @@ -131,7 +131,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration { int layoutPos) { int headerHeight = getHeaderHeightForLayout(header); - int top = getChildY(parent, child) - headerHeight; + int top = (int)child.getY() - headerHeight; if (sticky && layoutPos == 0) { final int count = parent.getChildCount(); final long currentId = adapter.getHeaderId(adapterPos); @@ -142,7 +142,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration { long nextId = adapter.getHeaderId(adapterPosHere); if (nextId != currentId) { final View next = parent.getChildAt(translatedChildPosition(parent, i)); - final int offset = getChildY(parent, next) - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight()); + final int offset = (int)next.getY() - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight()); if (offset < 0) { return offset; } else { @@ -162,16 +162,6 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration { return isReverseLayout(parent) ? parent.getChildCount() - 1 - position : position; } - private int getChildY(RecyclerView parent, View child) { - if (VERSION.SDK_INT < 11) { - Rect rect = new Rect(); - parent.getChildVisibleRect(child, rect, null); - return rect.top; - } else { - return (int)ViewCompat.getY(child); - } - } - protected int getHeaderHeightForLayout(View header) { return renderInline ? 0 : header.getHeight(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/video/EncryptedMediaDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/video/EncryptedMediaDataSource.java index 8a3d2c3f74..78541e02a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/video/EncryptedMediaDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/video/EncryptedMediaDataSource.java @@ -1,22 +1,20 @@ package org.thoughtcrime.securesms.video; -import android.annotation.TargetApi; import android.media.MediaDataSource; -import android.os.Build; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.session.libsession.utilities.Util; import org.thoughtcrime.securesms.crypto.AttachmentSecret; import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; -import org.session.libsession.utilities.Util; import java.io.File; import java.io.IOException; import java.io.InputStream; -@TargetApi(Build.VERSION_CODES.M) public class EncryptedMediaDataSource extends MediaDataSource { private final AttachmentSecret attachmentSecret; diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/AudioManagerCompat.java b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/AudioManagerCompat.java index da50cd0846..50af4f36c0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/AudioManagerCompat.java +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/AudioManagerCompat.java @@ -8,10 +8,8 @@ import android.media.AudioDeviceInfo; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.media.SoundPool; -import android.os.Build; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import org.session.libsession.utilities.ServiceUtil; import org.session.libsignal.utilities.Log; @@ -116,14 +114,9 @@ public abstract class AudioManagerCompat { abstract public void abandonCallAudioFocus(); public static AudioManagerCompat create(@NonNull Context context) { - if (Build.VERSION.SDK_INT >= 26) { - return new Api26AudioManagerCompat(context); - } else { - return new Api21AudioManagerCompat(context); - } + return new Api26AudioManagerCompat(context); } - @RequiresApi(26) private static class Api26AudioManagerCompat extends AudioManagerCompat { private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() @@ -180,44 +173,4 @@ public abstract class AudioManagerCompat { audioFocusRequest = null; } } - - @RequiresApi(21) - private static class Api21AudioManagerCompat extends AudioManagerCompat { - - private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) - .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) - .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL) - .build(); - - private Api21AudioManagerCompat(@NonNull Context context) { - super(context); - } - - @Override - public SoundPool createSoundPool() { - return new SoundPool.Builder() - .setAudioAttributes(AUDIO_ATTRIBUTES) - .setMaxStreams(1) - .build(); - } - - @Override - public void requestCallAudioFocus() { - int result = audioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_VOICE_CALL, AUDIOFOCUS_GAIN); - - if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { - Log.w(TAG, "Audio focus not granted. Result code: " + result); - } - } - - @Override - public void abandonCallAudioFocus() { - int result = audioManager.abandonAudioFocus(onAudioFocusChangeListener); - - if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { - Log.w(TAG, "Audio focus abandon failed. Result code: " + result); - } - } - } } diff --git a/build.gradle b/build.gradle index 08efb9ca24..ef9f081e96 100644 --- a/build.gradle +++ b/build.gradle @@ -69,7 +69,7 @@ allprojects { } project.ext { - androidMinimumSdkVersion = 23 + androidMinimumSdkVersion = 26 androidTargetSdkVersion = 34 androidCompileSdkVersion = 34 } diff --git a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt index 099b2541ab..c3335c5a99 100644 --- a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt @@ -73,8 +73,8 @@ object SnodeAPI { private const val maxRetryCount = 6 private const val minimumSnodePoolCount = 12 private const val minimumSwarmSnodeCount = 3 - // Use port 4433 if the API level can handle the network security configuration and enforce pinned certificates - private val seedNodePort = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) 443 else 4443 + // Use port 4433 to enforce pinned certificates + private val seedNodePort = 4443 private const val useTestnet = false diff --git a/libsession/src/main/java/org/session/libsession/utilities/DecodedAudio.kt b/libsession/src/main/java/org/session/libsession/utilities/DecodedAudio.kt index ef21abe4c0..a342ee1ae5 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/DecodedAudio.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/DecodedAudio.kt @@ -5,17 +5,12 @@ import android.media.MediaCodec import android.media.MediaDataSource import android.media.MediaExtractor import android.media.MediaFormat -import android.os.Build - -import androidx.annotation.RequiresApi - import java.io.FileDescriptor import java.io.IOException import java.io.InputStream import java.nio.ByteBuffer import java.nio.ByteOrder import java.nio.ShortBuffer -import kotlin.jvm.Throws import kotlin.math.ceil import kotlin.math.roundToInt import kotlin.math.sqrt @@ -44,7 +39,6 @@ class DecodedAudio { } @JvmStatic - @RequiresApi(api = Build.VERSION_CODES.M) @Throws(IOException::class) fun create(dataSource: MediaDataSource): DecodedAudio { val mediaExtractor = MediaExtractor().apply { setDataSource(dataSource) } @@ -69,15 +63,7 @@ class DecodedAudio { val samples: ShortBuffer get() { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && - Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 - ) { - // Hack for Nougat where asReadOnlyBuffer fails to respect byte ordering. - // See https://code.google.com/p/android/issues/detail?id=223824 - decodedSamples - } else { - decodedSamples.asReadOnlyBuffer() - } + return decodedSamples.asReadOnlyBuffer() } /** @@ -128,15 +114,13 @@ class DecodedAudio { codec.start() // Check if the track is in PCM 16 bit encoding. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - try { - val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING) - if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) { - throw IOException("Unsupported PCM encoding code: $pcmEncoding") - } - } catch (e: NullPointerException) { - // If KEY_PCM_ENCODING is not specified, means it's ENCODING_PCM_16BIT. + try { + val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING) + if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) { + throw IOException("Unsupported PCM encoding code: $pcmEncoding") } + } catch (e: NullPointerException) { + // If KEY_PCM_ENCODING is not specified, means it's ENCODING_PCM_16BIT. } var decodedSamplesSize: Int = 0 // size of the output buffer containing decoded samples. diff --git a/libsession/src/main/java/org/session/libsession/utilities/ServiceUtil.java b/libsession/src/main/java/org/session/libsession/utilities/ServiceUtil.java index 394a8a0f31..a66d5bf840 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/ServiceUtil.java +++ b/libsession/src/main/java/org/session/libsession/utilities/ServiceUtil.java @@ -6,13 +6,8 @@ import android.app.NotificationManager; import android.content.Context; import android.media.AudioManager; import android.net.ConnectivityManager; -import android.os.Build; import android.os.PowerManager; import android.os.Vibrator; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; @@ -54,8 +49,4 @@ public class ServiceUtil { return (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) - public static @Nullable SubscriptionManager getSubscriptionManager(@NonNull Context context) { - return (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - } } diff --git a/libsession/src/main/java/org/session/libsession/utilities/ViewUtil.java b/libsession/src/main/java/org/session/libsession/utilities/ViewUtil.java index 34a0212c63..f8ca27cfff 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/ViewUtil.java +++ b/libsession/src/main/java/org/session/libsession/utilities/ViewUtil.java @@ -19,21 +19,16 @@ package org.session.libsession.utilities; import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewStub; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import android.widget.LinearLayout.LayoutParams; import androidx.annotation.IdRes; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.view.ViewCompat; import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import org.session.libsignal.utilities.ListenableFuture; @@ -42,58 +37,7 @@ import org.session.libsignal.utilities.SettableFuture; public class ViewUtil { @SuppressWarnings("deprecation") public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - v.setBackground(drawable); - } else { - v.setBackgroundDrawable(drawable); - } - } - - public static void setY(final @NonNull View v, final int y) { - if (VERSION.SDK_INT >= 11) { - ViewCompat.setY(v, y); - } else { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v.getLayoutParams(); - params.topMargin = y; - v.setLayoutParams(params); - } - } - - public static float getY(final @NonNull View v) { - if (VERSION.SDK_INT >= 11) { - return ViewCompat.getY(v); - } else { - return ((ViewGroup.MarginLayoutParams)v.getLayoutParams()).topMargin; - } - } - - public static void setX(final @NonNull View v, final int x) { - if (VERSION.SDK_INT >= 11) { - ViewCompat.setX(v, x); - } else { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v.getLayoutParams(); - params.leftMargin = x; - v.setLayoutParams(params); - } - } - - public static float getX(final @NonNull View v) { - if (VERSION.SDK_INT >= 11) { - return ViewCompat.getX(v); - } else { - return ((LayoutParams)v.getLayoutParams()).leftMargin; - } - } - - public static void swapChildInPlace(ViewGroup parent, View toRemove, View toAdd, int defaultIndex) { - int childIndex = parent.indexOfChild(toRemove); - if (childIndex > -1) parent.removeView(toRemove); - parent.addView(toAdd, childIndex > -1 ? childIndex : defaultIndex); - } - - @SuppressWarnings("unchecked") - public static T inflateStub(@NonNull View parent, @IdRes int stubId) { - return (T)((ViewStub)parent.findViewById(stubId)).inflate(); + v.setBackground(drawable); } @SuppressWarnings("unchecked") @@ -106,10 +50,6 @@ public class ViewUtil { return (T) parent.findViewById(resId); } - public static Stub findStubById(@NonNull Activity parent, @IdRes int resId) { - return new Stub((ViewStub)parent.findViewById(resId)); - } - private static Animation getAlphaAnimation(float from, float to, int duration) { final Animation anim = new AlphaAnimation(from, to); anim.setInterpolator(new FastOutSlowInInterpolator()); @@ -177,58 +117,4 @@ public class ViewUtil { return (int)((dp * context.getResources().getDisplayMetrics().density) + 0.5); } - public static void updateLayoutParams(@NonNull View view, int width, int height) { - view.getLayoutParams().width = width; - view.getLayoutParams().height = height; - view.requestLayout(); - } - - public static int getLeftMargin(@NonNull View view) { - if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) { - return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin; - } - return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin; - } - - public static int getRightMargin(@NonNull View view) { - if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) { - return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin; - } - return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin; - } - - public static void setLeftMargin(@NonNull View view, int margin) { - if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) { - ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin; - } else { - ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin; - } - view.forceLayout(); - view.requestLayout(); - } - - public static void setTopMargin(@NonNull View view, int margin) { - ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = margin; - view.requestLayout(); - } - - public static void setPaddingTop(@NonNull View view, int padding) { - view.setPadding(view.getPaddingLeft(), padding, view.getPaddingRight(), view.getPaddingBottom()); - } - - public static void setPaddingBottom(@NonNull View view, int padding) { - view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding); - } - - public static boolean isPointInsideView(@NonNull View view, float x, float y) { - int[] location = new int[2]; - - view.getLocationOnScreen(location); - - int viewX = location[0]; - int viewY = location[1]; - - return x > viewX && x < viewX + view.getWidth() && - y > viewY && y < viewY + view.getHeight(); - } } diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java index 0aef158387..ac0c9067c4 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java @@ -718,7 +718,7 @@ public class Recipient implements RecipientModifiedListener { } public synchronized @Nullable String getNotificationChannel() { - return !(Build.VERSION.SDK_INT >= 26) ? null : notificationChannel; + return notificationChannel; } public void setNotificationChannel(@Nullable String value) {