remove android 4 compatibility code

This commit is contained in:
adbenitez 2024-11-21 01:16:20 +01:00
parent a51013cc00
commit 0ca92ec6b5
74 changed files with 207 additions and 1077 deletions

View file

@ -28,11 +28,6 @@ public class FcmReceiveService extends FirebaseMessagingService {
private static volatile String prefixedToken;
public static void register(Context context) {
if (Build.VERSION.SDK_INT < 19) {
Log.w(TAG, "FCM not available on SDK < 19");
triedRegistering = true;
return;
}
if (FcmReceiveService.prefixedToken != null) {
Log.i(TAG, "FCM already registered");

View file

@ -36,7 +36,6 @@ import org.thoughtcrime.securesms.connect.KeepAliveService;
import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
import org.thoughtcrime.securesms.crypto.PRNGFixes;
import org.thoughtcrime.securesms.geolocation.DcLocationManager;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
@ -178,7 +177,6 @@ public class ApplicationContext extends MultiDexApplication {
KeepAliveService.maybeStartSelf(this);
initializeRandomNumberFix();
initializeLogging();
initializeJobManager();
InChatSounds.getInstance(this);
@ -226,10 +224,6 @@ public class ApplicationContext extends MultiDexApplication {
return jobManager;
}
private void initializeRandomNumberFix() {
PRNGFixes.apply();
}
private void initializeLogging() {
SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger());
}

View file

@ -152,10 +152,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
this.findPreference(PREFERENCE_CATEGORY_HELP)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
tintIcons(getActivity());
}
DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
}

View file

@ -33,9 +33,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
onPreCreate();
if (BaseActivity.isMenuWorkaroundRequired()) {
forceOverflowMenu();
}
super.onCreate(savedInstanceState);
}
@ -46,20 +43,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
dynamicTheme.onResume(this);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) {
openOptionsMenu();
return true;
}
return super.onKeyUp(keyCode, event);
}
private void initializeScreenshotSecurity() {
if (Prefs.isScreenSecurityEnabled(this)) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);

View file

@ -1,28 +0,0 @@
package org.thoughtcrime.securesms;
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;
public abstract class BaseActivity extends FragmentActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) {
openOptionsMenu();
return true;
}
return super.onKeyUp(keyCode, event);
}
public static boolean isMenuWorkaroundRequired() {
return VERSION.SDK_INT < VERSION_CODES.KITKAT && ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE));
}
}

View file

@ -364,9 +364,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
return true;
}
@ -395,11 +393,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
actionMode = null;
getListAdapter().initializeBatchMode(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
color.recycle();
}
Context context = getContext();
if (context != null) {

View file

@ -136,9 +136,7 @@ public class ContactSelectionListFragment extends Fragment
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.contact_list, menu);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu);
actionMode.setTitle("1");
return true;
@ -170,12 +168,10 @@ public class ContactSelectionListFragment extends Fragment
ContactSelectionListFragment.this.actionMode = null;
getContactSelectionListAdapter().resetActionModeSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
color.recycle();
}
}
};
return view;

View file

@ -940,12 +940,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
case AttachmentTypeSelector.TAKE_PHOTO:
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
case AttachmentTypeSelector.RECORD_VIDEO:
if(VideoRecoder.canRecode()) {
attachmentManager.captureVideo(this, RECORD_VIDEO);
}
else {
Toast.makeText(this, "This device does not support video-compression (requires Android 4.4 KitKat)", Toast.LENGTH_LONG).show();
}
break;
}
}

View file

@ -893,11 +893,9 @@ public class ConversationFragment extends MessageSelectorFragment
mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getActivity().getWindow();
statusBarColor = window.getStatusBarColor();
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
}
setCorrectMenuVisibility(menu);
ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
@ -914,9 +912,7 @@ public class ConversationFragment extends MessageSelectorFragment
((ConversationAdapter)list.getAdapter()).clearSelection();
list.getAdapter().notifyDataSetChanged();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(statusBarColor);
}
actionMode = null;
hideAddReactionView();

View file

@ -495,9 +495,7 @@ public class ConversationItem extends BaseConversationItem
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration);
audioViewStub.get().setOnClickListener(passthroughClickListener);
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -515,9 +513,7 @@ public class ConversationItem extends BaseConversationItem
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
documentViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -534,9 +530,7 @@ public class ConversationItem extends BaseConversationItem
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -554,9 +548,7 @@ public class ConversationItem extends BaseConversationItem
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
vcardViewStub.get().setOnLongClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -592,9 +584,7 @@ public class ConversationItem extends BaseConversationItem
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
setThumbnailOutlineCorners(messageRecord, showSender);
@ -617,9 +607,7 @@ public class ConversationItem extends BaseConversationItem
stickerStub.get().setThumbnailClickListener(new StickerClickListener());
stickerStub.get().setOnLongClickListener(passthroughClickListener);
stickerStub.get().setOnClickListener(passthroughClickListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

View file

@ -174,10 +174,8 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
vibrate(viewHolder.itemView.getContext());
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
recyclerView.cancelPendingInputEvents();
}
}
private static void resetProgress(RecyclerView.ViewHolder viewHolder) {
ConversationSwipeAnimationHelper.update((ConversationItem) viewHolder.itemView,
@ -199,11 +197,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
}
private static float getSignFromDirection(@NonNull View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
} else {
return 1f;
}
}
private static boolean sameSign(float dX, float sign) {

View file

@ -29,7 +29,6 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View file

@ -197,12 +197,11 @@ public class LogViewFragment extends Fragment {
asMegs(info.maxMemory()));
}
@TargetApi(VERSION_CODES.KITKAT)
public static String getMemoryClass(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
String lowMem = "";
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) {
if (activityManager.isLowRamDevice()) {
lowMem = ", low-mem device";
}
return activityManager.getMemoryClass() + lowMem;
@ -252,10 +251,8 @@ public class LogViewFragment extends Fragment {
Locale locale = Util.getLocale();
builder.append("lang=").append(locale.toString()).append("\n");
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
builder.append("rtl=").append(isRtl).append("\n");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
boolean notifPermGranted = PermissionChecker.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PermissionChecker.PERMISSION_GRANTED;

View file

@ -228,11 +228,9 @@ public class ProfileDocumentsFragment
mode.getMenuInflater().inflate(R.menu.profile_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));
}
setCorrectMenuVisibility(menu);
return true;
}
@ -282,9 +280,7 @@ public class ProfileDocumentsFragment
actionMode = null;
getListAdapter().clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
}
}
}

View file

@ -219,11 +219,9 @@ public class ProfileGalleryFragment
mode.getMenuInflater().inflate(R.menu.profile_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));
}
setCorrectMenuVisibility(menu);
return true;
}
@ -269,9 +267,7 @@ public class ProfileGalleryFragment
actionMode = null;
getListAdapter().clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
}
}
}

View file

@ -268,11 +268,9 @@ public class ProfileSettingsFragment extends Fragment
menu.findItem(R.id.menu_select_all).setVisible(false);
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));
}
return true;
}
@ -314,11 +312,9 @@ public class ProfileSettingsFragment extends Fragment
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
adapter.clearSelection();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

View file

@ -100,14 +100,10 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar) {
if (!Util.isClickedRecently()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Prefs.isDeveloperModeEnabled(context)) {
WebView.setWebContentsDebuggingEnabled(true);
}
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar));
} else {
Toast.makeText(context, "At least Android 5.0 (Lollipop) required for Webxdc.", Toast.LENGTH_LONG).show();
}
}
}
@ -329,7 +325,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
res = new WebResourceResponse("text/plain", "UTF-8", targetStream);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !internetAccess) {
if (!internetAccess) {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Security-Policy",
"default-src 'self'; "
@ -348,14 +344,12 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
}
private void callJavaScriptFunction(String func) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (internetAccess) {
webView.evaluateJavascript("window." + func + ";", null);
} else {
webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null);
}
}
}
@Override
public void handleEvent(@NonNull DcEvent event) {

View file

@ -176,7 +176,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_storage_denied))
.onAllGranted(() -> {
File imexDir = DcHelper.getImexDir();
if (Build.VERSION.SDK_INT >= 30) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
AttachmentManager.selectMediaType(this, "application/x-tar", null, PICK_BACKUP, StorageUtil.getDownloadUri());
} else {
final String backupFile = dcContext.imexHasBackup(imexDir.getAbsolutePath());

View file

@ -130,15 +130,10 @@ 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());
}
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
animateButtonIn(videoButton, ANIMATION_DURATION / 2);
animateButtonIn(imageButton, ANIMATION_DURATION / 3);
@ -148,15 +143,10 @@ public class AttachmentTypeSelector extends PopupWindow {
animateButtonIn(videoChatButton, 0);
animateButtonIn(closeButton, 0);
}
}
@Override
public void dismiss() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowOutCircular(currentAnchor, getContentView());
} else {
animateWindowOutTranslate(getContentView());
}
}
public void setListener(@Nullable AttachmentClickedListener listener) {
@ -186,7 +176,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,
@ -205,7 +194,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

@ -71,12 +71,10 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
this.pauseButton.setOnClickListener(new PauseClickedListener());
this.seekBar.setOnSeekBarChangeListener(new SeekBarModifiedListener());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
}
setTint(getContext().getResources().getColor(R.color.audio_icon));
}
@ -192,13 +190,8 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
}
public void setTint(int foregroundTint) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
} else {
this.playButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
this.pauseButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
}
this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
@ -220,25 +213,20 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
private void togglePlayToPause() {
controlToggle.displayQuick(pauseButton);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.play_to_pause_animation);
pauseButton.setImageDrawable(playToPauseDrawable);
playToPauseDrawable.start();
}
}
private void togglePauseToPlay() {
controlToggle.displayQuick(playButton);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.pause_to_play_animation);
playButton.setImageDrawable(pauseToPlayDrawable);
pauseToPlayDrawable.start();
}
}
private class PlayClickedListener implements View.OnClickListener {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
try {
@ -279,7 +267,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
}
private class PauseClickedListener implements View.OnClickListener {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onClick(View v) {
Log.w(TAG, "pausebutton onClick");

View file

@ -122,7 +122,6 @@ public class ComposeText extends AppCompatEditText {
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;

View file

@ -120,15 +120,10 @@ public class ConversationItemThumbnail extends FrameLayout {
@SuppressWarnings("SuspiciousNameCombination")
@Override
protected void dispatchDraw(Canvas canvas) {
if (cornerMask.isLegacy()) {
cornerMask.mask(canvas);
}
super.dispatchDraw(canvas);
if (!cornerMask.isLegacy()) {
cornerMask.mask(canvas);
}
final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2;

View file

@ -7,7 +7,7 @@ import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import androidx.annotation.NonNull;
import android.view.View;
@ -20,11 +20,7 @@ public class CornerMask {
private final RectF bounds = new RectF();
public CornerMask(@NonNull View view) {
if (isLegacy()) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} else {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
clearPaint.setColor(Color.BLACK);
clearPaint.setStyle(Paint.Style.FILL);
@ -44,19 +40,10 @@ public class CornerMask {
// Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does.
// So we find and inverse path and use Mode.CLEAR for versions that support Path.op().
// See issue https://issuetracker.google.com/issues/111394085.
if (!isLegacy()) {
outline.reset();
outline.addRect(bounds, Path.Direction.CW);
outline.op(corners, Path.Op.DIFFERENCE);
canvas.drawPath(outline, clearPaint);
} else {
corners.addRoundRect(bounds, radii, Path.Direction.CW);
canvas.clipPath(corners);
}
}
public boolean isLegacy() {
return Build.VERSION.SDK_INT < 19;
}
public void setRadius(int radius) {

View file

@ -104,7 +104,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
}
private void updateKeyboardState() {
if (viewInset == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) viewInset = getViewInset();
if (viewInset == 0) viewInset = getViewInset();
getWindowVisibleDisplayFrame(rect);
@ -148,7 +148,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private int getViewInset() {
try {
Field attachInfoField = View.class.getDeclaredField("mAttachInfo");
@ -219,11 +218,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
return Surface.ROTATION_0;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRotation();
}
if (Build.VERSION.SDK_INT >= 30) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
getContext().getDisplay().getRealMetrics(displayMetrics);
} else {
ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRealMetrics(displayMetrics);

View file

@ -40,7 +40,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();

View file

@ -78,7 +78,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
initialize(attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(attrs);

View file

@ -29,7 +29,6 @@ public class RepeatableImageKey extends ImageButton {
init();
}
@TargetApi(VERSION_CODES.LOLLIPOP)
public RepeatableImageKey(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes)
{

View file

@ -130,15 +130,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);
setVisibility(View.VISIBLE);
animator.start();
} else {
setVisibility(View.VISIBLE);
}
}
}
@ -153,7 +149,6 @@ 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() {
@ -163,9 +158,6 @@ public class SearchToolbar extends LinearLayout {
}
});
animator.start();
} else {
setVisibility(View.INVISIBLE);
}
}
}

View file

@ -18,7 +18,6 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
setLayoutRes();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutRes();

View file

@ -463,7 +463,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

@ -260,9 +260,7 @@ public class DcHelper {
}
public static File getImexDir() {
// DIRECTORY_DOCUMENTS is only available since KitKat;
// as we also support Ice Cream Sandwich and Jellybean (2017: 11% in total), this is no option.
// Moreover, DIRECTORY_DOWNLOADS seems to be easier accessible by the user,
// DIRECTORY_DOCUMENTS could be used but DIRECTORY_DOWNLOADS seems to be easier accessible by the user,
// eg. "Download Managers" are nearly always installed.
// CAVE: do not use DownloadManager to add the file as it is deleted on uninstall then ...
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

View file

@ -1,345 +0,0 @@
/*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will Google be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, as long as the origin is not misrepresented.
*/
package org.thoughtcrime.securesms.crypto;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import java.security.Security;
/**
* This class is taken directly from the Android blog post announcing this bug:
* http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html
*
* Since I still don't know exactly what the source of this bug was, I'm using
* this class verbatim under the assumption that the Android team knows what
* they're doing. Although, at this point, that is perhaps a foolish assumption.
*/
/**
* Fixes for the output of the default PRNG having low entropy.
*
* The fixes need to be applied via {@link #apply()} before any use of Java
* Cryptography Architecture primitives. A good place to invoke them is in the
* application's {@code onCreate}.
*/
public final class PRNGFixes {
private static final int VERSION_CODE_JELLY_BEAN = 16;
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
getBuildFingerprintAndDeviceSerial();
/** Hidden constructor to prevent instantiation. */
private PRNGFixes() {}
/**
* Applies all fixes.
*
* @throws SecurityException if a fix is needed but could not be applied.
*/
public static void apply() {
applyOpenSSLFix();
installLinuxPRNGSecureRandom();
}
/**
* Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the
* fix is not needed.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void applyOpenSSLFix() throws SecurityException {
if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN)
|| (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) {
// No need to apply the fix
return;
}
try {
// Mix in the device- and invocation-specific seed.
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, generateSeed());
// Mix output of Linux PRNG into OpenSSL's PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
if (bytesRead != 1024) {
throw new IOException(
"Unexpected number of bytes read from Linux PRNG: "
+ bytesRead);
}
} catch (Exception e) {
throw new SecurityException("Failed to seed OpenSSL PRNG", e);
}
}
/**
* Installs a Linux PRNG-backed {@code SecureRandom} implementation as the
* default. Does nothing if the implementation is already the default or if
* there is not need to install the implementation.
*
* @throws SecurityException if the fix is needed but could not be applied.
*/
private static void installLinuxPRNGSecureRandom()
throws SecurityException {
if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {
// No need to apply the fix
return;
}
// Install a Linux PRNG-based SecureRandom implementation as the
// default, if not yet installed.
Provider[] secureRandomProviders =
Security.getProviders("SecureRandom.SHA1PRNG");
if ((secureRandomProviders == null)
|| (secureRandomProviders.length < 1)
|| (!LinuxPRNGSecureRandomProvider.class.equals(
secureRandomProviders[0].getClass()))) {
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
}
// Assert that new SecureRandom() and
// SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed
// by the Linux PRNG-based SecureRandom implementation.
SecureRandom rng1 = new SecureRandom();
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng1.getProvider().getClass())) {
throw new SecurityException(
"new SecureRandom() backed by wrong Provider: "
+ rng1.getProvider().getClass());
}
SecureRandom rng2;
try {
rng2 = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException("SHA1PRNG not available", e);
}
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng2.getProvider().getClass())) {
throw new SecurityException(
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
+ " Provider: " + rng2.getProvider().getClass());
}
}
/**
* {@code Provider} of {@code SecureRandom} engines which pass through
* all requests to the Linux PRNG.
*/
private static class LinuxPRNGSecureRandomProvider extends Provider {
public LinuxPRNGSecureRandomProvider() {
super("LinuxPRNG",
1.0,
"A Linux-specific random number provider that uses"
+ " /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some apps
// explicitly request a SHA1PRNG SecureRandom and we thus need to
// prevent them from getting the default implementation whose output
// may have low entropy.
put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName());
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
}
/**
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG
* ({@code /dev/urandom}).
*/
public static class LinuxPRNGSecureRandom extends SecureRandomSpi {
/*
* IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed
* are passed through to the Linux PRNG (/dev/urandom). Instances of
* this class seed themselves by mixing in the current time, PID, UID,
* build fingerprint, and hardware serial number (where available) into
* Linux PRNG.
*
* Concurrency: Read requests to the underlying Linux PRNG are
* serialized (on sLock) to ensure that multiple threads do not get
* duplicated PRNG output.
*/
private static final File URANDOM_FILE = new File("/dev/urandom");
private static final Object sLock = new Object();
/**
* Input stream for reading from Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static DataInputStream sUrandomIn;
/**
* Output stream for writing to Linux PRNG or {@code null} if not yet
* opened.
*
* @GuardedBy("sLock")
*/
private static OutputStream sUrandomOut;
/**
* Whether this engine instance has been seeded. This is needed because
* each instance needs to seed itself if the client does not explicitly
* seed it.
*/
private boolean mSeeded;
@Override
protected void engineSetSeed(byte[] bytes) {
try {
OutputStream out;
synchronized (sLock) {
out = getUrandomOutputStream();
}
out.write(bytes);
out.flush();
} catch (IOException e) {
// On a small fraction of devices /dev/urandom is not writable.
// Log and ignore.
Log.w(PRNGFixes.class.getSimpleName(),
"Failed to mix seed into " + URANDOM_FILE);
} finally {
mSeeded = true;
}
}
@Override
protected void engineNextBytes(byte[] bytes) {
if (!mSeeded) {
// Mix in the device- and invocation-specific seed.
engineSetSeed(generateSeed());
}
try {
DataInputStream in;
synchronized (sLock) {
in = getUrandomInputStream();
}
synchronized (in) {
in.readFully(bytes);
}
} catch (IOException e) {
throw new SecurityException(
"Failed to read from " + URANDOM_FILE, e);
}
}
@Override
protected byte[] engineGenerateSeed(int size) {
byte[] seed = new byte[size];
engineNextBytes(seed);
return seed;
}
private DataInputStream getUrandomInputStream() {
synchronized (sLock) {
if (sUrandomIn == null) {
// NOTE: Consider inserting a BufferedInputStream between
// DataInputStream and FileInputStream if you need higher
// PRNG output performance and can live with future PRNG
// output being pulled into this process prematurely.
try {
sUrandomIn = new DataInputStream(
new FileInputStream(URANDOM_FILE));
} catch (IOException e) {
throw new SecurityException("Failed to open "
+ URANDOM_FILE + " for reading", e);
}
}
return sUrandomIn;
}
}
private OutputStream getUrandomOutputStream() throws IOException {
synchronized (sLock) {
if (sUrandomOut == null) {
sUrandomOut = new FileOutputStream(URANDOM_FILE);
}
return sUrandomOut;
}
}
}
/**
* Generates a device- and invocation-specific seed to be mixed into the
* Linux PRNG.
*/
private static byte[] generateSeed() {
try {
ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
DataOutputStream seedBufferOut =
new DataOutputStream(seedBuffer);
seedBufferOut.writeLong(System.currentTimeMillis());
seedBufferOut.writeLong(System.nanoTime());
seedBufferOut.writeInt(Process.myPid());
seedBufferOut.writeInt(Process.myUid());
seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL);
seedBufferOut.close();
return seedBuffer.toByteArray();
} catch (IOException e) {
throw new SecurityException("Failed to generate seed", e);
}
}
/**
* Gets the hardware serial number of this device.
*
* @return serial number or {@code null} if not available.
*/
private static String getDeviceSerialNumber() {
// We're using the Reflection API because Build.SERIAL is only available
// since API Level 9 (Gingerbread, Android 2.3).
try {
return (String) Build.class.getField("SERIAL").get(null);
} catch (Exception ignored) {
return null;
}
}
private static byte[] getBuildFingerprintAndDeviceSerial() {
StringBuilder result = new StringBuilder();
String fingerprint = Build.FINGERPRINT;
if (fingerprint != null) {
result.append(fingerprint);
}
String serial = getDeviceSerialNumber();
if (serial != null) {
result.append(serial);
}
try {
return result.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 encoding not supported");
}
}
}

View file

@ -585,7 +585,7 @@ public class AttachmentManager {
final Intent intent = new Intent();
intent.setType(type);
if (extraMimeType != null && Build.VERSION.SDK_INT >= 19) {
if (extraMimeType != null) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeType);
}
@ -597,7 +597,6 @@ public class AttachmentManager {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
try {
activity.startActivityForResult(intent, requestCode);
@ -605,7 +604,6 @@ public class AttachmentManager {
} catch (ActivityNotFoundException anfe) {
Log.w(TAG, "couldn't complete ACTION_OPEN_DOCUMENT, no activity found. falling back.");
}
}
intent.setAction(Intent.ACTION_GET_CONTENT);

View file

@ -187,9 +187,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
Preference developerModeEnabled = this.findPreference("pref_developer_mode_enabled");
developerModeEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WebView.setWebContentsDebuggingEnabled((Boolean) newValue);
}
return true;
});

View file

@ -26,7 +26,6 @@ public class ProfilePreference extends Preference {
private TextView profileNameView;
private TextView profileAddressView;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ProfilePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();

View file

@ -63,15 +63,10 @@ public class AvatarHelper {
}
public static void cropAvatar(Activity context, Uri imageUri) {
if (Build.VERSION.SDK_INT >= 19) { // Image editor requires Android 4.4 KitKat or newer.
Intent intent = new Intent(context, ScribbleActivity.class);
intent.setData(imageUri);
intent.putExtra(ScribbleActivity.CROP_AVATAR, true);
context.startActivityForResult(intent, ScribbleActivity.SCRIBBLE_REQUEST_CODE);
} else {
Uri outputFile = Uri.fromFile(new File(context.getCacheDir(), "cropped"));
Crop.of(imageUri, outputFile).asSquare().start(context);
}
}
}

View file

@ -59,9 +59,6 @@ public class AddReactionView extends LinearLayout {
}
anyReactionView = findViewById(R.id.reaction_any);
anyReactionView.setOnClickListener(v -> anyReactionClicked());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
anyReactionView.setVisibility(View.GONE); // EmojiPickerView requires SDK 21 or newer
}
}
}

View file

@ -96,11 +96,7 @@ public final class ImageEditorHud extends LinearLayout {
}
private void initializeVisibilityMap() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, blurButton, textButton, stickerButton, cropButton, undoButton, saveButton);
} else {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, stickerButton, cropButton, undoButton, saveButton);
}
setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette);

View file

@ -117,16 +117,13 @@ final class UriGlideRenderer implements Renderer {
rendererContext.restore();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
renderBlurOverlay(rendererContext);
}
} else if (rendererContext.isBlockingLoad()) {
// If failed to load, we draw a black out, in case image was sticker positioned to cover private info.
rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint);
}
}
@RequiresApi(17)
private void renderBlurOverlay(RendererContext rendererContext) {
boolean renderMask = false;

View file

@ -98,7 +98,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();

View file

@ -15,10 +15,6 @@ public final class AccessibilityUtil {
Log.e("AccessibilityUtil", "animationsDisabled: context was null");
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1) == 0f;
} else {
return false;
}
}
}

View file

@ -110,11 +110,7 @@ public class DateUtils extends android.text.format.DateUtils {
}
private static String getLocalizedPattern(String template) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
return DateFormat.getBestDateTimePattern(Util.getLocale(), template);
} else {
return new SimpleDateFormat(template, Util.getLocale()).toLocalizedPattern();
}
}
public static String getFormatedDuration(long millis) {

View file

@ -16,8 +16,7 @@ public class FileProviderUtil {
private static final String AUTHORITY = BuildConfig.APPLICATION_ID+".fileprovider";
public static Uri getUriFor(@NonNull Context context, @NonNull File file) throws IllegalStateException, NullPointerException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return FileProvider.getUriForFile(context, AUTHORITY, file);
else return Uri.fromFile(file);
return FileProvider.getUriForFile(context, AUTHORITY, file);
}
}

View file

@ -12,7 +12,7 @@ public class ScreenLockUtil {
public static boolean applyScreenLock(Activity activity, String title, String descr, int requestCode) {
KeyguardManager keyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
Intent intent;
if (keyguardManager != null && isScreenLockAvailable()) {
if (keyguardManager != null) {
intent = keyguardManager.createConfirmDeviceCredentialIntent(title, descr);
if (intent != null) {
activity.startActivityForResult(intent, requestCode);
@ -22,7 +22,4 @@ public class ScreenLockUtil {
return false;
}
private static boolean isScreenLockAvailable() {
return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP;
}
}

View file

@ -20,29 +20,17 @@ public class StorageUtil {
}
public static @NonNull Uri getVideoUri() {
if (Build.VERSION.SDK_INT < 21) {
return getLegacyUri(Environment.DIRECTORY_MOVIES);
} else {
return MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
}
public static @NonNull
Uri getAudioUri() {
if (Build.VERSION.SDK_INT < 21) {
return getLegacyUri(Environment.DIRECTORY_MUSIC);
} else {
return MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
}
public static @NonNull Uri getImageUri() {
if (Build.VERSION.SDK_INT < 21) {
return getLegacyUri(Environment.DIRECTORY_PICTURES);
} else {
return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
}
public static @NonNull Uri getDownloadUri() {
if (Build.VERSION.SDK_INT < 29) {

View file

@ -257,12 +257,10 @@ public class Util {
return Arrays.hashCode(objects);
}
@TargetApi(VERSION_CODES.KITKAT)
public static boolean isLowMemory(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
return (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) ||
activityManager.getLargeMemoryClass() <= 64;
return activityManager.isLowRamDevice() || activityManager.getLargeMemoryClass() <= 64;
}
public static int clamp(int value, int min, int max) {
@ -386,10 +384,7 @@ public class Util {
}
public static int getLayoutDirection(Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
Configuration configuration = context.getResources().getConfiguration();
return configuration.getLayoutDirection();
}
return ViewCompat.LAYOUT_DIRECTION_LTR;
}
}

View file

@ -168,18 +168,15 @@ public class ViewUtil {
@SuppressLint("RtlHardcoded")
public static void setTextViewGravityStart(final @NonNull TextView textView, @NonNull Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
textView.setGravity(Gravity.RIGHT);
} else {
textView.setGravity(Gravity.LEFT);
}
}
}
public static void mirrorIfRtl(View view, Context context) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1 &&
Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
if (Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL) {
view.setScaleX(-1.0f);
}
}

View file

@ -1,14 +1,10 @@
package org.thoughtcrime.securesms.video.recode;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Build;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
@ -36,14 +32,7 @@ public class VideoRecoder {
private static final String TAG = VideoRecoder.class.getSimpleName();
private boolean videoConvertFirstWrite = true;
private final static String MIME_TYPE = "video/avc";
private final static int PROCESSOR_TYPE_OTHER = 0;
private final static int PROCESSOR_TYPE_QCOM = 1;
private final static int PROCESSOR_TYPE_INTEL = 2;
private final static int PROCESSOR_TYPE_MTK = 3;
private final static int PROCESSOR_TYPE_SEC = 4;
private final static int PROCESSOR_TYPE_TI = 5;
private final boolean cancelCurrentVideoConversion = false;
private final Object videoConvertSync = new Object();
@ -57,7 +46,6 @@ public class VideoRecoder {
}
}
@TargetApi(16)
private int selectTrack(MediaExtractor extractor, boolean audio) {
int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; i++) {
@ -76,60 +64,6 @@ public class VideoRecoder {
return -5;
}
@SuppressLint("NewApi")
private static MediaCodecInfo selectCodec(String mimeType) {
int numCodecs = MediaCodecList.getCodecCount();
MediaCodecInfo lastCodecInfo = null;
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (String type : types) {
if (type.equalsIgnoreCase(mimeType)) {
lastCodecInfo = codecInfo;
if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
return lastCodecInfo;
} else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
return lastCodecInfo;
}
}
}
}
return lastCodecInfo;
}
private static boolean isRecognizedFormat(int colorFormat) {
switch (colorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
return true;
default:
return false;
}
}
@SuppressLint("NewApi")
private static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
int lastColorFormat = 0;
for (int i = 0; i < capabilities.colorFormats.length; i++) {
int colorFormat = capabilities.colorFormats[i];
if (isRecognizedFormat(colorFormat)) {
lastColorFormat = colorFormat;
if (!(codecInfo.getName().equals("OMX.SEC.AVC.Encoder") && colorFormat == 19)) {
return colorFormat;
}
}
}
return lastColorFormat;
}
@TargetApi(16)
private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception {
int trackIndex = selectTrack(extractor, isAudio);
if (trackIndex >= 0) {
@ -199,7 +133,6 @@ public class VideoRecoder {
return -1;
}
@TargetApi(16)
private boolean convertVideo(final VideoEditedInfo videoEditedInfo, String destPath) {
long startTime = videoEditedInfo.startTime;
@ -214,13 +147,6 @@ public class VideoRecoder {
int rotateRender = 0;
File cacheFile = new File(destPath);
if (Build.VERSION.SDK_INT < 18 && resultHeight > resultWidth && resultWidth != originalWidth && resultHeight != originalHeight) {
int temp = resultHeight;
resultHeight = resultWidth;
resultWidth = temp;
rotationValue = 90;
rotateRender = 270;
} else if (Build.VERSION.SDK_INT > 20) {
if (rotationValue == 90) {
int temp = resultHeight;
resultHeight = resultWidth;
@ -237,7 +163,6 @@ public class VideoRecoder {
rotationValue = 0;
rotateRender = 90;
}
}
File inputFile = new File(videoEditedInfo.originalPath);
if (!inputFile.canRead()) {
@ -246,7 +171,6 @@ public class VideoRecoder {
return false;
}
videoConvertFirstWrite = true;
boolean error = false;
long videoStartTime = startTime;
@ -282,71 +206,12 @@ public class VideoRecoder {
boolean outputDone = false;
boolean inputDone = false;
boolean decoderDone = false;
int swapUV = 0;
int videoTrackIndex = -5;
int colorFormat;
int processorType = PROCESSOR_TYPE_OTHER;
String manufacturer = Build.MANUFACTURER.toLowerCase();
if (Build.VERSION.SDK_INT < 18) {
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
if (colorFormat == 0) {
throw new RuntimeException("no supported color format");
}
String codecName = codecInfo.getName();
if (codecName.contains("OMX.qcom.")) {
processorType = PROCESSOR_TYPE_QCOM;
if (Build.VERSION.SDK_INT == 16) {
if (manufacturer.equals("lge") || manufacturer.equals("nokia")) {
swapUV = 1;
}
}
} else if (codecName.contains("OMX.Intel.")) {
processorType = PROCESSOR_TYPE_INTEL;
} else if (codecName.equals("OMX.MTK.VIDEO.ENCODER.AVC")) {
processorType = PROCESSOR_TYPE_MTK;
} else if (codecName.equals("OMX.SEC.AVC.Encoder")) {
processorType = PROCESSOR_TYPE_SEC;
swapUV = 1;
} else if (codecName.equals("OMX.TI.DUCATI1.VIDEO.H264E")) {
processorType = PROCESSOR_TYPE_TI;
}
//Log.i("DeltaChat", "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer + "device = " + Build.MODEL);
} else {
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
}
//Log.i("DeltaChat", "colorFormat = " + colorFormat);
int resultHeightAligned = resultHeight;
int padding = 0;
int bufferSize = resultWidth * resultHeight * 3 / 2;
if (processorType == PROCESSOR_TYPE_OTHER) {
if (resultHeight % 16 != 0) {
resultHeightAligned += (16 - (resultHeight % 16));
padding = resultWidth * (resultHeightAligned - resultHeight);
bufferSize += padding * 5 / 4;
}
} else if (processorType == PROCESSOR_TYPE_QCOM) {
if (!manufacturer.toLowerCase().equals("lge")) {
int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
padding = uvoffset - (resultWidth * resultHeight);
bufferSize += padding;
}
} else if (processorType == PROCESSOR_TYPE_TI) {
//resultHeightAligned = 368;
//bufferSize = resultWidth * resultHeightAligned * 3 / 2;
//resultHeightAligned += (16 - (resultHeight % 16));
//padding = resultWidth * (resultHeightAligned - resultHeight);
//bufferSize += padding * 5 / 4;
} else if (processorType == PROCESSOR_TYPE_MTK) {
if (manufacturer.equals("baidu")) {
resultHeightAligned += (16 - (resultHeight % 16));
padding = resultWidth * (resultHeightAligned - resultHeight);
bufferSize += padding * 5 / 4;
}
}
extractor.selectTrack(videoIndex);
if (startTime > 0) {
extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
@ -360,39 +225,21 @@ public class VideoRecoder {
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, resultVideoBitrate != 0 ? resultVideoBitrate : 921600);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
if (Build.VERSION.SDK_INT < 18) {
outputFormat.setInteger("stride", resultWidth + 32);
outputFormat.setInteger("slice-height", resultHeight);
}
encoder = MediaCodec.createEncoderByType(MIME_TYPE);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
if (Build.VERSION.SDK_INT >= 18) {
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
}
encoder.start();
decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
if (Build.VERSION.SDK_INT >= 18) {
outputSurface = new OutputSurface();
} else {
outputSurface = new OutputSurface(resultWidth, resultHeight, rotateRender);
}
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
decoder.start();
final int TIMEOUT_USEC = 2500;
ByteBuffer[] decoderInputBuffers = null;
ByteBuffer[] encoderOutputBuffers = null;
ByteBuffer[] encoderInputBuffers = null;
if (Build.VERSION.SDK_INT < 21) {
decoderInputBuffers = decoder.getInputBuffers();
encoderOutputBuffers = encoder.getOutputBuffers();
if (Build.VERSION.SDK_INT < 18) {
encoderInputBuffers = encoder.getInputBuffers();
}
}
checkConversionCanceled();
@ -405,11 +252,7 @@ public class VideoRecoder {
int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
ByteBuffer inputBuf;
if (Build.VERSION.SDK_INT < 21) {
inputBuf = decoderInputBuffers[inputBufIndex];
} else {
inputBuf = decoder.getInputBuffer(inputBufIndex);
}
int chunkSize = extractor.readSampleData(inputBuf, 0);
if (chunkSize < 0) {
decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
@ -439,9 +282,6 @@ public class VideoRecoder {
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
encoderOutputAvailable = false;
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
if (Build.VERSION.SDK_INT < 21) {
encoderOutputBuffers = encoder.getOutputBuffers();
}
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = encoder.getOutputFormat();
if (videoTrackIndex == -5) {
@ -451,11 +291,7 @@ public class VideoRecoder {
throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
} else {
ByteBuffer encodedData;
if (Build.VERSION.SDK_INT < 21) {
encodedData = encoderOutputBuffers[encoderStatus];
} else {
encodedData = encoder.getOutputBuffer(encoderStatus);
}
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
}
@ -513,11 +349,7 @@ public class VideoRecoder {
throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else {
boolean doRender;
if (Build.VERSION.SDK_INT >= 18) {
doRender = info.size != 0;
} else {
doRender = info.size != 0 || info.presentationTimeUs != 0;
}
if (endTime > 0 && info.presentationTimeUs >= endTime) {
inputDone = true;
decoderDone = true;
@ -542,40 +374,15 @@ public class VideoRecoder {
Log.w(TAG, "error while waiting for recording output surface", e);
}
if (!errorWait) {
if (Build.VERSION.SDK_INT >= 18) {
outputSurface.drawImage(false);
inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
inputSurface.swapBuffers();
} else {
Log.w(TAG, "Cannot proceed with the current SDK version");
return false; // TODO: this should be caught much earlier
/*
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
outputSurface.drawImage(true);
ByteBuffer rgbBuf = outputSurface.getFrame();
ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex];
yuvBuf.clear();
Utilities.convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV);
encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
} else {
//Log.i("DeltaChat", "input buffer not available");
}
*/
}
}
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
decoderOutputAvailable = false;
//Log.i("DeltaChat", "decoder stream end");
if (Build.VERSION.SDK_INT >= 18) {
encoder.signalEndOfInputStream();
} else {
int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
if (inputBufIndex >= 0) {
encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
}
}
}
@ -662,45 +469,6 @@ public class VideoRecoder {
int estimatedBytes;
}
public static boolean canRecode()
{
boolean canRecode = true;
if (Build.VERSION.SDK_INT < 16 /*= Jelly Bean 4.1 (before that codecInfo.getName() was not there) */) {
Log.w(TAG, "Cannot recode: API < 16");
canRecode = false;
}
else if (Build.VERSION.SDK_INT < 18 /*= Jelly Bean 4.3*/) {
try {
MediaCodecInfo codecInfo = VideoRecoder.selectCodec(VideoRecoder.MIME_TYPE);
if (codecInfo == null) {
Log.w(TAG, "Cannot recode: cannot select codec");
canRecode = false;
} else {
String name = codecInfo.getName();
if (name.equals("OMX.google.h264.encoder") ||
name.equals("OMX.ST.VFM.H264Enc") ||
name.equals("OMX.Exynos.avc.enc") ||
name.equals("OMX.MARVELL.VIDEO.HW.CODA7542ENCODER") ||
name.equals("OMX.MARVELL.VIDEO.H264ENCODER") ||
name.equals("OMX.k3.video.encoder.avc") ||
name.equals("OMX.TI.DUCATI1.VIDEO.H264E")) {
Log.w(TAG, "Cannot recode: no supported codec found");
canRecode = false;
} else {
if (VideoRecoder.selectColorFormat(codecInfo, VideoRecoder.MIME_TYPE) == 0) {
Log.w(TAG, "Cannot recode: cannot select color format");
canRecode = false;
}
}
}
} catch (Exception e) {
Log.w(TAG, "Cannot recode: Determinating recoding capabilities failed unexpectedly", e);
canRecode = false;
}
}
return canRecode;
}
private static VideoEditedInfo getVideoEditInfoFromFile(String videoPath) {
// load information for the given video
VideoEditedInfo vei = new VideoEditedInfo();
@ -811,11 +579,6 @@ public class VideoRecoder {
}
msg.setDuration((int)vei.originalDurationMs);
if (!canRecode()) {
alert(context, String.format("Recoding failed for %s: this system cannot recode videos", inPath));
return false;
}
// check if video bitrate is already reasonable
final int MAX_KBPS = 1500000;
final long MAX_BYTES = DcHelper.getInt(context, "sys.msgsize_max_recommended");

View file

Before

Width:  |  Height:  |  Size: 1,002 B

After

Width:  |  Height:  |  Size: 1,002 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 750 B

View file

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

Before After
Before After

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@color/black" />
</shape>
</item>
</ripple>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
</selector>
</item>
</ripple>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg" />
</selector>
</item>
</ripple>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/pinned_bg_dark" />
</selector>
</item>
</ripple>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item
android:id="@android:id/mask"
android:drawable="@android:color/white" />
</ripple>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Like touch_highlight_background, but creates a stronger (i.e. better visible)
visual feedback when the button is pressed. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/white" />
<item>
<selector>
<item android:drawable="@color/touch_highlight_strong" android:state_pressed="true" />
</selector>
</item>
</ripple>

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

View file

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@color/touch_highlight" />
<solid android:color="@color/black" />
</shape>
</item>
</selector>
</ripple>

View file

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" />
</selector>
</item>
</ripple>

View file

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" />
</selector>
</item>
</ripple>

View file

@ -2,7 +2,7 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/pause_icon"
tools:targetApi="lollipop">
>
<target
android:name="@string/play_icon_group_parts"

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" />
<item android:drawable="@color/pinned_bg" />
</selector>
</item>
</ripple>

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/black" />
<item>
<selector>
<item android:drawable="@color/primary_alpha33" android:state_selected="true" />
<item android:drawable="@color/primary_alpha33" android:state_pressed="true" />
<item android:drawable="@color/primary_alpha_focus" android:state_focused="true" />
<item android:drawable="@color/pinned_bg_dark" />
</selector>
</item>
</ripple>

View file

@ -2,7 +2,7 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:drawable="@drawable/play_icon"
tools:targetApi="lollipop">
>
<target
android:name="@string/play_icon_group_parts"

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/touch_highlight" />
<item android:state_focused="true" android:drawable="@color/delta_primary" />
<item android:drawable="@android:color/transparent" />
</selector>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/touch_highlight">
<item
android:id="@android:id/mask"
android:drawable="@android:color/white" />
</ripple>

View file

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/touch_highlight_strong" />
<item android:state_focused="true" android:drawable="@color/delta_primary" />
<item android:drawable="@android:color/transparent" />
<!-- Like touch_highlight_background, but creates a stronger (i.e. better visible)
visual feedback when the button is pressed. -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/delta_primary">
<item android:id="@android:id/mask" android:drawable="@android:color/white" />
<item>
<selector>
<item android:drawable="@color/touch_highlight_strong" android:state_pressed="true" />
</selector>
</item>
</ripple>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="touch_highlight">#22000000</color>
</resources>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>

View file

@ -36,7 +36,7 @@
<color name="conversation_compose_divider">#32000000</color>
<color name="action_mode_status_bar">@color/gray50</color>
<color name="touch_highlight">#400099cc</color>
<color name="touch_highlight">#22000000</color>
<color name="touch_highlight_strong">#5C4CB8DB</color>
<color name="sticker_selected_color">#99ffffff</color>

View file

@ -256,6 +256,8 @@
</style>
<style name="TextSecure.ScribbleTheme" parent="TextSecure.DarkNoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>