Messaging: Meet Play memory/R8 rules, ship Q icon, and polish home chrome
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -41,6 +41,7 @@ android {
|
|||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
|
shrinkResources true
|
||||||
signingConfig signingConfigs.release
|
signingConfig signingConfigs.release
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
|
||||||
rootProject.file('proguard-release.flags'),
|
rootProject.file('proguard-release.flags'),
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:appCategory="social"
|
android:appCategory="social"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:localeConfig="@xml/locales_config"
|
android:localeConfig="@xml/locales_config"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
|
|||||||
@@ -128,6 +128,18 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
|||||||
Trace.endSection();
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrimMemory(final int level) {
|
||||||
|
super.onTrimMemory(level);
|
||||||
|
if (level < TRIM_MEMORY_UI_HIDDEN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||||
|
LogUtil.d(TAG, "BugleApplication.onTrimMemory " + level);
|
||||||
|
}
|
||||||
|
reclaimCachedBitmaps();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLowMemory() {
|
public void onLowMemory() {
|
||||||
super.onLowMemory();
|
super.onLowMemory();
|
||||||
@@ -135,7 +147,14 @@ public class BugleApplication extends Application implements UncaughtExceptionHa
|
|||||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||||
LogUtil.d(TAG, "BugleApplication.onLowMemory");
|
LogUtil.d(TAG, "BugleApplication.onLowMemory");
|
||||||
}
|
}
|
||||||
Factory.get().reclaimMemory();
|
reclaimCachedBitmaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void reclaimCachedBitmaps() {
|
||||||
|
final Factory factory = Factory.get();
|
||||||
|
if (factory != null) {
|
||||||
|
factory.reclaimMemory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -211,7 +211,16 @@ public class DecodedImageResource extends ImageResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
byte[] encodedBytes = ImageUtils.bitmapToBytes(bitmap, COMPRESS_QUALITY);
|
byte[] encodedBytes = ImageUtils.bitmapToBytes(bitmap, COMPRESS_QUALITY);
|
||||||
return new EncodedImageResource(getKey(), encodedBytes, getOrientation());
|
int desiredWidth = ImageRequest.UNSPECIFIED_SIZE;
|
||||||
|
int desiredHeight = ImageRequest.UNSPECIFIED_SIZE;
|
||||||
|
if (mOriginalImageRequest instanceof ImageRequest<?>) {
|
||||||
|
final ImageRequestDescriptor descriptor =
|
||||||
|
((ImageRequest<?>) mOriginalImageRequest).getDescriptor();
|
||||||
|
desiredWidth = descriptor.desiredWidth;
|
||||||
|
desiredHeight = descriptor.desiredHeight;
|
||||||
|
}
|
||||||
|
return new EncodedImageResource(getKey(), encodedBytes, getOrientation(),
|
||||||
|
desiredWidth, desiredHeight);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// Something went wrong during bitmap compression, fall back to just using the
|
// Something went wrong during bitmap compression, fall back to just using the
|
||||||
// original bitmap.
|
// original bitmap.
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ package com.android.messaging.datamodel.media;
|
|||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import com.android.messaging.util.Assert;
|
import com.android.messaging.util.Assert;
|
||||||
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
import com.android.messaging.util.Assert.DoesNotRunOnMainThread;
|
||||||
|
import com.android.messaging.util.ImageUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,10 +41,20 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class EncodedImageResource extends ImageResource {
|
public class EncodedImageResource extends ImageResource {
|
||||||
private final byte[] mImageBytes;
|
private final byte[] mImageBytes;
|
||||||
|
private final int mDesiredWidth;
|
||||||
|
private final int mDesiredHeight;
|
||||||
|
|
||||||
public EncodedImageResource(String key, byte[] imageBytes, int orientation) {
|
public EncodedImageResource(String key, byte[] imageBytes, int orientation) {
|
||||||
|
this(key, imageBytes, orientation, ImageRequest.UNSPECIFIED_SIZE,
|
||||||
|
ImageRequest.UNSPECIFIED_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodedImageResource(String key, byte[] imageBytes, int orientation,
|
||||||
|
final int desiredWidth, final int desiredHeight) {
|
||||||
super(key, orientation);
|
super(key, orientation);
|
||||||
mImageBytes = imageBytes;
|
mImageBytes = imageBytes;
|
||||||
|
mDesiredWidth = desiredWidth;
|
||||||
|
mDesiredHeight = desiredHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,7 +64,7 @@ public class EncodedImageResource extends ImageResource {
|
|||||||
try {
|
try {
|
||||||
// This should only be called during the decode request.
|
// This should only be called during the decode request.
|
||||||
Assert.isNotMainThread();
|
Assert.isNotMainThread();
|
||||||
return BitmapFactory.decodeByteArray(mImageBytes, 0, mImageBytes.length);
|
return decodeSampledBitmap();
|
||||||
} finally {
|
} finally {
|
||||||
releaseLock();
|
releaseLock();
|
||||||
}
|
}
|
||||||
@@ -99,11 +109,15 @@ public class EncodedImageResource extends ImageResource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Bitmap decodeSampledBitmap() {
|
||||||
|
return ImageUtils.decodeByteArraySampled(mImageBytes, mDesiredWidth, mDesiredHeight);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
MediaRequest<? extends RefCountedMediaResource> getMediaDecodingRequest(
|
MediaRequest<? extends RefCountedMediaResource> getMediaDecodingRequest(
|
||||||
final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
|
final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
|
||||||
Assert.isTrue(isEncoded());
|
Assert.isTrue(isEncoded());
|
||||||
return new DecodeImageRequest();
|
return new DecodeImageRequest(originalRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +126,22 @@ public class EncodedImageResource extends ImageResource {
|
|||||||
* properties such as binding.
|
* properties such as binding.
|
||||||
*/
|
*/
|
||||||
private class DecodeImageRequest implements MediaRequest<ImageResource> {
|
private class DecodeImageRequest implements MediaRequest<ImageResource> {
|
||||||
public DecodeImageRequest() {
|
private final int mRequestDesiredWidth;
|
||||||
|
private final int mRequestDesiredHeight;
|
||||||
|
|
||||||
|
public DecodeImageRequest(
|
||||||
|
final MediaRequest<? extends RefCountedMediaResource> originalRequest) {
|
||||||
|
int desiredWidth = mDesiredWidth;
|
||||||
|
int desiredHeight = mDesiredHeight;
|
||||||
|
if (originalRequest != null) {
|
||||||
|
final MediaRequestDescriptor<?> descriptor = originalRequest.getDescriptor();
|
||||||
|
if (descriptor instanceof ImageRequestDescriptor) {
|
||||||
|
desiredWidth = ((ImageRequestDescriptor) descriptor).desiredWidth;
|
||||||
|
desiredHeight = ((ImageRequestDescriptor) descriptor).desiredHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRequestDesiredWidth = desiredWidth;
|
||||||
|
mRequestDesiredHeight = desiredHeight;
|
||||||
// Hold a ref onto the encoded resource before the request finishes.
|
// Hold a ref onto the encoded resource before the request finishes.
|
||||||
addRef();
|
addRef();
|
||||||
}
|
}
|
||||||
@@ -129,8 +158,11 @@ public class EncodedImageResource extends ImageResource {
|
|||||||
Assert.isNotMainThread();
|
Assert.isNotMainThread();
|
||||||
acquireLock();
|
acquireLock();
|
||||||
try {
|
try {
|
||||||
final Bitmap decodedBitmap = BitmapFactory.decodeByteArray(mImageBytes, 0,
|
final Bitmap decodedBitmap = ImageUtils.decodeByteArraySampled(mImageBytes,
|
||||||
mImageBytes.length);
|
mRequestDesiredWidth, mRequestDesiredHeight);
|
||||||
|
if (decodedBitmap == null) {
|
||||||
|
throw new RuntimeException("failed decoding encoded bitmap");
|
||||||
|
}
|
||||||
return new DecodedImageResource(getKey(), decodedBitmap, getOrientation());
|
return new DecodedImageResource(getKey(), decodedBitmap, getOrientation());
|
||||||
} finally {
|
} finally {
|
||||||
releaseLock();
|
releaseLock();
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ package com.android.messaging.datamodel.media;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.support.v7.mms.pdu.ContentType;
|
import android.support.v7.mms.pdu.ContentType;
|
||||||
|
|
||||||
import com.android.messaging.Factory;
|
import com.android.messaging.Factory;
|
||||||
import com.android.messaging.util.Assert;
|
import com.android.messaging.util.Assert;
|
||||||
|
import com.android.messaging.util.ImageUtils;
|
||||||
import com.android.messaging.util.LogUtil;
|
import com.android.messaging.util.LogUtil;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -91,7 +91,11 @@ public class NetworkUriImageRequest<D extends UriImageRequestDescriptor> extends
|
|||||||
connection.setDoInput(true);
|
connection.setDoInput(true);
|
||||||
connection.connect();
|
connection.connect();
|
||||||
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||||
bitmap = BitmapFactory.decodeStream(connection.getInputStream());
|
try (InputStream inputStream = connection.getInputStream()) {
|
||||||
|
final byte[] bytes = ImageUtils.readStreamToByteArray(inputStream);
|
||||||
|
bitmap = ImageUtils.decodeByteArraySampled(bytes,
|
||||||
|
mDescriptor.desiredWidth, mDescriptor.desiredHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
LogUtil.e(LogUtil.BUGLE_TAG,
|
LogUtil.e(LogUtil.BUGLE_TAG,
|
||||||
|
|||||||
+2
@@ -19,6 +19,7 @@ package com.android.messaging.ui.conversationlist;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
|
import android.window.SplashScreenView;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -34,6 +35,7 @@ public class ConversationListActivity extends AbstractConversationListActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
Trace.beginSection("ConversationListActivity.onCreate");
|
Trace.beginSection("ConversationListActivity.onCreate");
|
||||||
|
getSplashScreen().setOnExitAnimationListener(SplashScreenView::remove);
|
||||||
setTheme(R.style.BugleTheme_ConversationListActivity);
|
setTheme(R.style.BugleTheme_ConversationListActivity);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mConversationListFragment = ConversationListFragment.createConversationListFragment(null);
|
mConversationListFragment = ConversationListFragment.createConversationListFragment(null);
|
||||||
|
|||||||
+40
-2
@@ -20,10 +20,12 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.v7.mms.pdu.ContentType;
|
import android.support.v7.mms.pdu.ContentType;
|
||||||
|
import android.text.Layout;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
@@ -221,6 +223,9 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
|
|||||||
mListDividerView = findViewById(R.id.conversation_list_divider);
|
mListDividerView = findViewById(R.id.conversation_list_divider);
|
||||||
mConversationNameView.addOnLayoutChangeListener(this);
|
mConversationNameView.addOnLayoutChangeListener(this);
|
||||||
mSnippetTextView.addOnLayoutChangeListener(this);
|
mSnippetTextView.addOnLayoutChangeListener(this);
|
||||||
|
if (mCategoryChipView != null) {
|
||||||
|
mCategoryChipView.addOnLayoutChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
final Resources resources = getContext().getResources();
|
final Resources resources = getContext().getResources();
|
||||||
final Resources.Theme theme = getContext().getTheme();
|
final Resources.Theme theme = getContext().getTheme();
|
||||||
@@ -243,6 +248,8 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
|
|||||||
setSnippet();
|
setSnippet();
|
||||||
} else if (v == mSubjectTextView) {
|
} else if (v == mSubjectTextView) {
|
||||||
setSubject();
|
setSubject();
|
||||||
|
} else if (v == mCategoryChipView) {
|
||||||
|
alignSimBadgeToFirstSnippetLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,10 +265,12 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
|
|||||||
if (!SimNameUtil.shouldShowSimName(getContext())) {
|
if (!SimNameUtil.shouldShowSimName(getContext())) {
|
||||||
mCategoryChipView.setText(null);
|
mCategoryChipView.setText(null);
|
||||||
mCategoryChipView.setVisibility(GONE);
|
mCategoryChipView.setVisibility(GONE);
|
||||||
|
mCategoryChipView.setTranslationY(0f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCategoryChipView.setText(SimNameUtil.getSimDisplayName(getContext(), mData.getSelfId()));
|
mCategoryChipView.setText(SimNameUtil.getSimDisplayName(getContext(), mData.getSelfId()));
|
||||||
mCategoryChipView.setVisibility(VISIBLE);
|
mCategoryChipView.setVisibility(VISIBLE);
|
||||||
|
alignSimBadgeToFirstSnippetLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setConversationName() {
|
private void setConversationName() {
|
||||||
@@ -344,13 +353,42 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
|
|||||||
final int indent = getSnippetChipIndent();
|
final int indent = getSnippetChipIndent();
|
||||||
if (indent <= 0) {
|
if (indent <= 0) {
|
||||||
mSnippetTextView.setText(snippetText);
|
mSnippetTextView.setText(snippetText);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
final SpannableString spanned = new SpannableString(snippetText == null ? "" : snippetText);
|
final SpannableString spanned = new SpannableString(snippetText == null ? "" : snippetText);
|
||||||
spanned.setSpan(new LeadingMarginSpan.Standard(indent, 0),
|
spanned.setSpan(new LeadingMarginSpan.Standard(indent, 0),
|
||||||
0, spanned.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
0, spanned.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
mSnippetTextView.setText(spanned);
|
mSnippetTextView.setText(spanned);
|
||||||
}
|
}
|
||||||
|
alignSimBadgeToFirstSnippetLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void alignSimBadgeToFirstSnippetLine() {
|
||||||
|
if (mCategoryChipView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mCategoryChipView.getVisibility() != VISIBLE || mSnippetTextView == null) {
|
||||||
|
mCategoryChipView.setTranslationY(0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int chipHeight = mCategoryChipView.getHeight();
|
||||||
|
if (chipHeight <= 0) {
|
||||||
|
mCategoryChipView.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
|
||||||
|
chipHeight = mCategoryChipView.getMeasuredHeight();
|
||||||
|
}
|
||||||
|
if (chipHeight <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Paint.FontMetricsInt fm = mSnippetTextView.getPaint().getFontMetricsInt();
|
||||||
|
final int textHeight = fm.descent - fm.ascent;
|
||||||
|
int textTop = mSnippetTextView.getPaddingTop();
|
||||||
|
final Layout layout = mSnippetTextView.getLayout();
|
||||||
|
if (layout != null && layout.getLineCount() > 0) {
|
||||||
|
textTop = mSnippetTextView.getPaddingTop() + layout.getLineBaseline(0) + fm.ascent;
|
||||||
|
}
|
||||||
|
mCategoryChipView.setTranslationY(textTop + (textHeight - chipHeight) / 2f);
|
||||||
|
}
|
||||||
|
|
||||||
private int getSnippetChipIndent() {
|
private int getSnippetChipIndent() {
|
||||||
if (mCategoryChipView == null || mCategoryChipView.getVisibility() != VISIBLE) {
|
if (mCategoryChipView == null || mCategoryChipView.getVisibility() != VISIBLE) {
|
||||||
|
|||||||
@@ -22,14 +22,20 @@ public final class HomeCategoryAddModal {
|
|||||||
void onCategoryCreated(HomeCategoryStore.Category created);
|
void onCategoryCreated(HomeCategoryStore.Category created);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean sShowing;
|
||||||
|
|
||||||
private HomeCategoryAddModal() {
|
private HomeCategoryAddModal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void show(@NonNull final Context context, @Nullable final Listener listener) {
|
public static void show(@NonNull final Context context, @Nullable final Listener listener) {
|
||||||
|
if (sShowing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sShowing = true;
|
||||||
final View content = LayoutInflater.from(context)
|
final View content = LayoutInflater.from(context)
|
||||||
.inflate(R.layout.home_category_name_dialog, null, false);
|
.inflate(R.layout.home_category_name_dialog, null, false);
|
||||||
final EditText field = content.findViewById(R.id.home_category_name_field);
|
final EditText field = content.findViewById(R.id.home_category_name_field);
|
||||||
HomeModal.builder(context)
|
final HomeModal.Handle handle = HomeModal.builder(context)
|
||||||
.icon(R.drawable.ic_home_category)
|
.icon(R.drawable.ic_home_category)
|
||||||
.title(R.string.home_category_add)
|
.title(R.string.home_category_add)
|
||||||
.message(R.string.home_category_name_message)
|
.message(R.string.home_category_name_message)
|
||||||
@@ -44,6 +50,11 @@ public final class HomeCategoryAddModal {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.show();
|
.show();
|
||||||
|
if (handle == null || handle.dialog == null) {
|
||||||
|
sShowing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handle.dialog.setOnDismissListener(dialog -> sShowing = false);
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
field.requestFocus();
|
field.requestFocus();
|
||||||
ImeUtil.get().showImeKeyboard(context, field);
|
ImeUtil.get().showImeKeyboard(context, field);
|
||||||
|
|||||||
@@ -202,6 +202,46 @@ public class ImageUtils {
|
|||||||
return inSampleSize;
|
return inSampleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cap for full-resolution decodes when the caller did not give a target size.
|
||||||
|
* 2048px keeps a 12 MP photo from becoming a ~48 MB ARGB_8888 bitmap.
|
||||||
|
*/
|
||||||
|
public static final int MAX_DECODE_EDGE = 2048;
|
||||||
|
|
||||||
|
public static Bitmap decodeByteArraySampled(final byte[] bytes, final int reqWidth,
|
||||||
|
final int reqHeight) {
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final BitmapFactory.Options bounds = new BitmapFactory.Options();
|
||||||
|
bounds.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, bounds);
|
||||||
|
int targetWidth = reqWidth;
|
||||||
|
int targetHeight = reqHeight;
|
||||||
|
if (targetWidth == ImageRequest.UNSPECIFIED_SIZE
|
||||||
|
&& targetHeight == ImageRequest.UNSPECIFIED_SIZE) {
|
||||||
|
targetWidth = MAX_DECODE_EDGE;
|
||||||
|
targetHeight = MAX_DECODE_EDGE;
|
||||||
|
}
|
||||||
|
final BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
options.outWidth = bounds.outWidth;
|
||||||
|
options.outHeight = bounds.outHeight;
|
||||||
|
options.inSampleSize = get().calculateInSampleSize(options, targetWidth, targetHeight);
|
||||||
|
options.inJustDecodeBounds = false;
|
||||||
|
options.inMutable = true;
|
||||||
|
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] readStreamToByteArray(final InputStream inputStream) throws IOException {
|
||||||
|
final ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
final byte[] buffer = new byte[16 * 1024];
|
||||||
|
int read;
|
||||||
|
while ((read = inputStream.read(buffer)) != -1) {
|
||||||
|
output.write(buffer, 0, read);
|
||||||
|
}
|
||||||
|
return output.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
private static final String[] MEDIA_CONTENT_PROJECTION = new String[] {
|
private static final String[] MEDIA_CONTENT_PROJECTION = new String[] {
|
||||||
MediaStore.MediaColumns.MIME_TYPE
|
MediaStore.MediaColumns.MIME_TYPE
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -1,18 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
|
||||||
SPDX-FileCopyrightText: 2022 The LineageOS Project
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108">
|
||||||
<path
|
<path android:pathData="M0,0h108v108h-108z">
|
||||||
android:pathData="M0,0h108v108h-108z"
|
<aapt:attr name="android:fillColor">
|
||||||
android:fillColor="#359944"/>
|
<gradient
|
||||||
<path
|
android:type="linear"
|
||||||
android:pathData="M54,76C66.15,76 76,66.15 76,54C76,49.769 74.806,45.817 72.736,42.463L74.327,36.098C74.693,34.634 73.366,33.307 71.902,33.673L65.537,35.264C62.183,33.194 58.231,32 54,32C41.85,32 32,41.85 32,54C32,66.15 41.85,76 54,76Z"
|
android:startX="54"
|
||||||
android:fillColor="#ffffff"
|
android:startY="0"
|
||||||
android:fillType="evenOdd"/>
|
android:endX="54"
|
||||||
|
android:endY="108">
|
||||||
|
<item android:offset="0" android:color="#8E2DEE"/>
|
||||||
|
<item android:offset="1" android:color="#530CCA"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
SPDX-FileCopyrightText: 2022 The LineageOS Project
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<group>
|
|
||||||
<clip-path
|
|
||||||
android:pathData="M0,0h108v108h-108z"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M54,66C60.75,66 66,63.627 66,57C66,47.373 60.75,42 54,42C47.25,42 42,47.373 42,57C42,63.627 47.25,66 54,66ZM54,57.5C57.057,57.5 60.055,56.942 62,56C61.125,58.603 59.333,62 54,62C48.667,62 46.875,58.603 46,56C47.945,56.942 50.943,57.5 54,57.5Z"
|
|
||||||
android:fillColor="#143721"
|
|
||||||
android:fillType="evenOdd"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M28.54,28.54m-72,0a72,72 0,1 1,144 0a72,72 0,1 1,-144 0"
|
|
||||||
android:fillAlpha="0.6">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:gradientRadius="72"
|
|
||||||
android:centerX="28.54"
|
|
||||||
android:centerY="28.54"
|
|
||||||
android:type="radial">
|
|
||||||
<item android:offset="0" android:color="#19FFFFFF"/>
|
|
||||||
<item android:offset="1" android:color="#00FFFFFF"/>
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -1,19 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
SPDX-FileCopyrightText: 2022 The LineageOS Project
|
android:src="@drawable/ic_launcher_foreground"
|
||||||
SPDX-License-Identifier: Apache-2.0
|
android:tint="#FF000000" />
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:pathData="M69.465,42.887L70.916,37.083L65.113,38.534L64.033,37.861C61.123,36.048 57.688,35 54,35C43.507,35 35,43.507 35,54C35,64.493 43.507,73 54,73C64.493,73 73,64.493 73,54C73,50.311 71.952,46.876 70.138,43.966L69.465,42.887ZM76,54C76,66.15 66.15,76 54,76C41.85,76 32,66.15 32,54C32,41.85 41.85,32 54,32C58.265,32 62.248,33.214 65.619,35.315L71.805,33.769C73.27,33.403 74.597,34.729 74.23,36.194L72.684,42.38C74.786,45.752 76,49.734 76,54Z"
|
|
||||||
android:fillColor="#ffffffff"
|
|
||||||
android:fillType="evenOdd"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M54,65.733C60.6,65.733 65.733,63.414 65.733,56.933C65.733,47.52 60.6,42.267 54,42.267C47.4,42.267 42.267,47.52 42.267,56.933C42.267,63.414 47.4,65.733 54,65.733ZM54,56.933C56.802,56.933 59.551,56.387 61.333,55.467C60.532,58.012 58.889,61.333 54,61.333C49.111,61.333 47.468,58.012 46.667,55.467C48.449,56.387 51.198,56.933 54,56.933Z"
|
|
||||||
android:fillColor="#ffffffff"
|
|
||||||
android:fillType="evenOdd"/>
|
|
||||||
</vector>
|
|
||||||
|
|||||||
@@ -275,8 +275,8 @@
|
|||||||
<include
|
<include
|
||||||
android:id="@+id/home_category_add"
|
android:id="@+id/home_category_add"
|
||||||
layout="@layout/home_category_add_tab"
|
layout="@layout/home_category_add_tab"
|
||||||
android:layout_width="32dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="32dp" />
|
android:layout_height="24dp" />
|
||||||
</com.android.messaging.ui.home.HomeCategoryStrip>
|
</com.android.messaging.ui.home.HomeCategoryStrip>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -274,7 +274,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top|start"
|
android:layout_gravity="top|start"
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -2,9 +2,12 @@
|
|||||||
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
|
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
style="@style/Home.AddButton"
|
style="@style/Home.AddButton"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
android:layout_marginEnd="4dp"
|
android:layout_marginEnd="4dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
|
android:padding="6dp"
|
||||||
android:contentDescription="@string/home_category_add_content_description"
|
android:contentDescription="@string/home_category_add_content_description"
|
||||||
app:srcCompat="@drawable/ic_home_automation_plus"
|
app:srcCompat="@drawable/ic_home_automation_plus"
|
||||||
app:tint="@color/home_add_icon_tint" />
|
app:tint="@color/home_add_icon_tint" />
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
-keep class com.android.messaging.ui.contact.* { *; }
|
|
||||||
|
|
||||||
-assumenosideeffects public class com.android.messaging.util.Trace {
|
-assumenosideeffects public class com.android.messaging.util.Trace {
|
||||||
public void beginSection(...);
|
public void beginSection(...);
|
||||||
public void endSection(...);
|
public void endSection(...);
|
||||||
|
|||||||
+15
-24
@@ -22,54 +22,45 @@
|
|||||||
RuntimeVisibleTypeAnnotations,
|
RuntimeVisibleTypeAnnotations,
|
||||||
AnnotationDefault
|
AnnotationDefault
|
||||||
|
|
||||||
-keep class com.android.messaging.* { *; }
|
# Manifest / XML entry points. Do not keep the whole app or androidx packages —
|
||||||
-keep class com.android.messaging.*.* { *; }
|
# Play requires 25% shrink / optimize / obfuscate when uncompressed DEX > 10 MB.
|
||||||
-keep class com.android.messaging.*.*.* { *; }
|
|
||||||
|
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.app.Activity {
|
-keep public class * extends android.app.Activity {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.app.Application {
|
-keep public class * extends android.app.Application {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.app.Service {
|
-keep public class * extends android.app.Service {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.content.BroadcastReceiver {
|
-keep public class * extends android.content.BroadcastReceiver {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.content.ContentProvider {
|
-keep public class * extends android.content.ContentProvider {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.app.backup.BackupAgentHelper {
|
-keep public class * extends android.app.backup.BackupAgentHelper {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
|
||||||
-keep public class * extends android.preference.Preference {
|
-keep public class * extends android.preference.Preference {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
# TODO(b/373579455): Evaluate if <init> needs to be kept.
|
-keep public class * extends androidx.preference.Preference {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
-keep public class * extends androidx.fragment.app.Fragment {
|
-keep public class * extends androidx.fragment.app.Fragment {
|
||||||
void <init>();
|
void <init>();
|
||||||
}
|
}
|
||||||
-keep public class com.android.vcard.* { *; }
|
|
||||||
|
|
||||||
-keep class androidx.collection.* { *; }
|
# Actions cross the ActionService / BackgroundWorker via Parcelable extras.
|
||||||
-keep class androidx.core.* { *; }
|
-keep class com.android.messaging.datamodel.action.Action {
|
||||||
-keep class androidx.core.*.* { *; }
|
void <init>();
|
||||||
-keep class androidx.appcompat.* { *; }
|
}
|
||||||
-keep class androidx.appcompat.*.* { *; }
|
-keep class * extends com.android.messaging.datamodel.action.Action {
|
||||||
-keep class androidx.recyclerview.widget.* { *; }
|
public static android.os.Parcelable$Creator CREATOR;
|
||||||
-keep class androidx.viewpager.widget.* { *; }
|
<init>(...);
|
||||||
|
}
|
||||||
# Keep rastermill classes that need to be accessed from native code (JNI)
|
|
||||||
-keep class android.support.rastermill.** { *; }
|
|
||||||
|
|
||||||
# Preserve the name of the getCaller method so it can find itself in the stack trace it generates
|
# Preserve the name of the getCaller method so it can find itself in the stack trace it generates
|
||||||
-keepclassmembers public class com.android.messaging.util.DebugUtils {
|
-keepclassmembers public class com.android.messaging.util.DebugUtils {
|
||||||
@@ -77,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Keep the static fields of referenced inner classes of auto-generated R classes, in case we
|
# Keep the static fields of referenced inner classes of auto-generated R classes, in case we
|
||||||
# access those fields by reflection (e.g. EmojiMarkup)
|
# access those fields by reflection
|
||||||
-keepclassmembers class **.R$* {
|
-keepclassmembers class **.R$* {
|
||||||
public static <fields>;
|
public static <fields>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user