summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/discovery
diff options
context:
space:
mode:
authorMario Bertschler <bmario@google.com>2017-02-17 12:16:13 -0800
committerMario Bertschler <bmario@google.com>2017-03-03 13:05:57 -0800
commit0fc6f684e730b0137900fe317f2c759c1b3909c7 (patch)
tree05b8a9aa9863127e6f9728c13a71968c9e5ab1c6 /src/com/android/launcher3/discovery
parent74480b7bca8451eaea64236cb4b4c8e31def6b9b (diff)
downloadandroid_packages_apps_Trebuchet-0fc6f684e730b0137900fe317f2c759c1b3909c7.tar.gz
android_packages_apps_Trebuchet-0fc6f684e730b0137900fe317f2c759c1b3909c7.tar.bz2
android_packages_apps_Trebuchet-0fc6f684e730b0137900fe317f2c759c1b3909c7.zip
App discovery integration in All Apps search
This is the basis for app discovery integration while searching in all apps. This does NOT include binding to the actual service and retrieving results, but instead provides all the UI to show suggested instant apps and apps from a store with star rating and pricing. Change-Id: I1605b52848491acee4ac1d15c0112e6a768363f6
Diffstat (limited to 'src/com/android/launcher3/discovery')
-rw-r--r--src/com/android/launcher3/discovery/AppDiscoveryAppInfo.java88
-rw-r--r--src/com/android/launcher3/discovery/AppDiscoveryItem.java62
-rw-r--r--src/com/android/launcher3/discovery/AppDiscoveryItemView.java100
-rw-r--r--src/com/android/launcher3/discovery/AppDiscoveryUpdateState.java21
-rw-r--r--src/com/android/launcher3/discovery/RatingView.java94
5 files changed, 365 insertions, 0 deletions
diff --git a/src/com/android/launcher3/discovery/AppDiscoveryAppInfo.java b/src/com/android/launcher3/discovery/AppDiscoveryAppInfo.java
new file mode 100644
index 000000000..50e979aac
--- /dev/null
+++ b/src/com/android/launcher3/discovery/AppDiscoveryAppInfo.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 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.discovery;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutInfo;
+
+public class AppDiscoveryAppInfo extends AppInfo {
+
+ private final @NonNull Launcher mLauncher;
+
+ public final boolean showAsDiscoveryItem;
+ public final boolean isInstantApp;
+ public final float rating;
+ public final long reviewCount;
+ public final @NonNull String publisher;
+ public final @NonNull Intent installIntent;
+ public final @NonNull Intent launchIntent;
+ public final @Nullable String priceFormatted;
+
+ public AppDiscoveryAppInfo(AppDiscoveryItem item, Launcher launcher) {
+ this.mLauncher = launcher;
+ this.intent = item.isInstantApp ? item.launchIntent : item.installIntent;
+ this.title = item.title;
+ this.iconBitmap = item.bitmap;
+ this.isDisabled = ShortcutInfo.DEFAULT;
+ this.usingLowResIcon = false;
+ this.isInstantApp = item.isInstantApp;
+ this.rating = item.starRating;
+ this.showAsDiscoveryItem = true;
+ this.publisher = item.publisher != null ? item.publisher : "";
+ this.priceFormatted = item.price;
+ this.componentName = new ComponentName(item.packageName, "");
+ this.installIntent = item.installIntent;
+ this.launchIntent = item.launchIntent;
+ this.reviewCount = item.reviewCount;
+ this.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ }
+
+ @Override
+ public ShortcutInfo makeShortcut() {
+ if (!isDragAndDropSupported()) {
+ throw new RuntimeException("DnD is currently not supported for discovered store apps");
+ }
+ ShortcutInfo shortcutInfo = super.makeShortcut();
+ if (isInstantApp) {
+ int iconSize = iconBitmap.getWidth();
+ int badgeSize = mLauncher.getResources().getDimensionPixelOffset(R.dimen.badge_size);
+ Bitmap icon = Bitmap.createBitmap(iconBitmap);
+ Drawable badgeDrawable = mLauncher.getDrawable(R.drawable.ic_instant_app);
+ badgeDrawable.setBounds(iconSize - badgeSize, iconSize - badgeSize, iconSize, iconSize);
+ Canvas canvas = new Canvas(icon);
+ badgeDrawable.draw(canvas);
+ shortcutInfo.iconBitmap = icon;
+ }
+ return shortcutInfo;
+ }
+
+ public boolean isDragAndDropSupported() {
+ return isInstantApp;
+ }
+
+}
diff --git a/src/com/android/launcher3/discovery/AppDiscoveryItem.java b/src/com/android/launcher3/discovery/AppDiscoveryItem.java
new file mode 100644
index 000000000..7c10371d0
--- /dev/null
+++ b/src/com/android/launcher3/discovery/AppDiscoveryItem.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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.discovery;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+
+/**
+ * This class represents the model for a discovered app via app discovery.
+ * It holds all information for one result retrieved from an app discovery service.
+ */
+public class AppDiscoveryItem {
+
+ public final String packageName;
+ public final boolean isInstantApp;
+ public final float starRating;
+ public final long reviewCount;
+ public final Intent launchIntent;
+ public final Intent installIntent;
+ public final CharSequence title;
+ public final String publisher;
+ public final String price;
+ public final Bitmap bitmap;
+
+ public AppDiscoveryItem(String packageName,
+ boolean isInstantApp,
+ float starRating,
+ long reviewCount,
+ CharSequence title,
+ String publisher,
+ Bitmap bitmap,
+ String price,
+ Intent launchIntent,
+ Intent installIntent) {
+ this.packageName = packageName;
+ this.isInstantApp = isInstantApp;
+ this.starRating = starRating;
+ this.reviewCount = reviewCount;
+ this.launchIntent = launchIntent;
+ this.installIntent = installIntent;
+ this.title = title;
+ this.publisher = publisher;
+ this.price = price;
+ this.bitmap = bitmap;
+ }
+
+}
diff --git a/src/com/android/launcher3/discovery/AppDiscoveryItemView.java b/src/com/android/launcher3/discovery/AppDiscoveryItemView.java
new file mode 100644
index 000000000..6faad87ab
--- /dev/null
+++ b/src/com/android/launcher3/discovery/AppDiscoveryItemView.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.discovery;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.launcher3.R;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+public class AppDiscoveryItemView extends RelativeLayout {
+
+ private static boolean SHOW_REVIEW_COUNT = false;
+
+ private ImageView mImage;
+ private ImageView mBadge;
+ private TextView mTitle;
+ private TextView mRatingText;
+ private RatingView mRatingView;
+ private TextView mReviewCount;
+ private TextView mPrice;
+ private OnLongClickListener mOnLongClickListener;
+
+ public AppDiscoveryItemView(Context context) {
+ this(context, null);
+ }
+
+ public AppDiscoveryItemView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AppDiscoveryItemView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ this.mImage = (ImageView) findViewById(R.id.image);
+ this.mBadge = (ImageView) findViewById(R.id.badge);
+ this.mTitle = (TextView) findViewById(R.id.title);
+ this.mRatingText = (TextView) findViewById(R.id.rating);
+ this.mRatingView = (RatingView) findViewById(R.id.rating_view);
+ this.mPrice = (TextView) findViewById(R.id.price);
+ this.mReviewCount = (TextView) findViewById(R.id.review_count);
+ }
+
+ public void init(OnClickListener clickListener,
+ AccessibilityDelegate accessibilityDelegate,
+ OnLongClickListener onLongClickListener) {
+ setOnClickListener(clickListener);
+ mImage.setOnClickListener(clickListener);
+ setAccessibilityDelegate(accessibilityDelegate);
+ mOnLongClickListener = onLongClickListener;
+ }
+
+ public void apply(@NonNull AppDiscoveryAppInfo info) {
+ setTag(info);
+ mImage.setTag(info);
+ mImage.setImageBitmap(info.iconBitmap);
+ mImage.setOnLongClickListener(info.isDragAndDropSupported() ? mOnLongClickListener : null);
+ mBadge.setVisibility(info.isInstantApp ? View.VISIBLE : View.GONE);
+ mTitle.setText(info.title);
+ mPrice.setText(info.priceFormatted != null ? info.priceFormatted : "");
+ mReviewCount.setVisibility(SHOW_REVIEW_COUNT ? View.VISIBLE : View.GONE);
+ if (info.rating >= 0) {
+ mRatingText.setText(new DecimalFormat("#.#").format(info.rating));
+ mRatingView.setRating(info.rating);
+ mRatingView.setVisibility(View.VISIBLE);
+ String reviewCountFormatted = NumberFormat.getInstance().format(info.reviewCount);
+ mReviewCount.setText("(" + reviewCountFormatted + ")");
+ } else {
+ // if we don't have a rating
+ mRatingView.setVisibility(View.GONE);
+ mRatingText.setText("");
+ mReviewCount.setText("");
+ }
+ }
+}
diff --git a/src/com/android/launcher3/discovery/AppDiscoveryUpdateState.java b/src/com/android/launcher3/discovery/AppDiscoveryUpdateState.java
new file mode 100644
index 000000000..0700a1023
--- /dev/null
+++ b/src/com/android/launcher3/discovery/AppDiscoveryUpdateState.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 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.discovery;
+
+public enum AppDiscoveryUpdateState {
+ START, UPDATE, END
+}
diff --git a/src/com/android/launcher3/discovery/RatingView.java b/src/com/android/launcher3/discovery/RatingView.java
new file mode 100644
index 000000000..8fe63d6ba
--- /dev/null
+++ b/src/com/android/launcher3/discovery/RatingView.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 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.discovery;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.ClipDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+
+import com.android.launcher3.R;
+
+/**
+ * A simple rating view that shows stars with a rating from 0-5.
+ */
+public class RatingView extends View {
+
+ private static final float WIDTH_FACTOR = 0.9f;
+ private static final int MAX_LEVEL = 10000;
+ private static final int MAX_STARS = 5;
+
+ private final Drawable mStarDrawable;
+ private final int mColorGray;
+ private final int mColorHighlight;
+
+ private float rating;
+
+ public RatingView(Context context) {
+ this(context, null);
+ }
+
+ public RatingView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RatingView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mStarDrawable = getResources().getDrawable(R.drawable.ic_star_rating, null);
+ mColorGray = 0x1E000000;
+ mColorHighlight = 0x8A000000;
+ }
+
+ public void setRating(float rating) {
+ this.rating = Math.min(Math.max(rating, 0), MAX_STARS);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ drawStars(canvas, MAX_STARS, mColorGray);
+ drawStars(canvas, rating, mColorHighlight);
+ }
+
+ private void drawStars(Canvas canvas, float stars, int color) {
+ int fullWidth = getLayoutParams().width;
+ int cellWidth = fullWidth / MAX_STARS;
+ int starWidth = (int) (cellWidth * WIDTH_FACTOR);
+ int padding = cellWidth - starWidth;
+ int fullStars = (int) stars;
+ float partialStarFactor = stars - fullStars;
+
+ for (int i = 0; i < fullStars; i++) {
+ int x = i * cellWidth + padding;
+ Drawable star = mStarDrawable.getConstantState().newDrawable().mutate();
+ star.setTint(color);
+ star.setBounds(x, padding, x + starWidth, padding + starWidth);
+ star.draw(canvas);
+ }
+ if (partialStarFactor > 0f) {
+ int x = fullStars * cellWidth + padding;
+ ClipDrawable star = new ClipDrawable(mStarDrawable,
+ Gravity.LEFT, ClipDrawable.HORIZONTAL);
+ star.setTint(color);
+ star.setLevel((int) (MAX_LEVEL * partialStarFactor));
+ star.setBounds(x, padding, x + starWidth, padding + starWidth);
+ star.draw(canvas);
+ }
+ }
+}