Removing unrequired APi checks (#1620)

* Removing unrequired APi checks

* Bumping min sdk to 26 and further cleaning version checks

* More clean ups

* Removed unused class
This commit is contained in:
ThomasSession
2024-08-15 15:32:41 +10:00
committed by GitHub
parent 5a248da445
commit 93a28906fb
58 changed files with 201 additions and 1165 deletions

View File

@@ -291,10 +291,6 @@
android:name="org.thoughtcrime.securesms.scribbles.StickerSelectActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:theme="@style/Theme.Session.ForceDark" />
<activity
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat" />
<activity
android:name="org.thoughtcrime.securesms.ShortcutLauncherActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"

View File

@@ -4,12 +4,8 @@ import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
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 android.view.KeyEvent;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper;

View File

@@ -39,7 +39,9 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.loader.app.LoaderManager;
@@ -421,11 +423,13 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
mode.getMenuInflater().inflate(R.menu.media_overview_context, menu);
mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getActivity().getWindow();
originalStatusBarColor = window.getStatusBarColor();
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
FragmentActivity activity = getActivity();
if (activity == null) return false;
Window window = activity.getWindow();
originalStatusBarColor = window.getStatusBarColor();
window.setStatusBarColor(ContextCompat.getColor(activity, R.color.action_mode_status_bar));
return true;
}
@@ -455,11 +459,12 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
getListAdapter().clearSelection();
((MediaOverviewActivity) getActivity()).onExitMultiSelect();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
MediaOverviewActivity activity = ((MediaOverviewActivity) getActivity());
if(activity == null) return;
activity.onExitMultiSelect();
activity.getWindow().setStatusBarColor(originalStatusBarColor);
}
}
}

View File

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

View File

@@ -1,22 +1,19 @@
package org.thoughtcrime.securesms.audio;
import android.annotation.TargetApi;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.os.Build;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.Util;
import org.session.libsignal.utilities.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class AudioCodec {
private static final String TAG = AudioCodec.class.getSimpleName();

View File

@@ -46,7 +46,7 @@ public class AudioSlidePlayer implements SensorEventListener {
private final @NonNull Handler progressEventHandler;
private final @NonNull AudioManager audioManager;
private final @NonNull SensorManager sensorManager;
private final @NonNull Sensor proximitySensor;
private final Sensor proximitySensor;
private final @Nullable WakeLock wakeLock;
private @NonNull WeakReference<Listener> listener;
@@ -132,7 +132,9 @@ public class AudioSlidePlayer implements SensorEventListener {
mediaPlayer.seekTo((long) (mediaPlayer.getDuration() * progress));
}
sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
if(proximitySensor != null) {
sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
setPlaying(AudioSlidePlayer.this);
}

View File

@@ -2,15 +2,10 @@ package org.thoughtcrime.securesms.components;
import android.Manifest;
import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
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.view.Gravity;
import android.view.LayoutInflater;
@@ -26,8 +21,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
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.thoughtcrime.securesms.permissions.Permissions;
import network.loki.messenger.R;
@@ -126,25 +125,19 @@ public class AttachmentTypeSelector extends PopupWindow {
public void onGlobalLayout() {
getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowInCircular(anchor, getContentView());
} else {
animateWindowInTranslate(getContentView());
}
animateWindowInCircular(anchor, getContentView());
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateButtonIn(imageButton, ANIMATION_DURATION / 2);
animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
animateButtonIn(imageButton, ANIMATION_DURATION / 2);
animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
animateButtonIn(audioButton, ANIMATION_DURATION / 3);
animateButtonIn(locationButton, ANIMATION_DURATION / 3);
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
animateButtonIn(gifButton, ANIMATION_DURATION / 4);
animateButtonIn(contactButton, 0);
animateButtonIn(closeButton, 0);
}
animateButtonIn(audioButton, ANIMATION_DURATION / 3);
animateButtonIn(locationButton, ANIMATION_DURATION / 3);
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
animateButtonIn(gifButton, ANIMATION_DURATION / 4);
animateButtonIn(contactButton, 0);
animateButtonIn(closeButton, 0);
}
private void updateHeight() {
@@ -159,11 +152,7 @@ public class AttachmentTypeSelector extends PopupWindow {
@Override
public void dismiss() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowOutCircular(currentAnchor, getContentView());
} else {
animateWindowOutTranslate(getContentView());
}
animateWindowOutCircular(currentAnchor, getContentView());
}
public void setListener(@Nullable AttachmentClickedListener listener) {
@@ -182,7 +171,6 @@ public class AttachmentTypeSelector extends PopupWindow {
button.startAnimation(animation);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
@@ -201,7 +189,6 @@ public class AttachmentTypeSelector extends PopupWindow {
getContentView().startAnimation(animation);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),

View File

@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.text.Spannable;
@@ -16,15 +15,14 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.os.BuildCompat;
import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
public class ComposeText extends EmojiEditText {
@@ -136,7 +134,6 @@ public class ComposeText extends EmojiEditText {
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
if (Build.VERSION.SDK_INT < 21) return inputConnection;
if (mediaListener == null) return inputConnection;
if (inputConnection == null) return null;
@@ -154,7 +151,6 @@ public class ComposeText extends EmojiEditText {
}
}
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR2)
private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener {
private static final String TAG = CommitContentListener.class.getSimpleName();

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,24 +3,24 @@ package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import network.loki.messenger.R;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.RequestManager;
import org.session.libsession.utilities.Stub;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.video.VideoPlayer;
import org.session.libsession.utilities.Stub;
import java.io.IOException;
import network.loki.messenger.R;
public class MediaView extends FrameLayout {
private ZoomingImageView imageView;
@@ -41,12 +41,6 @@ public class MediaView extends FrameLayout {
initialize();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();
}
private void initialize() {
inflate(getContext(), R.layout.media_view, this);

View File

@@ -1,19 +1,11 @@
package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -21,16 +13,24 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature;
import network.loki.messenger.R;
import org.session.libsession.utilities.ViewUtil;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
import com.bumptech.glide.Glide;
import org.session.libsession.utilities.ViewUtil;
import network.loki.messenger.R;
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
@@ -130,14 +130,12 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
}
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination")
private String getWidthColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH;
else return MediaStore.Images.ImageColumns.HEIGHT;
}
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination")
private String getHeightColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT;

View File

@@ -94,15 +94,11 @@ public class SearchToolbar extends LinearLayout {
searchItem.expandActionView();
if (Build.VERSION.SDK_INT >= 21) {
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth());
animator.setDuration(400);
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth());
animator.setDuration(400);
setVisibility(View.VISIBLE);
animator.start();
} else {
setVisibility(View.VISIBLE);
}
setVisibility(View.VISIBLE);
animator.start();
}
}
@@ -116,19 +112,15 @@ public class SearchToolbar extends LinearLayout {
if (listener != null) listener.onSearchClosed();
if (Build.VERSION.SDK_INT >= 21) {
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0);
animator.setDuration(400);
animator.addListener(new AnimationCompleteListener() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(View.INVISIBLE);
}
});
animator.start();
} else {
setVisibility(View.INVISIBLE);
}
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0);
animator.setDuration(400);
animator.addListener(new AnimationCompleteListener() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(View.INVISIBLE);
}
});
animator.start();
}
}

View File

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

View File

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

View File

@@ -16,15 +16,9 @@
*/
package org.thoughtcrime.securesms.conversation.v2
import android.annotation.TargetApi
import android.app.ActivityManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Typeface
import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.text.Spannable
import android.text.SpannableString
import android.text.TextUtils
@@ -33,22 +27,16 @@ import android.view.View
import com.annimon.stream.Stream
import com.google.android.mms.pdu_alt.CharacterSets
import com.google.android.mms.pdu_alt.EncodedStringValue
import network.loki.messenger.R
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.components.ComposeText
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.UnsupportedEncodingException
import java.util.Collections
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.math.min
object Util {
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> {
val result = mutableListOf<T>() // LinkedList()
Collections.addAll(result, *elements)
@@ -104,19 +92,6 @@ object Util {
return sb.toString()
}
fun rightPad(value: String, length: Int): String {
if (value.length >= length) {
return value
}
val out = StringBuilder(value)
while (out.length < length) {
out.append(" ")
}
return out.toString()
}
fun isEmpty(value: Array<EncodedStringValue?>?): Boolean {
return value == null || value.size == 0
}
@@ -133,64 +108,6 @@ object Util {
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) {
try {
(lock as Object).wait(timeout)
@@ -225,20 +142,6 @@ object Util {
return parts
}
fun combine(vararg elements: ByteArray?): ByteArray {
try {
val baos = ByteArrayOutputStream()
for (element in elements) {
baos.write(element)
}
return baos.toByteArray()
} catch (e: IOException) {
throw AssertionError(e)
}
}
fun trim(input: ByteArray?, length: Int): ByteArray {
val result = ByteArray(length)
System.arraycopy(input, 0, result, 0, result.size)
@@ -251,26 +154,6 @@ object Util {
else Uri.parse(uri)
}
@TargetApi(VERSION_CODES.KITKAT)
fun isLowMemory(context: Context): Boolean {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice) ||
activityManager.largeMemoryClass <= 64
}
fun clamp(value: Int, min: Int, max: Int): Int {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toInt()
}
fun clamp(value: Long, min: Long, max: Long): Long {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toLong()
}
fun clamp(value: Float, min: Float, max: Float): Float {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toFloat()
}
/**
* Returns half of the difference between the given length, and the length when scaled by the
* given scale.
@@ -280,74 +163,6 @@ object Util {
return (length - scaledLength) / 2
}
fun readTextFromClipboard(context: Context): String? {
run {
val clipboardManager =
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
return if (clipboardManager.hasPrimaryClip() && clipboardManager.primaryClip!!.itemCount > 0) {
clipboardManager.primaryClip!!.getItemAt(0).text.toString()
} else {
null
}
}
}
fun writeTextToClipboard(context: Context, text: String) {
writeTextToClipboard(context, context.getString(R.string.app_name), text)
}
fun writeTextToClipboard(context: Context, label: String, text: String) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(label, text)
clipboard.setPrimaryClip(clip)
}
fun toIntExact(value: Long): Int {
if (value.toInt().toLong() != value) {
throw ArithmeticException("integer overflow")
}
return value.toInt()
}
fun isEquals(first: Long?, second: Long): Boolean {
return first != null && first == second
}
@SafeVarargs
fun <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
fun usingLeftToRightLanguage(context: Context): Boolean {
val config = context.resources.configuration

View File

@@ -148,11 +148,8 @@ class InputBarButton : RelativeLayout {
private fun onDown(event: MotionEvent) {
expand()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
} else {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
}
performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
longPressCallback?.let { gestureHandler.removeCallbacks(it) }
val newLongPressCallback = Runnable { onLongPress?.invoke() }
this.longPressCallback = newLongPressCallback

View File

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

View File

@@ -59,25 +59,17 @@ public class AttachmentSecretProvider {
{
AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return attachmentSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setAttachmentUnencryptedSecret(context, null);
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setAttachmentUnencryptedSecret(context, null);
return attachmentSecret;
}
return attachmentSecret;
}
private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
}
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
@@ -91,12 +83,8 @@ public class AttachmentSecretProvider {
}
private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setAttachmentUnencryptedSecret(context, attachmentSecret.serialize());
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
}
}

View File

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

View File

@@ -36,28 +36,20 @@ public class DatabaseSecretProvider {
try {
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return databaseSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
return databaseSecret;
}
return databaseSecret;
} catch (IOException e) {
throw new AssertionError(e);
}
}
private DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
}
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
@@ -66,12 +58,8 @@ public class DatabaseSecretProvider {
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setDatabaseUnencryptedSecret(context, databaseSecret.asString());
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
return databaseSecret;
}

View File

@@ -129,27 +129,19 @@ public class IdentityKeyUtil {
}
private static String getUnencryptedSecret(String key, String unencryptedSecret, Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return unencryptedSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes());
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes());
// save the encrypted suffix secret "key_encrypted"
save(context,key+ENCRYPTED_SUFFIX,encryptedSecret.serialize());
// delete the regular secret "key"
delete(context,key);
// save the encrypted suffix secret "key_encrypted"
save(context,key+ENCRYPTED_SUFFIX,encryptedSecret.serialize());
// delete the regular secret "key"
delete(context,key);
return unencryptedSecret;
}
return unencryptedSecret;
}
private static String getEncryptedSecret(String encryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret);
return new String(KeyStoreHelper.unseal(sealedData));
}
KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret);
return new String(KeyStoreHelper.unseal(sealedData));
}
@@ -157,17 +149,14 @@ public class IdentityKeyUtil {
SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0);
Editor preferencesEditor = preferences.edit();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX);
if (isEncryptedSuffix) {
preferencesEditor.putString(key, value);
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes());
preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize());
}
} else {
boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX);
if (isEncryptedSuffix) {
preferencesEditor.putString(key, value);
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes());
preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize());
}
if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences");
}

View File

@@ -966,11 +966,6 @@ public class AttachmentDatabase extends Database {
@SuppressLint("NewApi")
private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.w(TAG, "Video thumbnails not supported...");
return null;
}
DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA);
if (dataInfo == null) {

View File

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

View File

@@ -15,6 +15,7 @@ import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@@ -38,7 +39,6 @@ import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.getColorWithID
class PathActivity : PassphraseRequiredActionBarActivity() {
private lateinit var binding: ActivityPathBinding
@@ -283,7 +283,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private fun expand() {
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
@ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val startColor = ContextCompat.getColor(context, startColorID)
val endColor = context.getAccentColor()
GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
}
@@ -292,7 +292,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
@ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
val startColor = context.getAccentColor()
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val endColor = ContextCompat.getColor(context, endColorID)
GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
}

View File

@@ -9,6 +9,7 @@ import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.lifecycle.coroutineScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.coroutines.Dispatchers
@@ -17,7 +18,6 @@ import kotlinx.coroutines.withContext
import network.loki.messenger.R
import org.session.libsession.snode.OnionRequestAPI
import org.thoughtcrime.securesms.conversation.v2.ViewUtil
import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.toPx
class PathStatusView : View {
@@ -104,7 +104,7 @@ class PathStatusView : View {
sessionShadowColor = hasPathsColor
} else {
setBackgroundResource(R.drawable.paths_building_dot)
val pathsBuildingColor = resources.getColorWithID(R.color.paths_building, context.theme)
val pathsBuildingColor = ContextCompat.getColor(context, R.color.paths_building)
mainColor = pathsBuildingColor
sessionShadowColor = pathsBuildingColor
}

View File

@@ -8,11 +8,6 @@ public interface Constraint {
boolean isMet();
@NonNull String getFactoryKey();
@RequiresApi(26)
void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder);
interface Factory<T extends Constraint> {
T create();
}

View File

@@ -28,17 +28,6 @@ public class NetworkConstraint implements Constraint {
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@RequiresApi(26)
@Override
public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
public static final class Factory implements Constraint.Factory<NetworkConstraint> {
private final Application application;

View File

@@ -32,24 +32,16 @@ class LogSecretProvider {
}
private static byte[] parseEncryptedSecret(String secret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
return KeyStoreHelper.unseal(encryptedSecret);
} else {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
return KeyStoreHelper.unseal(encryptedSecret);
}
private static byte[] createAndStoreSecret(@NonNull Context context) {
byte[] secret = new byte[32];
SECURE_RANDOM.nextBytes(secret);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeBytes(secret));
}
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
return secret;
}

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,12 @@
package org.thoughtcrime.securesms.notifications;
import android.annotation.TargetApi;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
@@ -24,7 +21,6 @@ import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.Recipient.VibrateState;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
@@ -63,10 +59,6 @@ public class NotificationChannels {
* ignored for API < 26.
*/
public static synchronized void create(@NonNull Context context) {
if (!supported()) {
return;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context);
@@ -82,32 +74,6 @@ public class NotificationChannels {
});
}
/**
* Recreates all notification channels for contacts with custom notifications enabled. Should be
* safe to call repeatedly. Needs to be executed on a background thread.
*/
@WorkerThread
public static synchronized void restoreContactNotificationChannels(@NonNull Context context) {
if (!NotificationChannels.supported()) {
return;
}
RecipientDatabase db = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
Recipient recipient;
while ((recipient = reader.getNext()) != null) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
if (!channelExists(notificationManager.getNotificationChannel(recipient.getNotificationChannel()))) {
String id = createChannelFor(context, recipient);
db.setNotificationChannel(recipient, id);
}
}
}
ensureCustomChannelConsistency(context);
}
/**
* @return The channel ID for the default messages channel.
*/
@@ -115,13 +81,6 @@ public class NotificationChannels {
return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context));
}
/**
* @return Whether or not notification channels are supported.
*/
public static boolean supported() {
return Build.VERSION.SDK_INT >= 26;
}
/**
* @return A name suitable to be displayed as the notification channel title.
*/
@@ -137,119 +96,18 @@ public class NotificationChannels {
}
}
/**
* Creates a channel for the specified recipient.
* @return The channel ID for the newly-created channel.
*/
public static synchronized String createChannelFor(@NonNull Context context, @NonNull Recipient recipient) {
VibrateState vibrateState = recipient.getMessageVibrate();
boolean vibrationEnabled = vibrateState == VibrateState.DEFAULT ? TextSecurePreferences.isNotificationVibrateEnabled(context) : vibrateState == VibrateState.ENABLED;
Uri messageRingtone = recipient.getMessageRingtone() != null ? recipient.getMessageRingtone() : getMessageRingtone(context);
String displayName = getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress());
return createChannelFor(context, recipient.getAddress(), displayName, messageRingtone, vibrationEnabled);
}
/**
* More verbose version of {@link #createChannelFor(Context, Recipient)}.
*/
public static synchronized @Nullable String createChannelFor(@NonNull Context context,
@NonNull Address address,
@NonNull String displayName,
@Nullable Uri messageSound,
boolean vibrationEnabled)
{
if (!supported()) {
return null;
}
String channelId = generateChannelIdFor(address);
NotificationChannel channel = new NotificationChannel(channelId, displayName, NotificationManager.IMPORTANCE_HIGH);
setLedPreference(channel, TextSecurePreferences.getNotificationLedColor(context));
channel.setGroup(CATEGORY_MESSAGES);
channel.enableVibration(vibrationEnabled);
if (messageSound != null) {
channel.setSound(messageSound, new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build());
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
notificationManager.createNotificationChannel(channel);
return channelId;
}
/**
* Deletes the channel generated for the provided recipient. Safe to call even if there was never
* a channel made for that recipient.
*/
public static synchronized void deleteChannelFor(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported()) {
return;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
String channel = recipient.getNotificationChannel();
if (channel != null) {
Log.i(TAG, "Deleting channel");
notificationManager.deleteNotificationChannel(channel);
}
}
/**
* Navigates the user to the system settings for the desired notification channel.
*/
public static void openChannelSettings(@NonNull Context context, @NonNull String channelId) {
if (!supported()) {
return;
}
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
context.startActivity(intent);
}
/**
* Updates the LED color for message notifications and all contact-specific message notification
* channels. Performs database operations and should therefore be invoked on a background thread.
*/
@WorkerThread
public static synchronized void updateMessagesLedColor(@NonNull Context context, @NonNull Integer color) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating LED color.");
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
updateMessageChannel(context, channel -> setLedPreference(channel, color));
updateAllRecipientChannelLedColors(context, notificationManager, color);
ensureCustomChannelConsistency(context);
}
/**
* @return The message ringtone set for the default message channel.
*/
public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) {
if (!supported()) {
return Uri.EMPTY;
}
Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound();
return sound == null ? Uri.EMPTY : sound;
}
public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported() || recipient.getNotificationChannel() == null) {
return null;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel());
@@ -265,9 +123,6 @@ public class NotificationChannels {
* Update the message ringtone for the default message channel.
*/
public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri));
updateMessageChannel(context, channel -> {
@@ -275,121 +130,23 @@ public class NotificationChannels {
});
}
/**
* Updates the message ringtone for a specific recipient. If that recipient has no channel, this
* does nothing.
*
* This has to update the database, and therefore should be run on a background thread.
*/
@WorkerThread
public static synchronized void updateMessageRingtone(@NonNull Context context, @NonNull Recipient recipient, @Nullable Uri uri) {
if (!supported() || recipient.getNotificationChannel() == null) {
return;
}
Log.i(TAG, "Updating recipient message ringtone with URI: " + String.valueOf(uri));
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context),
recipient.getNotificationChannel(),
generateChannelIdFor(recipient.getAddress()),
channel -> channel.setSound(uri == null ? Settings.System.DEFAULT_NOTIFICATION_URI : uri, getRingtoneAudioAttributes()));
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
/**
* @return The vibrate settings for the default message channel.
*/
public static synchronized boolean getMessageVibrate(@NonNull Context context) {
if (!supported()) {
return false;
}
return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate();
}
/**
* @return The vibrate setting for a specific recipient. If that recipient has no channel, this
* will return the setting for the default message channel.
*/
public static synchronized boolean getMessageVibrate(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported()) {
return getMessageVibrate(context);
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel());
if (!channelExists(channel)) {
Log.w(TAG, "Recipient didn't have a channel. Returning message default.");
return getMessageVibrate(context);
}
return channel.shouldVibrate();
}
/**
* Sets the vibrate property for the default message channel.
*/
public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating default vibrate with value: " + enabled);
updateMessageChannel(context, channel -> channel.enableVibration(enabled));
}
/**
* Updates the message ringtone for a specific recipient. If that recipient has no channel, this
* does nothing.
*
* This has to update the database and should therefore be run on a background thread.
*/
@WorkerThread
public static synchronized void updateMessageVibrate(@NonNull Context context, @NonNull Recipient recipient, VibrateState vibrateState) {
if (!supported() || recipient.getNotificationChannel() == null) {
return ;
}
Log.i(TAG, "Updating recipient vibrate with value: " + vibrateState);
boolean enabled = vibrateState == VibrateState.DEFAULT ? getMessageVibrate(context) : vibrateState == VibrateState.ENABLED;
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context),
recipient.getNotificationChannel(),
newChannelId,
channel -> channel.enableVibration(enabled));
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
/**
* Updates the name of an existing channel to match the recipient's current name. Will have no
* effect if the recipient doesn't have an existing valid channel.
*/
public static synchronized void updateContactChannelName(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported() || recipient.getNotificationChannel() == null) {
return;
}
Log.i(TAG, "Updating contact channel name");
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
if (notificationManager.getNotificationChannel(recipient.getNotificationChannel()) == null) {
Log.w(TAG, "Tried to update the name of a channel, but that channel doesn't exist.");
return;
}
NotificationChannel channel = new NotificationChannel(recipient.getNotificationChannel(),
getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress()),
NotificationManager.IMPORTANCE_HIGH);
channel.setGroup(CATEGORY_MESSAGES);
notificationManager.createNotificationChannel(channel);
}
@TargetApi(26)
@WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
@@ -421,7 +178,6 @@ public class NotificationChannels {
}
}
@TargetApi(26)
private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) {
NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.NotificationChannel_group_messages));
notificationManager.createNotificationChannelGroup(messagesGroup);
@@ -454,7 +210,6 @@ public class NotificationChannels {
}
}
@TargetApi(26)
private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) {
Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion);
@@ -469,7 +224,6 @@ public class NotificationChannels {
}
}
@TargetApi(26)
private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) {
if ("none".equals(ledColor)) {
channel.enableLights(false);
@@ -484,7 +238,6 @@ public class NotificationChannels {
return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis();
}
@TargetApi(26)
private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) {
NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance());
@@ -505,27 +258,7 @@ public class NotificationChannels {
return MESSAGES_PREFIX + version;
}
@WorkerThread
@TargetApi(26)
private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Integer color) {
RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader recipients = database.getRecipientsWithNotificationChannels()) {
Recipient recipient;
while ((recipient = recipients.getNext()) != null) {
assert recipient.getNotificationChannel() != null;
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(notificationManager, recipient.getNotificationChannel(), newChannelId, channel -> setLedPreference(channel, color));
database.setNotificationChannel(recipient, success ? newChannelId : null);
}
}
ensureCustomChannelConsistency(context);
}
@TargetApi(26)
private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context);
@@ -539,7 +272,6 @@ public class NotificationChannels {
}
}
@TargetApi(26)
private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager,
@NonNull String channelId,
@NonNull String newChannelId,
@@ -559,20 +291,17 @@ public class NotificationChannels {
return true;
}
@TargetApi(21)
private static AudioAttributes getRingtoneAudioAttributes() {
return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build();
}
@TargetApi(26)
private static boolean channelExists(@Nullable NotificationChannel channel) {
return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId());
}
private interface ChannelUpdater {
@TargetApi(26)
void update(@NonNull NotificationChannel channel);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,6 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.util.SparseArray
@@ -210,7 +209,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.settings_general, menu)
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (BuildConfig.DEBUG) {
menu.findItem(R.id.action_qr_code)?.contentDescription = resources.getString(R.string.AccessibilityId_view_qr_code)
}
return true

View File

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

View File

@@ -23,7 +23,6 @@
package org.thoughtcrime.securesms.scribbles.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -34,7 +33,6 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -98,12 +96,6 @@ public class VerticalSlideColorPicker extends View {
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
setWillNotDraw(false);

View File

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

View File

@@ -14,10 +14,7 @@ public class FileProviderUtil {
private static final String AUTHORITY = "network.loki.securesms.fileprovider";
public static Uri getUriFor(@NonNull Context context, @NonNull File file) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
return FileProvider.getUriForFile(context, AUTHORITY, file);
else
return Uri.fromFile(file);
return FileProvider.getUriForFile(context, AUTHORITY, file);
}
public static boolean delete(@NonNull Context context, @NonNull Uri uri) {

View File

@@ -1,20 +1,9 @@
package org.thoughtcrime.securesms.util
import android.content.res.Resources
import android.os.Build
import androidx.annotation.ColorRes
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.max
import kotlin.math.roundToInt
fun Resources.getColorWithID(@ColorRes id: Int, theme: Resources.Theme?): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getColor(id, theme)
} else {
@Suppress("DEPRECATION") getColor(id)
}
}
fun toPx(dp: Int, resources: Resources): Int {
return toPx(dp.toFloat(), resources).roundToInt()
}

View File

@@ -11,7 +11,6 @@ import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import network.loki.messenger.R
import kotlin.math.roundToInt
@@ -22,18 +21,6 @@ interface GlowView {
object GlowViewUtilities {
fun animateColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
animation.addUpdateListener { animator ->
val color = animator.animatedValue as Int
view.mainColor = color
}
animation.start()
}
fun animateColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) {
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
@@ -44,18 +31,6 @@ object GlowViewUtilities {
animation.start()
}
fun animateShadowColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
animation.addUpdateListener { animator ->
val color = animator.animatedValue as Int
view.sessionShadowColor = color
}
animation.start()
}
fun animateShadowColorChange(
view: GlowView,
@ColorInt startColor: Int,

View File

@@ -1,74 +0,0 @@
package org.thoughtcrime.securesms.util;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.Context;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import android.text.TextPaint;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.Toast;
import network.loki.messenger.R;
public class LongClickCopySpan extends URLSpan {
private static final String PREFIX_MAILTO = "mailto:";
private static final String PREFIX_TEL = "tel:";
private boolean isHighlighted;
@ColorInt
private int highlightColor;
public LongClickCopySpan(String url) {
super(url);
}
void onLongClick(View widget) {
Context context = widget.getContext();
String preparedUrl = prepareUrl(getURL());
copyUrl(context, preparedUrl);
Toast.makeText(context,
context.getString(R.string.ConversationItem_copied_text, preparedUrl), Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.bgColor = highlightColor;
ds.setUnderlineText(!isHighlighted);
}
void setHighlighted(boolean highlighted, @ColorInt int highlightColor) {
this.isHighlighted = highlighted;
this.highlightColor = highlightColor;
}
private void copyUrl(Context context, String url) {
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
@SuppressWarnings("deprecation") android.text.ClipboardManager clipboard =
(android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(url);
} else {
copyUriSdk11(context, url);
}
}
@TargetApi(android.os.Build.VERSION_CODES.HONEYCOMB)
private void copyUriSdk11(Context context, String url) {
android.content.ClipboardManager clipboard =
(android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(context.getString(R.string.app_name), url);
clipboard.setPrimaryClip(clip);
}
private String prepareUrl(String url) {
if (url.startsWith(PREFIX_MAILTO)) {
return url.substring(PREFIX_MAILTO.length());
} else if (url.startsWith(PREFIX_TEL)) {
return url.substring(PREFIX_TEL.length());
}
return url;
}
}

View File

@@ -131,7 +131,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
int layoutPos)
{
int headerHeight = getHeaderHeightForLayout(header);
int top = getChildY(parent, child) - headerHeight;
int top = (int)child.getY() - headerHeight;
if (sticky && layoutPos == 0) {
final int count = parent.getChildCount();
final long currentId = adapter.getHeaderId(adapterPos);
@@ -142,7 +142,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
long nextId = adapter.getHeaderId(adapterPosHere);
if (nextId != currentId) {
final View next = parent.getChildAt(translatedChildPosition(parent, i));
final int offset = getChildY(parent, next) - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight());
final int offset = (int)next.getY() - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight());
if (offset < 0) {
return offset;
} else {
@@ -162,16 +162,6 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
return isReverseLayout(parent) ? parent.getChildCount() - 1 - position : position;
}
private int getChildY(RecyclerView parent, View child) {
if (VERSION.SDK_INT < 11) {
Rect rect = new Rect();
parent.getChildVisibleRect(child, rect, null);
return rect.top;
} else {
return (int)ViewCompat.getY(child);
}
}
protected int getHeaderHeightForLayout(View header) {
return renderInline ? 0 : header.getHeight();
}

View File

@@ -1,22 +1,20 @@
package org.thoughtcrime.securesms.video;
import android.annotation.TargetApi;
import android.media.MediaDataSource;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.session.libsession.utilities.Util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@TargetApi(Build.VERSION_CODES.M)
public class EncryptedMediaDataSource extends MediaDataSource {
private final AttachmentSecret attachmentSecret;

View File

@@ -8,10 +8,8 @@ import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.session.libsession.utilities.ServiceUtil;
import org.session.libsignal.utilities.Log;
@@ -116,14 +114,9 @@ public abstract class AudioManagerCompat {
abstract public void abandonCallAudioFocus();
public static AudioManagerCompat create(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 26) {
return new Api26AudioManagerCompat(context);
} else {
return new Api21AudioManagerCompat(context);
}
return new Api26AudioManagerCompat(context);
}
@RequiresApi(26)
private static class Api26AudioManagerCompat extends AudioManagerCompat {
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
@@ -180,44 +173,4 @@ public abstract class AudioManagerCompat {
audioFocusRequest = null;
}
}
@RequiresApi(21)
private static class Api21AudioManagerCompat extends AudioManagerCompat {
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
.build();
private Api21AudioManagerCompat(@NonNull Context context) {
super(context);
}
@Override
public SoundPool createSoundPool() {
return new SoundPool.Builder()
.setAudioAttributes(AUDIO_ATTRIBUTES)
.setMaxStreams(1)
.build();
}
@Override
public void requestCallAudioFocus() {
int result = audioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_VOICE_CALL, AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.w(TAG, "Audio focus not granted. Result code: " + result);
}
}
@Override
public void abandonCallAudioFocus() {
int result = audioManager.abandonAudioFocus(onAudioFocusChangeListener);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.w(TAG, "Audio focus abandon failed. Result code: " + result);
}
}
}
}