Bumping min sdk to 26 and further cleaning version checks

This commit is contained in:
ThomasSession 2024-08-15 10:32:22 +10:00
parent a585e9c091
commit 088368769d
39 changed files with 119 additions and 854 deletions

View File

@ -4,12 +4,8 @@ import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import android.view.KeyEvent;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper; import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper;

View File

@ -17,7 +17,6 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
@ -26,7 +25,6 @@ import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -57,6 +55,9 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import org.session.libsession.messaging.messages.control.DataExtractionNotification; import org.session.libsession.messaging.messages.control.DataExtractionNotification;
import org.session.libsession.messaging.sending_receiving.MessageSender; import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment; import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
@ -72,8 +73,6 @@ import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel; import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter; 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.mms.Slide;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.AttachmentUtil;

View File

@ -2,15 +2,10 @@ package org.thoughtcrime.securesms.components;
import android.Manifest; import android.Manifest;
import android.animation.Animator; import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import android.util.Pair; import android.util.Pair;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -26,8 +21,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import org.thoughtcrime.securesms.permissions.Permissions; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import org.session.libsession.utilities.ViewUtil; import org.session.libsession.utilities.ViewUtil;
import org.thoughtcrime.securesms.permissions.Permissions;
import network.loki.messenger.R; import network.loki.messenger.R;
@ -172,7 +171,6 @@ public class AttachmentTypeSelector extends PopupWindow {
button.startAnimation(animation); button.startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(contentView, Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
@ -191,7 +189,6 @@ public class AttachmentTypeSelector extends PopupWindow {
getContentView().startAnimation(animation); getContentView().startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(), Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),

View File

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import android.text.Spannable; import android.text.Spannable;
@ -16,15 +15,14 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.os.BuildCompat; import androidx.core.os.BuildCompat;
import androidx.core.view.inputmethod.EditorInfoCompat; import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat; import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat; 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.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
public class ComposeText extends EmojiEditText { public class ComposeText extends EmojiEditText {
@ -153,7 +151,6 @@ public class ComposeText extends EmojiEditText {
} }
} }
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR2)
private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener { private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener {
private static final String TAG = CommitContentListener.class.getSimpleName(); private static final String TAG = CommitContentListener.class.getSimpleName();

View File

@ -1,9 +1,7 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
@ -27,7 +25,6 @@ public class ConversationItemAlertView extends LinearLayout {
initialize(attrs); initialize(attrs);
} }
@TargetApi(VERSION_CODES.HONEYCOMB)
public ConversationItemAlertView(final Context context, AttributeSet attrs, int defStyle) { public ConversationItemAlertView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
initialize(attrs); initialize(attrs);

View File

@ -1,9 +1,6 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.animation.AlphaAnimation; import android.view.animation.AlphaAnimation;
import android.view.animation.Animation; import android.view.animation.Animation;
@ -11,6 +8,8 @@ import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation; import android.view.animation.ScaleAnimation;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
public class HidingLinearLayout extends LinearLayout { public class HidingLinearLayout extends LinearLayout {
public HidingLinearLayout(Context context) { public HidingLinearLayout(Context context) {
@ -21,7 +20,6 @@ public class HidingLinearLayout extends LinearLayout {
super(context, attrs); super(context, attrs);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public HidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { public HidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }

View File

@ -1,13 +1,12 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.NonNull;
public class InputPanel extends LinearLayout { public class InputPanel extends LinearLayout {
public InputPanel(Context context) { public InputPanel(Context context) {
@ -18,7 +17,6 @@ public class InputPanel extends LinearLayout {
super(context, attrs); super(context, attrs);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public InputPanel(Context context, AttributeSet attrs, int defStyleAttr) { public InputPanel(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }

View File

@ -16,26 +16,25 @@
*/ */
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.appcompat.widget.LinearLayoutCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import org.session.libsignal.utilities.Log;
import android.view.Surface; import android.view.Surface;
import android.view.View; 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.ServiceUtil;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.utilities.Log;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import network.loki.messenger.R;
/** /**
* LinearLayout that, when a view container, will report back when it thinks a soft keyboard * LinearLayout that, when a view container, will report back when it thinks a soft keyboard
* has been opened and what its height would be. * has been opened and what its height would be.
@ -95,7 +94,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
private void updateKeyboardState() { private void updateKeyboardState() {
if (viewInset == 0 && Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) viewInset = getViewInset(); if (viewInset == 0) viewInset = getViewInset();
getWindowVisibleDisplayFrame(rect); getWindowVisibleDisplayFrame(rect);
@ -118,7 +117,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
} }
@TargetApi(VERSION_CODES.LOLLIPOP)
private int getViewInset() { private int getViewInset() {
try { try {
Field attachInfoField = View.class.getDeclaredField("mAttachInfo"); Field attachInfoField = View.class.getDeclaredField("mAttachInfo");

View File

@ -3,24 +3,24 @@ package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import android.net.Uri; 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.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import network.loki.messenger.R; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.RequestManager; import com.bumptech.glide.RequestManager;
import org.session.libsession.utilities.Stub;
import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.video.VideoPlayer; import org.thoughtcrime.securesms.video.VideoPlayer;
import org.session.libsession.utilities.Stub;
import java.io.IOException; import java.io.IOException;
import network.loki.messenger.R;
public class MediaView extends FrameLayout { public class MediaView extends FrameLayout {
private ZoomingImageView imageView; private ZoomingImageView imageView;
@ -41,12 +41,6 @@ public class MediaView extends FrameLayout {
initialize(); 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() { private void initialize() {
inflate(getContext(), R.layout.media_view, this); inflate(getContext(), R.layout.media_view, this);

View File

@ -1,19 +1,11 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore; 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.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -21,16 +13,24 @@ import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; 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.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature; 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.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader; 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<Cursor> { public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
@ -130,14 +130,12 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getWidthColumn(int orientation) { private String getWidthColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH; if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH;
else return MediaStore.Images.ImageColumns.HEIGHT; else return MediaStore.Images.ImageColumns.HEIGHT;
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getHeightColumn(int orientation) { private String getHeightColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT; if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT;

View File

@ -1,10 +1,7 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.BitmapFactory;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@ -24,7 +21,7 @@ public class SquareFrameLayout extends FrameLayout {
this(context, attrs, 0); this(context, attrs, 0);
} }
@TargetApi(VERSION_CODES.HONEYCOMB) @SuppressWarnings("unused") @SuppressWarnings("unused")
public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);

View File

@ -15,7 +15,6 @@
package org.thoughtcrime.securesms.components.camera; package org.thoughtcrime.securesms.components.camera;
import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
@ -28,26 +27,26 @@ import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size; import android.hardware.Camera.Size;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import org.session.libsignal.utilities.Log;
import android.view.OrientationEventListener; import android.view.OrientationEventListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import network.loki.messenger.R; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.util.BitmapUtil; import androidx.annotation.Nullable;
import org.session.libsignal.utilities.guava.Optional;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util; 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.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import network.loki.messenger.R;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class CameraView extends ViewGroup { public class CameraView extends ViewGroup {
private static final String TAG = CameraView.class.getSimpleName(); private static final String TAG = CameraView.class.getSimpleName();
@ -91,7 +90,6 @@ public class CameraView extends ViewGroup {
addView(surface); addView(surface);
} }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void onResume() { public void onResume() {
if (state != State.PAUSED) return; if (state != State.PAUSED) return;
state = State.RESUMED; state = State.RESUMED;
@ -255,33 +253,15 @@ public class CameraView extends ViewGroup {
return Camera.getNumberOfCameras() > 1; 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) { private void onCameraReady(final @NonNull Camera camera) {
final Parameters parameters = camera.getParameters(); final Parameters parameters = camera.getParameters();
if (VERSION.SDK_INT >= 14) { parameters.setRecordingHint(true);
parameters.setRecordingHint(true); final List<String> focusModes = parameters.getSupportedFocusModes();
final List<String> focusModes = parameters.getSupportedFocusModes(); if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
} else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
} }
displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo()); displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo());
@ -465,7 +445,7 @@ public class CameraView extends ViewGroup {
} }
final float newWidth = visibleRect.width() * scale; final float newWidth = visibleRect.width() * scale;
final float newHeight = visibleRect.height() * 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; final float centerY = previewHeight / 2;
visibleRect.set((int) (centerX - newWidth / 2), visibleRect.set((int) (centerX - newWidth / 2),

View File

@ -16,15 +16,9 @@
*/ */
package org.thoughtcrime.securesms.conversation.v2 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.content.Context
import android.graphics.Typeface import android.graphics.Typeface
import android.net.Uri import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.TextUtils import android.text.TextUtils
@ -33,22 +27,16 @@ import android.view.View
import com.annimon.stream.Stream import com.annimon.stream.Stream
import com.google.android.mms.pdu_alt.CharacterSets import com.google.android.mms.pdu_alt.CharacterSets
import com.google.android.mms.pdu_alt.EncodedStringValue import com.google.android.mms.pdu_alt.EncodedStringValue
import network.loki.messenger.R
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.components.ComposeText import org.thoughtcrime.securesms.components.ComposeText
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.IOException import java.io.IOException
import java.io.UnsupportedEncodingException import java.io.UnsupportedEncodingException
import java.util.Collections import java.util.Collections
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.math.min
object Util { object Util {
private val TAG: String = Log.tag(Util::class.java) private val TAG: String = Log.tag(Util::class.java)
private val BUILD_LIFESPAN = TimeUnit.DAYS.toMillis(90)
fun <T> asList(vararg elements: T): List<T> { fun <T> asList(vararg elements: T): List<T> {
val result = mutableListOf<T>() // LinkedList() val result = mutableListOf<T>() // LinkedList()
Collections.addAll(result, *elements) Collections.addAll(result, *elements)
@ -104,19 +92,6 @@ object Util {
return sb.toString() 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<EncodedStringValue?>?): Boolean { fun isEmpty(value: Array<EncodedStringValue?>?): Boolean {
return value == null || value.size == 0 return value == null || value.size == 0
} }
@ -133,64 +108,6 @@ object Util {
return charSequence == null || charSequence.length == 0 return charSequence == null || charSequence.length == 0
} }
fun hasItems(collection: Collection<*>?): Boolean {
return collection != null && !collection.isEmpty()
}
fun <K, V> getOrDefault(map: Map<K, V>, 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!")
}
}
fun wait(lock: Any, timeout: Long) { fun wait(lock: Any, timeout: Long) {
try { try {
(lock as Object).wait(timeout) (lock as Object).wait(timeout)
@ -225,20 +142,6 @@ object Util {
return parts 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 { fun trim(input: ByteArray?, length: Int): ByteArray {
val result = ByteArray(length) val result = ByteArray(length)
System.arraycopy(input, 0, result, 0, result.size) System.arraycopy(input, 0, result, 0, result.size)
@ -251,26 +154,6 @@ object Util {
else Uri.parse(uri) 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 * Returns half of the difference between the given length, and the length when scaled by the
* given scale. * given scale.
@ -280,74 +163,6 @@ object Util {
return (length - scaledLength) / 2 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 <T> concatenatedList(vararg items: Collection<T>): List<T> {
val concat: MutableList<T> = ArrayList(
Stream.of(*items).reduce(0) { sum: Int, list: Collection<T> -> 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 // Method to determine if we're currently in a left-to-right or right-to-left language like Arabic
fun usingLeftToRightLanguage(context: Context): Boolean { fun usingLeftToRightLanguage(context: Context): Boolean {
val config = context.resources.configuration val config = context.resources.configuration

View File

@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.conversation.v2.input_bar
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.net.Uri import android.net.Uri
import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
@ -57,7 +56,7 @@ class InputBarEditText : AppCompatEditText {
InputConnectionCompat.OnCommitContentListener { inputContentInfo, flags, opts -> InputConnectionCompat.OnCommitContentListener { inputContentInfo, flags, opts ->
val lacksPermission = (flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0 val lacksPermission = (flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0
// read and display inputContentInfo asynchronously // read and display inputContentInfo asynchronously
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && lacksPermission) { if (lacksPermission) {
try { try {
inputContentInfo.requestPermission() inputContentInfo.requestPermission()
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -42,9 +42,8 @@ class BiometricSecretProvider {
builder.setUnlockedDeviceRequired(true) builder.setUnlockedDeviceRequired(true)
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { builder.setInvalidatedByBiometricEnrollment(true)
builder.setInvalidatedByBiometricEnrollment(true)
}
keyGenerator.initialize(builder.build()) keyGenerator.initialize(builder.build())
keyGenerator.generateKeyPair() keyGenerator.generateKeyPair()
} }

View File

@ -252,11 +252,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
NotificationManager notificationManager = context.getSystemService(NotificationManager.class); NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
String channelId = context.getString(R.string.NotificationChannel_failures); String channelId = context.getString(R.string.NotificationChannel_failures);
if (NotificationChannels.supported()) { NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH); channel.enableVibration(true);
channel.enableVibration(true); notificationManager.createNotificationChannel(channel);
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification) .setSmallIcon(R.drawable.ic_notification)
@ -266,10 +264,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
.setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade)) .setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade))
.setAutoCancel(true); .setAutoCancel(true);
if (!NotificationChannels.supported()) {
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
}
notificationManager.notify(5874, builder.build()); notificationManager.notify(5874, builder.build());
// Throw the error (app will crash but there is nothing else we can do unfortunately) // Throw the error (app will crash but there is nothing else we can do unfortunately)

View File

@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.mediasend; package org.thoughtcrime.securesms.mediasend;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -200,14 +199,12 @@ class MediaRepository {
}).toList(); }).toList();
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getWidthColumn(int orientation) { private String getWidthColumn(int orientation) {
if (orientation == 0 || orientation == 180) return Images.Media.WIDTH; if (orientation == 0 || orientation == 180) return Images.Media.WIDTH;
else return Images.Media.HEIGHT; else return Images.Media.HEIGHT;
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getHeightColumn(int orientation) { private String getHeightColumn(int orientation) {
if (orientation == 0 || orientation == 180) return Images.Media.HEIGHT; if (orientation == 0 || orientation == 180) return Images.Media.HEIGHT;

View File

@ -50,8 +50,8 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
} }
public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) { public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) {
Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : TextSecurePreferences.getNotificationRingtone(context); Uri defaultRingtone = NotificationChannels.getMessageRingtone(context);
boolean defaultVibrate = NotificationChannels.supported() ? NotificationChannels.getMessageVibrate(context) : TextSecurePreferences.isNotificationVibrateEnabled(context); boolean defaultVibrate = NotificationChannels.getMessageVibrate(context);
if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone); if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone);
else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone); else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone);

View File

@ -37,10 +37,6 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE)); setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
setGroupSummary(true); setGroupSummary(true);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
public void setMessageCount(int messageCount, int threadCount) { public void setMessageCount(int messageCount, int threadCount) {

View File

@ -1,15 +1,12 @@
package org.thoughtcrime.securesms.notifications; package org.thoughtcrime.securesms.notifications;
import android.annotation.TargetApi;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes; import android.media.AudioAttributes;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; 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.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.recipients.Recipient; import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.Recipient.VibrateState;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
@ -63,10 +59,6 @@ public class NotificationChannels {
* ignored for API < 26. * ignored for API < 26.
*/ */
public static synchronized void create(@NonNull Context context) { public static synchronized void create(@NonNull Context context) {
if (!supported()) {
return;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int oldVersion = TextSecurePreferences.getNotificationChannelVersion(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. * @return The channel ID for the default messages channel.
*/ */
@ -115,13 +81,6 @@ public class NotificationChannels {
return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context)); 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. * @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. * @return The message ringtone set for the default message channel.
*/ */
public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) { public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) {
if (!supported()) {
return Uri.EMPTY;
}
Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound(); Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound();
return sound == null ? Uri.EMPTY : sound; return sound == null ? Uri.EMPTY : sound;
} }
public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) { public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported() || recipient.getNotificationChannel() == null) {
return null;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel()); NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel());
@ -265,9 +123,6 @@ public class NotificationChannels {
* Update the message ringtone for the default message channel. * Update the message ringtone for the default message channel.
*/ */
public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) { 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)); Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri));
updateMessageChannel(context, channel -> { 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. * @return The vibrate settings for the default message channel.
*/ */
public static synchronized boolean getMessageVibrate(@NonNull Context context) { public static synchronized boolean getMessageVibrate(@NonNull Context context) {
if (!supported()) {
return false;
}
return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate(); 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. * Sets the vibrate property for the default message channel.
*/ */
public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) { public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating default vibrate with value: " + enabled); Log.i(TAG, "Updating default vibrate with value: " + enabled);
updateMessageChannel(context, channel -> channel.enableVibration(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 @WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) { public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(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) { private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) {
NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.NotificationChannel_group_messages)); NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.NotificationChannel_group_messages));
notificationManager.createNotificationChannelGroup(messagesGroup); notificationManager.createNotificationChannelGroup(messagesGroup);
@ -454,7 +210,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) { private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) {
Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion); Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion);
@ -469,7 +224,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) { private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) {
if ("none".equals(ledColor)) { if ("none".equals(ledColor)) {
channel.enableLights(false); channel.enableLights(false);
@ -484,7 +238,6 @@ public class NotificationChannels {
return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis(); return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis();
} }
@TargetApi(26)
private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) { private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) {
NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance()); NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance());
@ -505,27 +258,7 @@ public class NotificationChannels {
return MESSAGES_PREFIX + version; 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) { private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context); int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context);
@ -539,7 +272,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager, private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager,
@NonNull String channelId, @NonNull String channelId,
@NonNull String newChannelId, @NonNull String newChannelId,
@ -559,20 +291,17 @@ public class NotificationChannels {
return true; return true;
} }
@TargetApi(21)
private static AudioAttributes getRingtoneAudioAttributes() { private static AudioAttributes getRingtoneAudioAttributes() {
return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build(); .build();
} }
@TargetApi(26)
private static boolean channelExists(@Nullable NotificationChannel channel) { private static boolean channelExists(@Nullable NotificationChannel channel) {
return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId()); return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId());
} }
private interface ChannelUpdater { private interface ChannelUpdater {
@TargetApi(26)
void update(@NonNull NotificationChannel channel); void update(@NonNull NotificationChannel channel);
} }
} }

View File

@ -51,8 +51,7 @@ public class NotificationState {
Recipient recipient = notifications.getFirst().getRecipient(); Recipient recipient = notifications.getFirst().getRecipient();
if (recipient != null) { if (recipient != null) {
return NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context, recipient) return NotificationChannels.getMessageRingtone(context, recipient);
: recipient.resolve().getMessageRingtone();
} }
} }

View File

@ -32,9 +32,5 @@ public class PendingMessageNotificationBuilder extends AbstractNotificationBuild
setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)); setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
setAutoCancel(true); setAutoCancel(true);
setAlarms(null, Recipient.VibrateState.DEFAULT); setAlarms(null, Recipient.VibrateState.DEFAULT);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
} }

View File

@ -13,7 +13,6 @@ import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -24,11 +23,10 @@ import androidx.core.app.NotificationCompat.Action;
import androidx.core.app.RemoteInput; import androidx.core.app.RemoteInput;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.session.libsession.avatars.ContactColors;
import org.session.libsession.avatars.ContactPhoto; import org.session.libsession.avatars.ContactPhoto;
import org.session.libsession.avatars.ResourceContactPhoto;
import org.session.libsession.messaging.contacts.Contact; import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.utilities.NotificationPrivacyPreference; import org.session.libsession.utilities.NotificationPrivacyPreference;
import org.session.libsession.utilities.TextSecurePreferences; 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.database.SessionContactDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import com.bumptech.glide.Glide;
import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator; import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
@ -69,10 +66,6 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
setSmallIcon(R.drawable.ic_notification); setSmallIcon(R.drawable.ic_notification);
setColor(ContextCompat.getColor(context, R.color.accent_green)); setColor(ContextCompat.getColor(context, R.color.accent_green));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
public void setThread(@NonNull Recipient recipient) { 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); 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,
replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, actionName,
actionName, wearableReplyIntent)
wearableReplyIntent) .addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build())
.addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build()) .build();
.build();
}
Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply, Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
actionName, actionName,

View File

@ -210,15 +210,8 @@ public class Permissions {
.toArray(new String[0]); .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) { public static boolean hasAll(@NonNull Context context, String... permissions) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || return Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
} }

View File

@ -56,14 +56,14 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
true true
} }
if (NotificationChannels.supported()) {
prefs.setNotificationRingtone( prefs.setNotificationRingtone(
NotificationChannels.getMessageRingtone(requireContext()).toString() NotificationChannels.getMessageRingtone(requireContext()).toString()
) )
prefs.setNotificationVibrateEnabled( prefs.setNotificationVibrateEnabled(
NotificationChannels.getMessageVibrate(requireContext()) NotificationChannels.getMessageVibrate(requireContext())
) )
}
findPreference<Preference>(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceChangeListener = RingtoneSummaryListener() findPreference<Preference>(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceChangeListener = RingtoneSummaryListener()
findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)!!.onPreferenceChangeListener = NotificationPrivacyListener() findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)!!.onPreferenceChangeListener = NotificationPrivacyListener()
findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF)!!.onPreferenceChangeListener = findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF)!!.onPreferenceChangeListener =
@ -99,18 +99,18 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
true true
} }
initializeListSummary(findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) as ListPreference?) initializeListSummary(findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) as ListPreference?)
if (NotificationChannels.supported()) {
findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener = findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
intent.putExtra( intent.putExtra(
Settings.EXTRA_CHANNEL_ID, NotificationChannels.getMessagesChannel(requireContext()) Settings.EXTRA_CHANNEL_ID, NotificationChannels.getMessagesChannel(requireContext())
) )
intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName)
startActivity(intent) startActivity(intent)
true true
} }
}
initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF)) initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF))
initializeMessageVibrateSummary(findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF) as SwitchPreferenceCompat?) initializeMessageVibrateSummary(findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF) as SwitchPreferenceCompat?)
} }

View File

@ -78,14 +78,9 @@ class PrivacySettingsPreferenceFragment : ListSummaryPreferenceFragment() {
title(R.string.CallNotificationBuilder_system_notification_title) title(R.string.CallNotificationBuilder_system_notification_title)
text(R.string.CallNotificationBuilder_system_notification_message) text(R.string.CallNotificationBuilder_system_notification_message)
button(R.string.activity_notification_settings_title) { button(R.string.activity_notification_settings_title) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
} else {
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
}
.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
.takeIf { IntentUtils.isResolvable(requireContext(), it) }.let { .takeIf { IntentUtils.isResolvable(requireContext(), it) }.let {
startActivity(it) startActivity(it)
} }

View File

@ -7,7 +7,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.util.SparseArray import android.util.SparseArray
@ -210,7 +209,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.settings_general, menu) 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_view_qr_code) menu.findItem(R.id.action_qr_code)?.contentDescription = resources.getString(R.string.AccessibilityId_view_qr_code)
} }
return true return true

View File

@ -2,14 +2,12 @@ package org.thoughtcrime.securesms.preferences.widgets;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.TextView; import android.widget.TextView;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceViewHolder;
import network.loki.messenger.R; import network.loki.messenger.R;
public class SignalListPreference extends ListPreference { public class SignalListPreference extends ListPreference {
@ -18,13 +16,11 @@ public class SignalListPreference extends ListPreference {
private CharSequence summary; private CharSequence summary;
private OnPreferenceClickListener clickListener; private OnPreferenceClickListener clickListener;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
initialize(); initialize();
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) { public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
initialize(); initialize();

View File

@ -23,7 +23,6 @@
package org.thoughtcrime.securesms.scribbles.widget; package org.thoughtcrime.securesms.scribbles.widget;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -34,7 +33,6 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Shader; import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -98,12 +96,6 @@ public class VerticalSlideColorPicker extends View {
init(); 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() { private void init() {
setWillNotDraw(false); setWillNotDraw(false);

View File

@ -18,17 +18,15 @@ package org.thoughtcrime.securesms.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.text.format.DateFormat;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.os.Build;
import android.text.format.DateFormat;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -127,11 +125,7 @@ public class DateUtils extends android.text.format.DateUtils {
@SuppressLint("ObsoleteSdkInt") @SuppressLint("ObsoleteSdkInt")
public static long parseIso8601(@Nullable String date) { public static long parseIso8601(@Nullable String date) {
SimpleDateFormat format; SimpleDateFormat format;
if (Build.VERSION.SDK_INT >= 24) { format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault());
format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault());
} else {
format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
}
if (date.isEmpty()) { if (date.isEmpty()) {
return -1; return -1;

View File

@ -1,15 +1,15 @@
package org.thoughtcrime.securesms.util; package org.thoughtcrime.securesms.util;
import android.annotation.TargetApi;
import android.content.ClipData; import android.content.ClipData;
import android.content.Context; import android.content.Context;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import network.loki.messenger.R; import network.loki.messenger.R;
public class LongClickCopySpan extends URLSpan { public class LongClickCopySpan extends URLSpan {
@ -39,23 +39,10 @@ public class LongClickCopySpan extends URLSpan {
ds.setUnderlineText(!isHighlighted); ds.setUnderlineText(!isHighlighted);
} }
void setHighlighted(boolean highlighted, @ColorInt int highlightColor) {
this.isHighlighted = highlighted;
this.highlightColor = highlightColor;
}
private void copyUrl(Context context, String url) { private void copyUrl(Context context, String url) {
int sdk = android.os.Build.VERSION.SDK_INT; copyUriSdk11(context, url);
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) { private void copyUriSdk11(Context context, String url) {
android.content.ClipboardManager clipboard = android.content.ClipboardManager clipboard =
(android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);

View File

@ -131,7 +131,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
int layoutPos) int layoutPos)
{ {
int headerHeight = getHeaderHeightForLayout(header); int headerHeight = getHeaderHeightForLayout(header);
int top = getChildY(parent, child) - headerHeight; int top = (int)child.getY() - headerHeight;
if (sticky && layoutPos == 0) { if (sticky && layoutPos == 0) {
final int count = parent.getChildCount(); final int count = parent.getChildCount();
final long currentId = adapter.getHeaderId(adapterPos); final long currentId = adapter.getHeaderId(adapterPos);
@ -142,7 +142,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
long nextId = adapter.getHeaderId(adapterPosHere); long nextId = adapter.getHeaderId(adapterPosHere);
if (nextId != currentId) { if (nextId != currentId) {
final View next = parent.getChildAt(translatedChildPosition(parent, i)); 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) { if (offset < 0) {
return offset; return offset;
} else { } else {
@ -162,16 +162,6 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
return isReverseLayout(parent) ? parent.getChildCount() - 1 - position : position; 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) { protected int getHeaderHeightForLayout(View header) {
return renderInline ? 0 : header.getHeight(); return renderInline ? 0 : header.getHeight();
} }

View File

@ -8,7 +8,6 @@ import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest; import android.media.AudioFocusRequest;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.SoundPool; import android.media.SoundPool;
import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
@ -116,14 +115,9 @@ public abstract class AudioManagerCompat {
abstract public void abandonCallAudioFocus(); abstract public void abandonCallAudioFocus();
public static AudioManagerCompat create(@NonNull Context context) { public static AudioManagerCompat create(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 26) { return new Api26AudioManagerCompat(context);
return new Api26AudioManagerCompat(context);
} else {
return new Api21AudioManagerCompat(context);
}
} }
@RequiresApi(26)
private static class Api26AudioManagerCompat extends AudioManagerCompat { private static class Api26AudioManagerCompat extends AudioManagerCompat {
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()

View File

@ -69,7 +69,7 @@ allprojects {
} }
project.ext { project.ext {
androidMinimumSdkVersion = 23 androidMinimumSdkVersion = 26
androidTargetSdkVersion = 34 androidTargetSdkVersion = 34
androidCompileSdkVersion = 34 androidCompileSdkVersion = 34
} }

View File

@ -73,8 +73,8 @@ object SnodeAPI {
private const val maxRetryCount = 6 private const val maxRetryCount = 6
private const val minimumSnodePoolCount = 12 private const val minimumSnodePoolCount = 12
private const val minimumSwarmSnodeCount = 3 private const val minimumSwarmSnodeCount = 3
// Use port 4433 if the API level can handle the network security configuration and enforce pinned certificates // Use port 4433 to enforce pinned certificates
private val seedNodePort = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) 443 else 4443 private val seedNodePort = 4443
private const val useTestnet = false private const val useTestnet = false

View File

@ -5,17 +5,12 @@ import android.media.MediaCodec
import android.media.MediaDataSource import android.media.MediaDataSource
import android.media.MediaExtractor import android.media.MediaExtractor
import android.media.MediaFormat import android.media.MediaFormat
import android.os.Build
import androidx.annotation.RequiresApi
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.nio.ShortBuffer import java.nio.ShortBuffer
import kotlin.jvm.Throws
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.sqrt import kotlin.math.sqrt
@ -44,7 +39,6 @@ class DecodedAudio {
} }
@JvmStatic @JvmStatic
@RequiresApi(api = Build.VERSION_CODES.M)
@Throws(IOException::class) @Throws(IOException::class)
fun create(dataSource: MediaDataSource): DecodedAudio { fun create(dataSource: MediaDataSource): DecodedAudio {
val mediaExtractor = MediaExtractor().apply { setDataSource(dataSource) } val mediaExtractor = MediaExtractor().apply { setDataSource(dataSource) }
@ -69,15 +63,7 @@ class DecodedAudio {
val samples: ShortBuffer val samples: ShortBuffer
get() { get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && return decodedSamples.asReadOnlyBuffer()
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()
}
} }
/** /**
@ -128,15 +114,13 @@ class DecodedAudio {
codec.start() codec.start()
// Check if the track is in PCM 16 bit encoding. // Check if the track is in PCM 16 bit encoding.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { try {
try { val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING)
val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING) if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) {
if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) { throw IOException("Unsupported PCM encoding code: $pcmEncoding")
throw IOException("Unsupported PCM encoding code: $pcmEncoding")
}
} catch (e: NullPointerException) {
// If KEY_PCM_ENCODING is not specified, means it's ENCODING_PCM_16BIT.
} }
} 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. var decodedSamplesSize: Int = 0 // size of the output buffer containing decoded samples.

View File

@ -6,13 +6,8 @@ import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.Build;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Vibrator; 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.telephony.TelephonyManager;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@ -54,8 +49,4 @@ public class ServiceUtil {
return (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); 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);
}
} }

View File

@ -19,21 +19,16 @@ package org.session.libsession.utilities;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.animation.AlphaAnimation; import android.view.animation.AlphaAnimation;
import android.view.animation.Animation; import android.view.animation.Animation;
import android.widget.LinearLayout.LayoutParams;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import org.session.libsignal.utilities.ListenableFuture; import org.session.libsignal.utilities.ListenableFuture;
@ -42,58 +37,7 @@ import org.session.libsignal.utilities.SettableFuture;
public class ViewUtil { public class ViewUtil {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) { public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { v.setBackground(drawable);
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 extends View> T inflateStub(@NonNull View parent, @IdRes int stubId) {
return (T)((ViewStub)parent.findViewById(stubId)).inflate();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -106,10 +50,6 @@ public class ViewUtil {
return (T) parent.findViewById(resId); return (T) parent.findViewById(resId);
} }
public static <T extends View> Stub<T> findStubById(@NonNull Activity parent, @IdRes int resId) {
return new Stub<T>((ViewStub)parent.findViewById(resId));
}
private static Animation getAlphaAnimation(float from, float to, int duration) { private static Animation getAlphaAnimation(float from, float to, int duration) {
final Animation anim = new AlphaAnimation(from, to); final Animation anim = new AlphaAnimation(from, to);
anim.setInterpolator(new FastOutSlowInInterpolator()); anim.setInterpolator(new FastOutSlowInInterpolator());
@ -177,58 +117,4 @@ public class ViewUtil {
return (int)((dp * context.getResources().getDisplayMetrics().density) + 0.5); 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();
}
} }

View File

@ -718,7 +718,7 @@ public class Recipient implements RecipientModifiedListener {
} }
public synchronized @Nullable String getNotificationChannel() { public synchronized @Nullable String getNotificationChannel() {
return !(Build.VERSION.SDK_INT >= 26) ? null : notificationChannel; return notificationChannel;
} }
public void setNotificationChannel(@Nullable String value) { public void setNotificationChannel(@Nullable String value) {