fd58d23cdf
Setup architecture for separation between aosp and quickstep search as setup for switch to android.app.SearchTarget Bug: 177223401 Test: manual Change-Id: Iefd069a34d5e5551bf731e9171958e93377774aa
204 lines
7.7 KiB
Java
204 lines
7.7 KiB
Java
/*
|
|
* 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.launcher3.search;
|
|
|
|
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Paint;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffXfermode;
|
|
import android.graphics.Rect;
|
|
import android.graphics.RectF;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.Button;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import com.android.launcher3.DeviceProfile;
|
|
import com.android.launcher3.Launcher;
|
|
import com.android.launcher3.R;
|
|
import com.android.launcher3.icons.BitmapRenderer;
|
|
import com.android.launcher3.util.Themes;
|
|
import com.android.systemui.plugins.shared.SearchTarget;
|
|
import com.android.systemui.plugins.shared.SearchTargetEvent;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URL;
|
|
import java.net.URLConnection;
|
|
|
|
/**
|
|
* A View representing a PlayStore item.
|
|
*/
|
|
public class SearchResultPlayItem extends LinearLayout implements
|
|
SearchTargetHandler {
|
|
|
|
public static final String TARGET_TYPE_PLAY = "play";
|
|
|
|
private static final int BITMAP_CROP_MASK_COLOR = 0xff424242;
|
|
final Paint mIconPaint = new Paint();
|
|
final Rect mTempRect = new Rect();
|
|
private final DeviceProfile mDeviceProfile;
|
|
private View mIconView;
|
|
private TextView mTitleView;
|
|
private TextView[] mDetailViews = new TextView[3];
|
|
private Button mPreviewButton;
|
|
private String mPackageName;
|
|
private boolean mIsInstantGame;
|
|
|
|
private SearchTarget mSearchTarget;
|
|
|
|
|
|
public SearchResultPlayItem(Context context) {
|
|
this(context, null, 0);
|
|
}
|
|
|
|
public SearchResultPlayItem(Context context,
|
|
@Nullable AttributeSet attrs) {
|
|
this(context, attrs, 0);
|
|
}
|
|
|
|
public SearchResultPlayItem(Context context, @Nullable AttributeSet attrs,
|
|
int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
mDeviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
|
|
}
|
|
|
|
@Override
|
|
protected void onFinishInflate() {
|
|
super.onFinishInflate();
|
|
mIconView = findViewById(R.id.icon);
|
|
mTitleView = findViewById(R.id.title_view);
|
|
mPreviewButton = findViewById(R.id.try_button);
|
|
mPreviewButton.setOnClickListener(view -> launchInstantGame());
|
|
mDetailViews[0] = findViewById(R.id.detail_0);
|
|
mDetailViews[1] = findViewById(R.id.detail_1);
|
|
mDetailViews[2] = findViewById(R.id.detail_2);
|
|
|
|
ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
|
|
iconParams.height = mDeviceProfile.allAppsIconSizePx;
|
|
iconParams.width = mDeviceProfile.allAppsIconSizePx;
|
|
setOnClickListener(view -> handleSelection(SearchTargetEvent.SELECT));
|
|
}
|
|
|
|
|
|
private Bitmap getRoundedBitmap(Bitmap bitmap) {
|
|
final int iconSize = bitmap.getWidth();
|
|
final float radius = Themes.getDialogCornerRadius(getContext());
|
|
|
|
Bitmap output = BitmapRenderer.createHardwareBitmap(iconSize, iconSize, (canvas) -> {
|
|
mTempRect.set(0, 0, iconSize, iconSize);
|
|
final RectF rectF = new RectF(mTempRect);
|
|
|
|
mIconPaint.setAntiAlias(true);
|
|
mIconPaint.reset();
|
|
canvas.drawARGB(0, 0, 0, 0);
|
|
mIconPaint.setColor(BITMAP_CROP_MASK_COLOR);
|
|
canvas.drawRoundRect(rectF, radius, radius, mIconPaint);
|
|
|
|
mIconPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
|
canvas.drawBitmap(bitmap, mTempRect, mTempRect, mIconPaint);
|
|
});
|
|
return output;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void applySearchTarget(SearchTarget searchTarget) {
|
|
mSearchTarget = searchTarget;
|
|
Bundle bundle = searchTarget.getExtras();
|
|
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
|
|
if (bundle.getString("package", "").equals(mPackageName)) {
|
|
return;
|
|
}
|
|
mIsInstantGame = bundle.getBoolean("instant_game", false);
|
|
mPackageName = bundle.getString("package");
|
|
mPreviewButton.setVisibility(mIsInstantGame ? VISIBLE : GONE);
|
|
mTitleView.setText(bundle.getString("title"));
|
|
// TODO: Should use a generic type to get values b/165320033
|
|
showIfNecessary(mDetailViews[0], bundle.getString("price"));
|
|
showIfNecessary(mDetailViews[1], bundle.getString("rating"));
|
|
|
|
mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
|
|
UI_HELPER_EXECUTOR.execute(() -> {
|
|
try {
|
|
URL url = new URL(bundle.getString("icon_url"));
|
|
URLConnection con = url.openConnection();
|
|
// TODO: monitor memory and investigate if it's better to use glide
|
|
con.addRequestProperty("Cache-Control", "max-age: 0");
|
|
con.setUseCaches(true);
|
|
Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
|
|
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
|
|
Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
|
|
mDeviceProfile.allAppsIconSizePx, false)));
|
|
mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void showIfNecessary(TextView textView, @Nullable String string) {
|
|
if (string == null || string.isEmpty()) {
|
|
textView.setVisibility(GONE);
|
|
} else {
|
|
textView.setText(string);
|
|
textView.setVisibility(VISIBLE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void handleSelection(int eventType) {
|
|
if (mPackageName == null) return;
|
|
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(
|
|
"https://play.google.com/store/apps/details?id="
|
|
+ mPackageName));
|
|
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
getContext().startActivity(i);
|
|
logSearchEvent(eventType);
|
|
}
|
|
|
|
private void launchInstantGame() {
|
|
if (!mIsInstantGame) return;
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
String referrer = "Pixel_Launcher";
|
|
String id = mPackageName;
|
|
String deepLinkUrl = "market://details?id=" + id + "&launch=true&referrer=" + referrer;
|
|
intent.setPackage("com.android.vending");
|
|
intent.setData(Uri.parse(deepLinkUrl));
|
|
intent.putExtra("overlay", true);
|
|
intent.putExtra("callerId", getContext().getPackageName());
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
getContext().startActivity(intent);
|
|
logSearchEvent(SearchTargetEvent.CHILD_SELECT);
|
|
}
|
|
|
|
private void logSearchEvent(int eventType) {
|
|
SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
|
|
new SearchTargetEvent.Builder(mSearchTarget, eventType).build());
|
|
}
|
|
}
|