Create BookmarkUtils class.
This factors out some bookmarks functionality that we would like to reuse when
impementing installable webapps.
Change-Id: Ia34d70b732c45220637767ddd0f05b280f0fc6bc
diff --git a/src/com/android/browser/BookmarkUtils.java b/src/com/android/browser/BookmarkUtils.java
new file mode 100644
index 0000000..0fdad15
--- /dev/null
+++ b/src/com/android/browser/BookmarkUtils.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2010 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.browser;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.net.Uri;
+import android.provider.Browser;
+import android.util.Log;
+
+class BookmarkUtils {
+ private final static String LOGTAG = "BookmarkUtils";
+
+ // XXX: There is no public string defining this intent so if Home changes the value, we
+ // have to update this string.
+ private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";
+
+ enum BookmarkIconType {
+ ICON_INSTALLABLE_WEB_APP, // Icon for an installable web app (launches WebAppRuntime).
+ ICON_HOME_SHORTCUT // Icon for a shortcut on the home screen (launches Browser).
+ };
+
+ /**
+ * Creates an icon to be associated with this bookmark. If available, the apple touch icon
+ * will be used, else we draw our own depending on the type of "bookmark" being created.
+ */
+ static Bitmap createIcon(Context context, Bitmap touchIcon, Bitmap favicon,
+ BookmarkIconType type) {
+ int iconDimension = context.getResources().getDimensionPixelSize(
+ android.R.dimen.app_icon_size);
+
+ Bitmap bm = Bitmap.createBitmap(iconDimension, iconDimension, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bm);
+ Rect iconBounds = new Rect(0, 0, bm.getWidth(), bm.getHeight());
+
+ // Use the apple-touch-icon if available
+ if (touchIcon != null) {
+ drawTouchIconToCanvas(touchIcon, canvas, iconBounds);
+ } else {
+ // No touch icon so create our own.
+ // Set the background based on the type of shortcut (either webapp or home shortcut).
+ Bitmap icon = getIconBackground(context, type);
+
+ if (icon != null) {
+ // Now draw the correct icon background into our new bitmap.
+ canvas.drawBitmap(icon, null, iconBounds, null);
+ }
+
+ // If we have a favicon, overlay it in a nice rounded white box on top of the
+ // background.
+ if (favicon != null) {
+ drawFaviconToCanvas(favicon, canvas, iconBounds,
+ context.getResources().getDisplayMetrics().density);
+ }
+ }
+ return bm;
+ }
+
+ /**
+ * Convenience method for creating an intent that will add a shortcut to the home screen.
+ */
+ static Intent createAddToHomeIntent(Context context, String url, String title,
+ Bitmap touchIcon, Bitmap favicon) {
+ Intent i = new Intent(INSTALL_SHORTCUT);
+ Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ long urlHash = url.hashCode();
+ long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
+ shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString(uniqueId));
+ i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
+ i.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(context, touchIcon, favicon,
+ BookmarkIconType.ICON_HOME_SHORTCUT));
+
+ // Do not allow duplicate items
+ i.putExtra("duplicate", false);
+ return i;
+ }
+
+ private static Bitmap getIconBackground(Context context, BookmarkIconType type) {
+ if (type == BookmarkIconType.ICON_HOME_SHORTCUT) {
+ // Want to create a shortcut icon on the homescreen, so the icon
+ // background is the red bookmark.
+ return BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.ic_launcher_shortcut_browser_bookmark);
+ } else if (type == BookmarkIconType.ICON_INSTALLABLE_WEB_APP) {
+ // Use the web browser icon as the background for the icon for an installable
+ // web app.
+ return BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.ic_launcher_browser);
+ }
+ return null;
+ }
+
+ private static void drawTouchIconToCanvas(Bitmap touchIcon, Canvas canvas, Rect iconBounds) {
+ Rect src = new Rect(0, 0, touchIcon.getWidth(), touchIcon.getHeight());
+
+ // Paint used for scaling the bitmap and drawing the rounded rect.
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setFilterBitmap(true);
+ canvas.drawBitmap(touchIcon, src, iconBounds, paint);
+
+ // Construct a path from a round rect. This will allow drawing with
+ // an inverse fill so we can punch a hole using the round rect.
+ Path path = new Path();
+ path.setFillType(Path.FillType.INVERSE_WINDING);
+ RectF rect = new RectF(iconBounds);
+ rect.inset(1, 1);
+ path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
+
+ // Reuse the paint and clear the outside of the rectangle.
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ canvas.drawPath(path, paint);
+ }
+
+ private static void drawFaviconToCanvas(Bitmap favicon, Canvas canvas, Rect iconBounds,
+ float density) {
+ // Make a Paint for the white background rectangle and for
+ // filtering the favicon.
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ p.setStyle(Paint.Style.FILL_AND_STROKE);
+ p.setColor(Color.WHITE);
+
+ // Create a rectangle that is slightly wider than the favicon
+ final float iconSize = 16 * density; // 16x16 favicon
+ final float padding = 2 * density; // white padding around icon
+ final float rectSize = iconSize + 2 * padding;
+ final float x = iconBounds.exactCenterX() - (rectSize / 2);
+ // Note: Subtract 2 dip from the y position since the box is
+ // slightly higher than center. Use padding since it is already
+ // 2 * density.
+ final float y = iconBounds.exactCenterY() - (rectSize / 2) - padding;
+ RectF r = new RectF(x, y, x + rectSize, y + rectSize);
+
+ // Draw a white rounded rectangle behind the favicon
+ canvas.drawRoundRect(r, 2, 2, p);
+
+ // Draw the favicon in the same rectangle as the rounded
+ // rectangle but inset by the padding
+ // (results in a 16x16 favicon).
+ r.inset(padding, padding);
+ canvas.drawBitmap(favicon, null, r, p);
+ }
+
+};
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 7560c78..320c438 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -74,10 +74,6 @@
private boolean mMostVisited;
private View mEmptyView;
private int mIconSize;
- // XXX: There is no public string defining this intent so if Home changes
- // the value, we have to update this string.
- private static final String INSTALL_SHORTCUT =
- "com.android.launcher.action.INSTALL_SHORTCUT";
private final static String LOGTAG = "browser";
private final static String PREF_BOOKMARK_VIEW_MODE = "pref_bookmark_view_mode";
@@ -108,9 +104,7 @@
editBookmark(i.position);
break;
case R.id.shortcut_context_menu_id:
- final Intent send = createShortcutIntent(i.position);
- send.setAction(INSTALL_SHORTCUT);
- sendBroadcast(send);
+ sendBroadcast(createShortcutIntent(i.position));
break;
case R.id.delete_context_menu_id:
if (mMostVisited) {
@@ -438,8 +432,7 @@
loadUrl(position);
}
} else {
- final Intent intent = createShortcutIntent(position);
- setResultToParent(RESULT_OK, intent);
+ setResultToParent(RESULT_OK, createShortcutIntent(position));
finish();
}
}
@@ -449,99 +442,8 @@
String url = getUrl(position);
String title = getBookmarkTitle(position);
Bitmap touchIcon = getTouchIcon(position);
-
- final Intent i = new Intent();
- final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(url));
- long urlHash = url.hashCode();
- long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
- shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID,
- Long.toString(uniqueId));
- i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
- i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
- // Use the apple-touch-icon if available
- if (touchIcon != null) {
- // Make a copy so we can modify the pixels. We can't use
- // createScaledBitmap or copy since they will preserve the config
- // and lose the ability to add alpha.
- Bitmap bm = Bitmap.createBitmap(mIconSize, mIconSize,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bm);
- Rect src = new Rect(0, 0, touchIcon.getWidth(),
- touchIcon.getHeight());
- Rect dest = new Rect(0, 0, bm.getWidth(), bm.getHeight());
-
- // Paint used for scaling the bitmap and drawing the rounded rect.
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setFilterBitmap(true);
- canvas.drawBitmap(touchIcon, src, dest, paint);
-
- // Construct a path from a round rect. This will allow drawing with
- // an inverse fill so we can punch a hole using the round rect.
- Path path = new Path();
- path.setFillType(Path.FillType.INVERSE_WINDING);
- RectF rect = new RectF(0, 0, bm.getWidth(), bm.getHeight());
- rect.inset(1, 1);
- path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
-
- // Reuse the paint and clear the outside of the rectangle.
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
- canvas.drawPath(path, paint);
-
- i.putExtra(Intent.EXTRA_SHORTCUT_ICON, bm);
- } else {
- Bitmap favicon = getFavicon(position);
- if (favicon == null) {
- i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
- Intent.ShortcutIconResource.fromContext(
- BrowserBookmarksPage.this,
- R.drawable.ic_launcher_shortcut_browser_bookmark));
- } else {
- Bitmap icon = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_launcher_shortcut_browser_bookmark_icon);
-
- // Make a copy of the regular icon so we can modify the pixels.
- Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true);
- Canvas canvas = new Canvas(copy);
-
- // Make a Paint for the white background rectangle and for
- // filtering the favicon.
- Paint p = new Paint(Paint.ANTI_ALIAS_FLAG
- | Paint.FILTER_BITMAP_FLAG);
- p.setStyle(Paint.Style.FILL_AND_STROKE);
- p.setColor(Color.WHITE);
-
- final float density =
- getResources().getDisplayMetrics().density;
- // Create a rectangle that is slightly wider than the favicon
- final float iconSize = 16 * density; // 16x16 favicon
- final float padding = 2 * density; // white padding around icon
- final float rectSize = iconSize + 2 * padding;
-
- final Rect iconBounds =
- new Rect(0, 0, icon.getWidth(), icon.getHeight());
- final float x = iconBounds.exactCenterX() - (rectSize / 2);
- // Note: Subtract 2 dip from the y position since the box is
- // slightly higher than center. Use padding since it is already
- // 2 * density.
- final float y = iconBounds.exactCenterY() - (rectSize / 2)
- - padding;
- RectF r = new RectF(x, y, x + rectSize, y + rectSize);
-
- // Draw a white rounded rectangle behind the favicon
- canvas.drawRoundRect(r, 2, 2, p);
-
- // Draw the favicon in the same rectangle as the rounded
- // rectangle but inset by the padding
- // (results in a 16x16 favicon).
- r.inset(padding, padding);
- canvas.drawBitmap(favicon, null, r, p);
- i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
- }
- }
- // Do not allow duplicate items
- i.putExtra("duplicate", false);
- return i;
+ Bitmap favicon = getFavicon(position);
+ return BookmarkUtils.createAddToHomeIntent(this, url, title, touchIcon, favicon);
}
private void saveCurrentPage() {