/* * Copyright (C) 2015 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.tv.menu; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.support.v7.graphics.Palette; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.android.tv.MainActivity; import com.android.tv.R; import com.android.tv.data.Channel; import com.android.tv.util.BitmapUtils; import com.android.tv.util.ImageLoader; import com.android.tv.util.TvInputManagerHelper; /** * A view to render an app link card. */ public class AppLinkCardView extends BaseCardView { private static final String TAG = MenuView.TAG; private static final boolean DEBUG = MenuView.DEBUG; private final int mCardImageWidth; private final int mCardImageHeight; private final int mIconWidth; private final int mIconHeight; private final int mIconPadding; private final int mIconColorFilter; private ImageView mImageView; private View mGradientView; private TextView mAppInfoView; private View mMetaViewHolder; private Channel mChannel; private Intent mIntent; private final PackageManager mPackageManager; private final TvInputManagerHelper mTvInputManagerHelper; public AppLinkCardView(Context context) { this(context, null); } public AppLinkCardView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public AppLinkCardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mCardImageWidth = getResources().getDimensionPixelSize(R.dimen.card_image_layout_width); mCardImageHeight = getResources().getDimensionPixelSize(R.dimen.card_image_layout_height); mIconWidth = getResources().getDimensionPixelSize(R.dimen.app_link_card_icon_width); mIconHeight = getResources().getDimensionPixelSize(R.dimen.app_link_card_icon_height); mIconPadding = getResources().getDimensionPixelOffset(R.dimen.app_link_card_icon_padding); mPackageManager = context.getPackageManager(); mTvInputManagerHelper = ((MainActivity) context).getTvInputManagerHelper(); mIconColorFilter = getResources().getColor(R.color.app_link_card_icon_color_filter, null); } /** * Returns the intent which will be started once this card is clicked. */ public Intent getIntent() { return mIntent; } @Override public void onBind(Channel channel, boolean selected) { if (DEBUG) { Log.d(TAG, "onBind(channelName=" + channel.getDisplayName() + ", selected=" + selected + ")"); } mChannel = channel; ApplicationInfo appInfo = mTvInputManagerHelper.getTvInputAppInfo(mChannel.getInputId()); int linkType = mChannel.getAppLinkType(getContext()); mIntent = mChannel.getAppLinkIntent(getContext()); switch (linkType) { case Channel.APP_LINK_TYPE_CHANNEL: setText(mChannel.getAppLinkText()); mAppInfoView.setVisibility(VISIBLE); mGradientView.setVisibility(VISIBLE); mAppInfoView.setCompoundDrawablePadding(mIconPadding); mAppInfoView.setCompoundDrawables(null, null, null, null); mAppInfoView.setText(mPackageManager.getApplicationLabel(appInfo)); if (!TextUtils.isEmpty(mChannel.getAppLinkIconUri())) { mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON, mIconWidth, mIconHeight, createChannelLogoCallback(this, mChannel, Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON)); } else if (appInfo.icon != 0) { Drawable appIcon = mPackageManager.getApplicationIcon(appInfo); BitmapUtils.setColorFilterToDrawable(mIconColorFilter, appIcon); appIcon.setBounds(0, 0, mIconWidth, mIconHeight); mAppInfoView.setCompoundDrawables(appIcon, null, null, null); } break; case Channel.APP_LINK_TYPE_APP: setText(getContext().getString( R.string.channels_item_app_link_app_launcher, mPackageManager.getApplicationLabel(appInfo))); mAppInfoView.setVisibility(GONE); mGradientView.setVisibility(GONE); break; default: mAppInfoView.setVisibility(GONE); mGradientView.setVisibility(GONE); Log.d(TAG, "Should not be here."); } if (mChannel.getAppLinkColor() == 0) { mMetaViewHolder.setBackgroundResource(R.color.channel_card_meta_background); } else { mMetaViewHolder.setBackgroundColor(mChannel.getAppLinkColor()); } if (!TextUtils.isEmpty(mChannel.getAppLinkPosterArtUri())) { mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default); mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART, mCardImageWidth, mCardImageHeight, createChannelLogoCallback(this, mChannel, Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART)); } else { setCardImageWithBanner(appInfo); } // Call super.onBind() at the end intentionally. In order to correctly handle extension of // text view, text should be set before calling super.onBind. super.onBind(channel, selected); } private static ImageLoader.ImageLoaderCallback createChannelLogoCallback( AppLinkCardView cardView, final Channel channel, final int type) { return new ImageLoader.ImageLoaderCallback(cardView) { @Override public void onBitmapLoaded(AppLinkCardView cardView, @Nullable Bitmap bitmap) { // mChannel can be changed before the image load finished. if (!cardView.mChannel.hasSameReadOnlyInfo(channel)) { return; } cardView.updateChannelLogo(bitmap, type); } }; } private void updateChannelLogo(@Nullable Bitmap bitmap, int type) { if (type == Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON) { BitmapDrawable drawable = null; if (bitmap != null) { drawable = new BitmapDrawable(getResources(), bitmap); if (bitmap.getWidth() > bitmap.getHeight()) { drawable.setBounds(0, 0, mIconWidth, mIconWidth * bitmap.getHeight() / bitmap.getWidth()); } else { drawable.setBounds(0, 0, mIconHeight * bitmap.getWidth() / bitmap.getHeight(), mIconHeight); } } BitmapUtils.setColorFilterToDrawable(mIconColorFilter, drawable); mAppInfoView.setCompoundDrawables(drawable, null, null, null); } else if (type == Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART) { if (bitmap == null) { setCardImageWithBanner( mTvInputManagerHelper.getTvInputAppInfo(mChannel.getInputId())); } else { mImageView.setImageBitmap(bitmap); if (mChannel.getAppLinkColor() == 0) { extractAndSetMetaViewBackgroundColor(bitmap); } } } } @Override protected void onFinishInflate() { super.onFinishInflate(); mImageView = (ImageView) findViewById(R.id.image); mGradientView = findViewById(R.id.image_gradient); mAppInfoView = (TextView) findViewById(R.id.app_info); mMetaViewHolder = findViewById(R.id.app_link_text_holder); } // Try to set the card image with following order: // 1) Provided poster art image, 2) Activity banner, 3) Activity icon, 4) Application banner, // 5) Application icon, and 6) default image. private void setCardImageWithBanner(ApplicationInfo appInfo) { Drawable banner = null; if (mIntent != null) { try { banner = mPackageManager.getActivityBanner(mIntent); if (banner == null) { banner = mPackageManager.getActivityIcon(mIntent); } } catch (PackageManager.NameNotFoundException e) { // do nothing. } } if (banner == null && appInfo != null) { if (appInfo.banner != 0) { banner = mPackageManager.getApplicationBanner(appInfo); } if (banner == null && appInfo.icon != 0) { banner = mPackageManager.getApplicationIcon(appInfo); } } if (banner == null) { mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default); mImageView.setBackgroundResource(R.color.channel_card); } else { Bitmap bitmap = Bitmap.createBitmap(mCardImageWidth, mCardImageHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); banner.setBounds(0, 0, mCardImageWidth, mCardImageHeight); banner.draw(canvas); mImageView.setImageDrawable(banner); if (mChannel.getAppLinkColor() == 0) { extractAndSetMetaViewBackgroundColor(bitmap); } } } private void extractAndSetMetaViewBackgroundColor(Bitmap bitmap) { new Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { mMetaViewHolder.setBackgroundColor(palette.getDarkVibrantColor( getResources().getColor(R.color.channel_card_meta_background, null))); } }); } }