From 87e308ca2ddb425b96653fefdd625374255fa8ed Mon Sep 17 00:00:00 2001 From: Wesley Johnston Date: Fri, 1 Jul 2011 14:26:00 -0400 Subject: [PATCH] Bug 667530 - Add ability to add application/bookmark shortcuts to Launcher screens [r=blassey, r=fabrice] --- embedding/android/AndroidManifest.xml.in | 10 + embedding/android/GeckoApp.java | 2 +- embedding/android/GeckoAppShell.java | 2 +- embedding/android/LauncherShortcuts.java.in | 184 ++++++++++++++++++ embedding/android/Makefile.in | 3 + .../android/locales/en-US/android_strings.dtd | 3 + .../resources/layout/launch_app_list.xml | 20 ++ .../resources/layout/launch_app_listitem.xml | 17 ++ embedding/android/strings.xml.in | 3 + 9 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 embedding/android/LauncherShortcuts.java.in create mode 100644 embedding/android/resources/layout/launch_app_list.xml create mode 100644 embedding/android/resources/layout/launch_app_listitem.xml diff --git a/embedding/android/AndroidManifest.xml.in b/embedding/android/AndroidManifest.xml.in index aa463b6f2ca3..1768d05d236d 100644 --- a/embedding/android/AndroidManifest.xml.in +++ b/embedding/android/AndroidManifest.xml.in @@ -89,6 +89,7 @@ + #if MOZ_CRASHREPORTER #endif + + + + + + + + diff --git a/embedding/android/GeckoApp.java b/embedding/android/GeckoApp.java index f4a3a059c4c9..8a851640f60f 100644 --- a/embedding/android/GeckoApp.java +++ b/embedding/android/GeckoApp.java @@ -303,7 +303,7 @@ abstract public class GeckoApp Log.i("GeckoApp", "Intent : ACTION_MAIN"); GeckoAppShell.sendEventToGecko(new GeckoEvent("")); } - else if (action.equals("org.mozilla.fennec.WEBAPP")) { + else if (action.equals("org.mozilla.gecko.WEBAPP")) { String uri = intent.getStringExtra("args"); GeckoAppShell.sendEventToGecko(new GeckoEvent(uri)); Log.i("GeckoApp","Intent : WEBAPP - " + uri); diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index d595b2f9ba55..76a150fd4ea0 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -678,7 +678,7 @@ public class GeckoAppShell Log.w("GeckoAppJava", "installWebApplication for " + aURI + " [" + aTitle + "]"); // the intent to be launched by the shortcut - Intent shortcutIntent = new Intent("org.mozilla.fennec.WEBAPP"); + Intent shortcutIntent = new Intent("org.mozilla.gecko.WEBAPP"); shortcutIntent.setClassName(GeckoApp.mAppContext, GeckoApp.mAppContext.getPackageName() + ".App"); shortcutIntent.putExtra("args", "--webapp=" + aURI); diff --git a/embedding/android/LauncherShortcuts.java.in b/embedding/android/LauncherShortcuts.java.in new file mode 100644 index 000000000000..32a4507237c9 --- /dev/null +++ b/embedding/android/LauncherShortcuts.java.in @@ -0,0 +1,184 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Android code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic + * Wes Johnston + * Mark Finkle + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#filter substitution +package @ANDROID_PACKAGE_NAME@; + +import java.io.*; + +import org.mozilla.gecko.*; + +import android.os.*; +import android.content.*; +import android.app.*; +import android.text.*; +import android.util.*; +import android.widget.*; +import android.database.sqlite.*; +import android.database.*; +import android.view.*; +import android.net.Uri; +import android.graphics.*; + + +public class LauncherShortcuts extends ListActivity { + public static final String CREATE_SHORTCUT = "org.mozilla.gecko.CREATE_SHORTCUT"; + + public class LauncherCursorAdapter extends SimpleCursorAdapter { + private Cursor _cursor; + private Context _context; + + public LauncherCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { + // Using the older, deprecated constructor so we can work on API < 11 + super(context, layout, c, from, to); + _cursor = c; + _context = context; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ImageView imageView = (ImageView) view.findViewById(R.id.favicon); + + String favicon = cursor.getString(3); + byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT); + Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), 48, 48, true); + imageView.setImageBitmap(bitmap); + + super.bindView(view, context, cursor); + } + } + + private Cursor getCursor(Context context) { + File home = new File(context.getFilesDir(), "mozilla"); + if (!home.exists()) + return null; + + File profile = null; + String[] files = home.list(); + for (int i = 0; i < files.length; i++) { + if (files[i].endsWith(".default")) { + profile = new File(home, files[i]); + break; + } + } + + if (profile == null) + return null; + + File webapps = new File(profile, "webapps.sqlite"); + if (!webapps.exists()) + return null; + + Log.i("LauncherShortcuts", "Opening: " + webapps.getPath()); + mDb = SQLiteDatabase.openDatabase(webapps.getPath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); + return mDb.rawQuery("SELECT rowid as _id, title, uri, icon FROM webapps", null); + } + + private Cursor mCursor; + private SQLiteDatabase mDb; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.launch_app_list); + + final Intent intent = getIntent(); + final String action = intent.getAction(); + + if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) { + mCursor = getCursor(this); + if (mCursor != null) { + // After selecting an item, the empty view can flash on screen. Clear + // the text so we don't see it. + TextView emptyText = (TextView)findViewById(android.R.id.empty); + emptyText.setText(""); + + // Load the list using a custom adapter so we can create the bitmaps + ListAdapter adapter = new LauncherCursorAdapter( + this, + R.layout.launch_app_listitem, + mCursor, + new String[] {"title"}, + new int[] {R.id.title} + ); + setListAdapter(adapter); + } + } + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + mCursor.moveToPosition(position); + + Intent shortcutintent = new Intent("org.mozilla.gecko.WEBAPP"); + shortcutintent.setClass(this, App.class); + shortcutintent.putExtra("args", "--webapp=" + mCursor.getString(2)); + + Intent intent = new Intent(); + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, mCursor.getString(1)); + intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent); + + String favicon = mCursor.getString(3); + byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT); + + DisplayMetrics dm = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(dm); + int size; + switch (dm.densityDpi) { + case DisplayMetrics.DENSITY_MEDIUM: + size = 48; + break; + case DisplayMetrics.DENSITY_HIGH: + size = 72; + break; + default: + size = 72; + } + + Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), size, size, true); + intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap); + + // Now, return the result to the launcher + setResult(RESULT_OK, intent); + mDb.close(); + mCursor.close(); + finish(); + } +} diff --git a/embedding/android/Makefile.in b/embedding/android/Makefile.in index a1ddc8fb19c4..136ceb0c471e 100644 --- a/embedding/android/Makefile.in +++ b/embedding/android/Makefile.in @@ -59,6 +59,7 @@ PROCESSEDJAVAFILES = \ App.java \ Restarter.java \ NotificationHandler.java \ + LauncherShortcuts.java \ $(NULL) @@ -116,6 +117,8 @@ RES_LAYOUT = \ res/layout/notification_progress.xml \ res/layout/notification_progress_text.xml \ res/layout/notification_icon_text.xml \ + res/layout/launch_app_list.xml \ + res/layout/launch_app_listitem.xml \ $(NULL) RES_VALUES = res/values/colors.xml res/values/themes.xml diff --git a/embedding/android/locales/en-US/android_strings.dtd b/embedding/android/locales/en-US/android_strings.dtd index eb4e791333f4..fe9f51c4d10e 100644 --- a/embedding/android/locales/en-US/android_strings.dtd +++ b/embedding/android/locales/en-US/android_strings.dtd @@ -16,3 +16,6 @@ + + + diff --git a/embedding/android/resources/layout/launch_app_list.xml b/embedding/android/resources/layout/launch_app_list.xml new file mode 100644 index 000000000000..66302158352f --- /dev/null +++ b/embedding/android/resources/layout/launch_app_list.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/embedding/android/resources/layout/launch_app_listitem.xml b/embedding/android/resources/layout/launch_app_listitem.xml new file mode 100644 index 000000000000..7821d696e3bc --- /dev/null +++ b/embedding/android/resources/layout/launch_app_listitem.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/embedding/android/strings.xml.in b/embedding/android/strings.xml.in index c59c0fbcab2f..e3bd5780377f 100644 --- a/embedding/android/strings.xml.in +++ b/embedding/android/strings.xml.in @@ -21,4 +21,7 @@ &sending_crash_report; &exit_label; &continue_label; + + &launcher_shortcuts_title; + &launcher_shortcuts_empty;