Merge "Use ImageResolver for BigPictureStyle when using BigPicture" into sc-dev
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.AttrRes;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StyleRes;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An ImageView used by BigPicture Notifications to correctly resolve the Uri in an Icon using the
|
||||
* LocalImageResolver, allowing it to support animated drawables which are not supported by
|
||||
* Icon.loadDrawable().
|
||||
*/
|
||||
@RemoteViews.RemoteView
|
||||
public class BigPictureNotificationImageView extends ImageView {
|
||||
|
||||
private static final String TAG = BigPictureNotificationImageView.class.getSimpleName();
|
||||
|
||||
public BigPictureNotificationImageView(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public BigPictureNotificationImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public BigPictureNotificationImageView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
@AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public BigPictureNotificationImageView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
@AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@android.view.RemotableViewMethod(asyncImpl = "setImageURIAsync")
|
||||
public void setImageURI(@Nullable Uri uri) {
|
||||
setImageDrawable(loadImage(uri));
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
public Runnable setImageURIAsync(@Nullable Uri uri) {
|
||||
final Drawable drawable = loadImage(uri);
|
||||
return () -> setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@android.view.RemotableViewMethod(asyncImpl = "setImageIconAsync")
|
||||
public void setImageIcon(@Nullable Icon icon) {
|
||||
setImageDrawable(loadImage(icon));
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
public Runnable setImageIconAsync(@Nullable Icon icon) {
|
||||
final Drawable drawable = loadImage(icon);
|
||||
return () -> setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
private Drawable loadImage(Uri uri) {
|
||||
if (uri == null) return null;
|
||||
try {
|
||||
return LocalImageResolver.resolveImage(uri, mContext);
|
||||
} catch (IOException ex) {
|
||||
Log.d(TAG, "Resolve failed from " + uri, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Drawable loadImage(Icon icon) {
|
||||
if (icon == null) return null;
|
||||
try {
|
||||
return LocalImageResolver.resolveImage(icon, mContext);
|
||||
} catch (IOException ex) {
|
||||
Log.d(TAG, "Resolve failed from " + icon, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.ImageDecoder;
|
||||
import android.graphics.drawable.AnimatedImageDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
import android.util.Size;
|
||||
|
||||
@@ -31,6 +32,9 @@ public class LocalImageResolver {
|
||||
|
||||
private static final int MAX_SAFE_ICON_SIZE_PX = 480;
|
||||
|
||||
/**
|
||||
* Resolve an image from the given Uri using {@link ImageDecoder}
|
||||
*/
|
||||
public static Drawable resolveImage(Uri uri, Context context) throws IOException {
|
||||
final ImageDecoder.Source source =
|
||||
ImageDecoder.createSource(context.getContentResolver(), uri);
|
||||
@@ -39,6 +43,25 @@ public class LocalImageResolver {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the drawable from Icon using {@link ImageDecoder} if it contains a Uri, or
|
||||
* using {@link Icon#loadDrawable(Context)} otherwise. This will correctly apply the Icon's,
|
||||
* tint, if present, to the drawable.
|
||||
*/
|
||||
public static Drawable resolveImage(Icon icon, Context context) throws IOException {
|
||||
Uri uri = getResolvableUri(icon);
|
||||
if (uri != null) {
|
||||
Drawable result = resolveImage(uri, context);
|
||||
if (icon.hasTint()) {
|
||||
result.mutate();
|
||||
result.setTintList(icon.getTintList());
|
||||
result.setTintBlendMode(icon.getTintBlendMode());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return icon.loadDrawable(context);
|
||||
}
|
||||
|
||||
public static Drawable resolveImage(Uri uri, Context context, int maxWidth, int maxHeight)
|
||||
throws IOException {
|
||||
final ImageDecoder.Source source =
|
||||
@@ -73,4 +96,16 @@ public class LocalImageResolver {
|
||||
: 1.0;
|
||||
decoder.setTargetSampleSize(getPowerOfTwoForSampleRatio(ratio));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Uri for this icon, assuming the icon can be treated as a pure Uri. Null otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
public static Uri getResolvableUri(@Nullable Icon icon) {
|
||||
if (icon == null || (icon.getType() != Icon.TYPE_URI
|
||||
&& icon.getType() != Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
|
||||
return null;
|
||||
}
|
||||
return icon.getUri();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<include layout="@layout/notification_template_text_multiline" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
<com.android.internal.widget.BigPictureNotificationImageView
|
||||
android:id="@+id/big_picture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.annotation.ColorInt;
|
||||
import android.annotation.DrawableRes;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -336,7 +337,7 @@ public final class Icon implements Parcelable {
|
||||
*/
|
||||
public Drawable loadDrawable(Context context) {
|
||||
final Drawable result = loadDrawableInner(context);
|
||||
if (result != null && (mTintList != null || mBlendMode != DEFAULT_BLEND_MODE)) {
|
||||
if (result != null && hasTint()) {
|
||||
result.mutate();
|
||||
result.setTintList(mTintList);
|
||||
result.setTintBlendMode(mBlendMode);
|
||||
@@ -762,6 +763,11 @@ public final class Icon implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public @Nullable ColorStateList getTintList() {
|
||||
return mTintList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a blending mode to use whenever this Icon is drawn.
|
||||
*
|
||||
@@ -784,6 +790,11 @@ public final class Icon implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public @NonNull BlendMode getTintBlendMode() {
|
||||
return mBlendMode;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
public boolean hasTint() {
|
||||
|
||||
Reference in New Issue
Block a user