summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2011-02-01 12:57:06 -0800
committerJohn Reck <jreck@google.com>2011-02-04 13:37:17 -0800
commit99c6d333106cc0fb3c028b5f8d1ff1f5cf726ca2 (patch)
treef60a6aa9058be7028ef089b27e5c132545d0d96d
parent4daecf299171596ff8d1c2f1b845be810fd87fb1 (diff)
downloadpackages_apps_browser-99c6d333106cc0fb3c028b5f8d1ff1f5cf726ca2.zip
packages_apps_browser-99c6d333106cc0fb3c028b5f8d1ff1f5cf726ca2.tar.gz
packages_apps_browser-99c6d333106cc0fb3c028b5f8d1ff1f5cf726ca2.tar.bz2
Get the widget off of startservice
Bug: 3379120 Now with drastically lower memory usage as well! Change-Id: Iff16d2acceba3c8a983a51ec03a31a39ac6a12ed
-rw-r--r--AndroidManifest.xml3
-rw-r--r--res/layout/bookmarkthumbnailwidget_item.xml2
-rw-r--r--src/com/android/browser/AccountsChangedReceiver.java3
-rw-r--r--src/com/android/browser/preferences/GeneralPreferencesFragment.java2
-rw-r--r--src/com/android/browser/provider/BrowserProvider2.java25
-rw-r--r--src/com/android/browser/widget/BookmarkThumbnailWidgetProvider.java60
-rw-r--r--src/com/android/browser/widget/BookmarkThumbnailWidgetService.java501
-rw-r--r--src/com/android/browser/widget/BookmarkWidgetProxy.java53
8 files changed, 316 insertions, 333 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f88dfd9..c32b76a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -193,6 +193,9 @@
android:name=".widget.BookmarkThumbnailWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
+ <receiver
+ android:name=".widget.BookmarkWidgetProxy"
+ android:exported="false" />
<!-- Makes .BrowserActivity the search target for any activity in Browser -->
<meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" />
diff --git a/res/layout/bookmarkthumbnailwidget_item.xml b/res/layout/bookmarkthumbnailwidget_item.xml
index b67b386..3247806 100644
--- a/res/layout/bookmarkthumbnailwidget_item.xml
+++ b/res/layout/bookmarkthumbnailwidget_item.xml
@@ -21,7 +21,7 @@
android:layout_height="wrap_content">
<ImageView
android:id="@+id/thumb"
- android:src="@drawable/browser_thumbnail"
+ android:src="@drawable/thumbnail_bookmarks_widget_no_bookmark_holo"
android:layout_width="match_parent"
android:layout_height="@dimen/widgetThumbnailHeight"
android:scaleType="centerCrop"
diff --git a/src/com/android/browser/AccountsChangedReceiver.java b/src/com/android/browser/AccountsChangedReceiver.java
index 92d6ad0..a34180a 100644
--- a/src/com/android/browser/AccountsChangedReceiver.java
+++ b/src/com/android/browser/AccountsChangedReceiver.java
@@ -16,6 +16,8 @@
package com.android.browser;
+import com.android.browser.widget.BookmarkThumbnailWidgetProvider;
+
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.BroadcastReceiver;
@@ -55,6 +57,7 @@ public class AccountsChangedReceiver extends BroadcastReceiver {
ContentResolver.setSyncAutomatically(a, BrowserContract.AUTHORITY, false);
ContentResolver.setIsSyncable(a, BrowserContract.AUTHORITY, 0);
}
+ BookmarkThumbnailWidgetProvider.refreshWidgets(context, true);
}
}
diff --git a/src/com/android/browser/preferences/GeneralPreferencesFragment.java b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
index b6228dc..33bfd9c 100644
--- a/src/com/android/browser/preferences/GeneralPreferencesFragment.java
+++ b/src/com/android/browser/preferences/GeneralPreferencesFragment.java
@@ -21,6 +21,7 @@ import com.android.browser.BrowserHomepagePreference;
import com.android.browser.BrowserPreferencesPage;
import com.android.browser.BrowserSettings;
import com.android.browser.R;
+import com.android.browser.widget.BookmarkThumbnailWidgetProvider;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -125,6 +126,7 @@ public class GeneralPreferencesFragment extends PreferenceFragment
if (BrowserBookmarksPage.PREF_ACCOUNT_NAME.equals(key)
|| BrowserBookmarksPage.PREF_ACCOUNT_TYPE.equals(key)) {
refreshUi();
+ BookmarkThumbnailWidgetProvider.refreshWidgets(getActivity(), true);
}
}
diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
index a51635c..74cb773 100644
--- a/src/com/android/browser/provider/BrowserProvider2.java
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -19,6 +19,7 @@ package com.android.browser.provider;
import com.android.browser.BookmarkUtils;
import com.android.browser.BrowserBookmarksPage;
import com.android.browser.R;
+import com.android.browser.widget.BookmarkThumbnailWidgetProvider;
import com.android.common.content.SyncStateContentProviderHelper;
import android.accounts.Account;
@@ -35,6 +36,7 @@ import android.content.res.TypedArray;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -106,6 +108,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
static final int BOOKMARKS_FOLDER = 1002;
static final int BOOKMARKS_FOLDER_ID = 1003;
static final int BOOKMARKS_SUGGESTIONS = 1004;
+ static final int BOOKMARKS_DEFAULT_FOLDER_ID = 1005;
static final int HISTORY = 2000;
static final int HISTORY_ID = 2001;
@@ -159,6 +162,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
matcher.addURI(authority, "bookmarks/#", BOOKMARKS_ID);
matcher.addURI(authority, "bookmarks/folder", BOOKMARKS_FOLDER);
matcher.addURI(authority, "bookmarks/folder/#", BOOKMARKS_FOLDER_ID);
+ matcher.addURI(authority, "bookmarks/folder/id", BOOKMARKS_DEFAULT_FOLDER_ID);
matcher.addURI(authority,
SearchManager.SUGGEST_URI_PATH_QUERY,
BOOKMARKS_SUGGESTIONS);
@@ -758,6 +762,15 @@ public class BrowserProvider2 extends SQLiteContentProvider {
return cursor;
}
+ case BOOKMARKS_DEFAULT_FOLDER_ID: {
+ String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
+ String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
+ long id = queryDefaultFolderId(accountName, accountType);
+ MatrixCursor c = new MatrixCursor(new String[] {Bookmarks._ID});
+ c.newRow().add(id);
+ return c;
+ }
+
case BOOKMARKS_SUGGESTIONS: {
return doSuggestQuery(selection, selectionArgs, limit);
}
@@ -973,6 +986,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
selectionArgs = (String[]) withAccount[1];
int deleted = deleteBookmarks(selection, selectionArgs, callerIsSyncAdapter);
pruneImages();
+ if (deleted > 0) {
+ BookmarkThumbnailWidgetProvider.refreshWidgets(getContext());
+ }
return deleted;
}
@@ -1054,7 +1070,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
}
long queryDefaultFolderId(String accountName, String accountType) {
- if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
+ if (!isNullAccount(accountName) && !isNullAccount(accountType)) {
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = db.query(TABLE_BOOKMARKS, new String[] { Bookmarks._ID },
ChromeSyncColumns.SERVER_UNIQUE + " = ?" +
@@ -1134,6 +1150,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
}
id = db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.DIRTY, values);
+ BookmarkThumbnailWidgetProvider.refreshWidgets(getContext());
break;
}
@@ -1302,6 +1319,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
int updated = updateBookmarksInTransaction(values, selection, selectionArgs,
callerIsSyncAdapter);
pruneImages();
+ if (updated > 0) {
+ BookmarkThumbnailWidgetProvider.refreshWidgets(getContext());
+ }
return updated;
}
@@ -1342,6 +1362,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
db.insertOrThrow(TABLE_IMAGES, Images.FAVICON, values);
count = 1;
}
+ if (count > 0) {
+ BookmarkThumbnailWidgetProvider.refreshWidgets(getContext());
+ }
return count;
}
diff --git a/src/com/android/browser/widget/BookmarkThumbnailWidgetProvider.java b/src/com/android/browser/widget/BookmarkThumbnailWidgetProvider.java
index b991abd..48d7123 100644
--- a/src/com/android/browser/widget/BookmarkThumbnailWidgetProvider.java
+++ b/src/com/android/browser/widget/BookmarkThumbnailWidgetProvider.java
@@ -32,12 +32,9 @@ import android.widget.RemoteViews;
* Widget that shows a preview of the user's bookmarks.
*/
public class BookmarkThumbnailWidgetProvider extends AppWidgetProvider {
- static final String ACTION_BOOKMARK_APPWIDGET_UPDATE =
+ public static final String ACTION_BOOKMARK_APPWIDGET_UPDATE =
"com.android.browser.BOOKMARK_APPWIDGET_UPDATE";
- /**
- * {@inheritDoc}
- */
@Override
public void onReceive(Context context, Intent intent) {
// Handle bookmark-specific updates ourselves because they might be
@@ -58,23 +55,27 @@ public class BookmarkThumbnailWidgetProvider extends AppWidgetProvider {
}
@Override
- public void onEnabled(Context context) {
- // Start the backing service
- context.startService(new Intent(context, BookmarkThumbnailWidgetService.class));
+ public void onDeleted(Context context, int[] appWidgetIds) {
+ super.onDeleted(context, appWidgetIds);
+ for (int widgetId : appWidgetIds) {
+ BookmarkThumbnailWidgetService.deleteWidgetState(context, widgetId);
+ }
+ removeOrphanedFiles(context);
}
@Override
public void onDisabled(Context context) {
- // Stop the backing service
- context.stopService(new Intent(context, BookmarkThumbnailWidgetService.class));
+ super.onDisabled(context);
+ removeOrphanedFiles(context);
}
- @Override
- public void onDeleted(Context context, int[] appWidgetIds) {
- super.onDeleted(context, appWidgetIds);
- context.startService(new Intent(BookmarkThumbnailWidgetService.ACTION_REMOVE_FACTORIES,
- null, context, BookmarkThumbnailWidgetService.class)
- .putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds));
+ /**
+ * Checks for any state files that may have not received onDeleted
+ */
+ void removeOrphanedFiles(Context context) {
+ AppWidgetManager wm = AppWidgetManager.getInstance(context);
+ int[] ids = wm.getAppWidgetIds(getComponentName(context));
+ BookmarkThumbnailWidgetService.removeOrphanedStates(context, ids);
}
private void performUpdate(Context context,
@@ -92,9 +93,9 @@ public class BookmarkThumbnailWidgetProvider extends AppWidgetProvider {
views.setOnClickPendingIntent(R.id.app_shortcut, launchBrowser);
views.setRemoteAdapter(appWidgetId, R.id.bookmarks_list, updateIntent);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.bookmarks_list);
- Intent ic = new Intent(context, BookmarkThumbnailWidgetService.class);
+ Intent ic = new Intent(context, BookmarkWidgetProxy.class);
views.setPendingIntentTemplate(R.id.bookmarks_list,
- PendingIntent.getService(context, 0, ic,
+ PendingIntent.getBroadcast(context, 0, ic,
PendingIntent.FLAG_UPDATE_CURRENT));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@@ -107,4 +108,29 @@ public class BookmarkThumbnailWidgetProvider extends AppWidgetProvider {
static ComponentName getComponentName(Context context) {
return new ComponentName(context, BookmarkThumbnailWidgetProvider.class);
}
+
+ public static void refreshWidgets(Context context) {
+ refreshWidgets(context, false);
+ }
+
+ public static void refreshWidgets(Context context, boolean zeroState) {
+ if (zeroState) {
+ final Context appContext = context.getApplicationContext();
+ new Thread() {
+ @Override
+ public void run() {
+ AppWidgetManager wm = AppWidgetManager.getInstance(appContext);
+ int[] ids = wm.getAppWidgetIds(getComponentName(appContext));
+ for (int id : ids) {
+ BookmarkThumbnailWidgetService.clearWidgetState(appContext, id);
+ }
+ refreshWidgets(appContext, false);
+ }
+ }.start();
+ } else {
+ context.sendBroadcast(new Intent(
+ BookmarkThumbnailWidgetProvider.ACTION_BOOKMARK_APPWIDGET_UPDATE,
+ null, context, BookmarkThumbnailWidgetProvider.class));
+ }
+ }
}
diff --git a/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java b/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java
index e525159..675cdd9 100644
--- a/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java
+++ b/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java
@@ -16,8 +16,8 @@
package com.android.browser.widget;
+import com.android.browser.BookmarkUtils;
import com.android.browser.BrowserActivity;
-import com.android.browser.BrowserBookmarksPage;
import com.android.browser.R;
import android.appwidget.AppWidgetManager;
@@ -25,17 +25,14 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.database.ContentObserver;
import android.database.Cursor;
+import android.database.MergeCursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.preference.PreferenceManager;
+import android.os.Binder;
import android.provider.BrowserContract;
import android.provider.BrowserContract.Bookmarks;
import android.text.TextUtils;
@@ -43,185 +40,164 @@ import android.util.Log;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class BookmarkThumbnailWidgetService extends RemoteViewsService {
static final String TAG = "BookmarkThumbnailWidgetService";
- static final boolean USE_FOLDERS = true;
-
- static final String ACTION_REMOVE_FACTORIES
- = "com.android.browser.widget.REMOVE_FACTORIES";
static final String ACTION_CHANGE_FOLDER
= "com.android.browser.widget.CHANGE_FOLDER";
+ static final String STATE_CURRENT_FOLDER = "current_folder";
+ static final String STATE_ROOT_FOLDER = "root_folder";
+
private static final String[] PROJECTION = new String[] {
BrowserContract.Bookmarks._ID,
BrowserContract.Bookmarks.TITLE,
BrowserContract.Bookmarks.URL,
BrowserContract.Bookmarks.FAVICON,
BrowserContract.Bookmarks.IS_FOLDER,
- BrowserContract.Bookmarks.TOUCH_ICON,
BrowserContract.Bookmarks.POSITION, /* needed for order by */
- BrowserContract.Bookmarks.THUMBNAIL};
+ BrowserContract.Bookmarks.THUMBNAIL,
+ BrowserContract.Bookmarks.PARENT};
private static final int BOOKMARK_INDEX_ID = 0;
private static final int BOOKMARK_INDEX_TITLE = 1;
private static final int BOOKMARK_INDEX_URL = 2;
private static final int BOOKMARK_INDEX_FAVICON = 3;
private static final int BOOKMARK_INDEX_IS_FOLDER = 4;
- private static final int BOOKMARK_INDEX_TOUCH_ICON = 5;
- private static final int BOOKMARK_INDEX_THUMBNAIL = 7;
-
- // The service will likely be destroyed at any time, so we need to keep references to the
- // factories across services connections.
- private static final Map<Integer, BookmarkFactory> mFactories =
- new HashMap<Integer, BookmarkFactory>();
- private Handler mUiHandler;
- private BookmarksObserver mBookmarksObserver;
+ private static final int BOOKMARK_INDEX_THUMBNAIL = 6;
+ private static final int BOOKMARK_INDEX_PARENT_ID = 7;
@Override
- public void onCreate() {
- super.onCreate();
- mUiHandler = new Handler();
- mBookmarksObserver = new BookmarksObserver(mUiHandler);
- getContentResolver().registerContentObserver(
- BrowserContract.Bookmarks.CONTENT_URI, true, mBookmarksObserver);
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+ if (widgetId < 0) {
+ Log.w(TAG, "Missing EXTRA_APPWIDGET_ID!");
+ return null;
+ }
+ return new BookmarkFactory(getApplicationContext(), widgetId);
}
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- String action = intent.getAction();
- if (Intent.ACTION_VIEW.equals(action)) {
- if (intent.getData() == null) {
- startActivity(new Intent(BrowserActivity.ACTION_SHOW_BROWSER, null,
- this, BrowserActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- } else {
- Intent view = new Intent(intent);
- view.setComponent(null);
- startActivity(view);
- }
- } else if (ACTION_REMOVE_FACTORIES.equals(action)) {
- int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
- if (ids != null) {
- for (int id : ids) {
- BookmarkFactory bf = mFactories.remove(id);
- if (bf != null) {
- // Workaround a known framework bug
- // onDestroy is currently never called
- bf.onDestroy();
- }
- }
- }
- } else if (ACTION_CHANGE_FOLDER.equals(action)) {
- int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
- long folderId = intent.getLongExtra(Bookmarks._ID, -1);
- BookmarkFactory fac = mFactories.get(widgetId);
- if (fac != null && folderId >= 0) {
- fac.changeFolder(folderId);
- } else {
- // This a workaround to the issue when the Browser process crashes, after which
- // mFactories is not populated (due to onBind() not being called). Calling
- // notifyDataSetChanged() will trigger a connection to be made.
- AppWidgetManager.getInstance(getApplicationContext())
- .notifyAppWidgetViewDataChanged(widgetId, R.id.bookmarks_list);
- }
- }
- return START_STICKY;
+ static SharedPreferences getWidgetState(Context context, int widgetId) {
+ return context.getSharedPreferences(
+ String.format("widgetState-%d", widgetId),
+ Context.MODE_PRIVATE);
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- getContentResolver().unregisterContentObserver(mBookmarksObserver);
+ static void deleteWidgetState(Context context, int widgetId) {
+ File file = context.getSharedPrefsFile(
+ String.format("widgetState-%d", widgetId));
+ if (file.exists()) {
+ if (!file.delete()) {
+ file.deleteOnExit();
+ }
+ }
}
- private class BookmarksObserver extends ContentObserver {
- public BookmarksObserver(Handler handler) {
- super(handler);
+ static void changeFolder(Context context, Intent intent) {
+ int wid = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+ long fid = intent.getLongExtra(Bookmarks._ID, -1);
+ if (wid >= 0 && fid >= 0) {
+ SharedPreferences prefs = getWidgetState(context, wid);
+ prefs.edit().putLong(STATE_CURRENT_FOLDER, fid).commit();
+ AppWidgetManager.getInstance(context)
+ .notifyAppWidgetViewDataChanged(wid, R.id.bookmarks_list);
}
+ }
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
+ static void clearWidgetState(Context context, int widgetId) {
+ SharedPreferences pref = getWidgetState(context, widgetId);
+ pref.edit()
+ .remove(STATE_CURRENT_FOLDER)
+ .remove(STATE_ROOT_FOLDER)
+ .commit();
+ }
- // Update all the bookmark widgets
- if (mFactories != null) {
- for (BookmarkFactory fac : mFactories.values()) {
- fac.loadData();
- }
+ /**
+ * Checks for any state files that may have not received onDeleted
+ */
+ static void removeOrphanedStates(Context context, int[] widgetIds) {
+ File prefsDirectory = context.getSharedPrefsFile("null").getParentFile();
+ File[] widgetStates = prefsDirectory.listFiles(new StateFilter(widgetIds));
+ for (File f : widgetStates) {
+ Log.w(TAG, "Found orphaned state: " + f.getName());
+ if (!f.delete()) {
+ f.deleteOnExit();
}
}
}
- @Override
- public RemoteViewsFactory onGetViewFactory(Intent intent) {
- int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
- if (widgetId < 0) {
- Log.w(TAG, "Missing EXTRA_APPWIDGET_ID!");
- return null;
- } else {
- BookmarkFactory fac = mFactories.get(widgetId);
- if (fac == null) {
- fac = new BookmarkFactory(getApplicationContext(), widgetId);
+ static class StateFilter implements FilenameFilter {
+
+ static final Pattern sStatePattern = Pattern.compile("widgetState-(\\d+)\\.xml");
+ HashSet<Integer> mWidgetIds;
+
+ StateFilter(int[] ids) {
+ mWidgetIds = new HashSet<Integer>();
+ for (int id : ids) {
+ mWidgetIds.add(id);
}
- mFactories.put(widgetId, fac);
- return fac;
}
- }
- private static class Breadcrumb {
- long mId;
- String mTitle;
- public Breadcrumb(long id, String title) {
- mId = id;
- mTitle = title;
+ @Override
+ public boolean accept(File dir, String filename) {
+ Matcher m = sStatePattern.matcher(filename);
+ if (m.matches()) {
+ int id = Integer.parseInt(m.group(1));
+ if (!mWidgetIds.contains(id)) {
+ return true;
+ }
+ }
+ return false;
}
+
}
- static class BookmarkFactory implements RemoteViewsService.RemoteViewsFactory,
- OnSharedPreferenceChangeListener {
- private List<RenderResult> mBookmarks;
+ static class BookmarkFactory implements RemoteViewsService.RemoteViewsFactory {
+ private Cursor mBookmarks;
private Context mContext;
private int mWidgetId;
- private String mAccountType;
- private String mAccountName;
- private Stack<Breadcrumb> mBreadcrumbs;
- private LoadBookmarksTask mLoadTask;
+ private long mCurrentFolder = -1;
+ private long mRootFolder = -1;
+ private SharedPreferences mPreferences = null;
public BookmarkFactory(Context context, int widgetId) {
- mBreadcrumbs = new Stack<Breadcrumb>();
mContext = context;
mWidgetId = widgetId;
}
- void changeFolder(long folderId) {
- if (mBookmarks == null) return;
-
- if (!mBreadcrumbs.empty() && mBreadcrumbs.peek().mId == folderId) {
- mBreadcrumbs.pop();
- loadData();
- return;
+ void syncState() {
+ if (mPreferences == null) {
+ mPreferences = getWidgetState(mContext, mWidgetId);
+ }
+ long currentFolder = mPreferences.getLong(STATE_CURRENT_FOLDER, -1);
+ mRootFolder = mPreferences.getLong(STATE_ROOT_FOLDER, -1);
+ if (currentFolder != mCurrentFolder) {
+ resetBookmarks();
+ mCurrentFolder = currentFolder;
}
+ }
- for (RenderResult res : mBookmarks) {
- if (res.mId == folderId) {
- mBreadcrumbs.push(new Breadcrumb(res.mId, res.mTitle));
- loadData();
- break;
- }
+ void saveState() {
+ if (mPreferences == null) {
+ mPreferences = getWidgetState(mContext, mWidgetId);
}
+ mPreferences.edit()
+ .putLong(STATE_CURRENT_FOLDER, mCurrentFolder)
+ .putLong(STATE_ROOT_FOLDER, mRootFolder)
+ .commit();
}
@Override
public int getCount() {
if (mBookmarks == null)
return 0;
- return mBookmarks.size();
+ return mBookmarks.getCount();
}
@Override
@@ -231,44 +207,33 @@ public class BookmarkThumbnailWidgetService extends RemoteViewsService {
@Override
public RemoteViews getLoadingView() {
- return null;
+ return new RemoteViews(
+ mContext.getPackageName(), R.layout.bookmarkthumbnailwidget_item);
}
@Override
public RemoteViews getViewAt(int position) {
- if (position < 0 || position >= getCount()) {
+ if (!mBookmarks.moveToPosition(position)) {
return null;
}
- RenderResult res = mBookmarks.get(position);
- Breadcrumb folder = mBreadcrumbs.empty() ? null : mBreadcrumbs.peek();
+ long id = mBookmarks.getLong(BOOKMARK_INDEX_ID);
+ String title = mBookmarks.getString(BOOKMARK_INDEX_TITLE);
+ String url = mBookmarks.getString(BOOKMARK_INDEX_URL);
+ boolean isFolder = mBookmarks.getInt(BOOKMARK_INDEX_IS_FOLDER) != 0;
RemoteViews views = new RemoteViews(
mContext.getPackageName(), R.layout.bookmarkthumbnailwidget_item);
- Intent fillin;
- if (res.mIsFolder) {
- long nfi = res.mId;
- fillin = new Intent(ACTION_CHANGE_FOLDER, null,
- mContext, BookmarkThumbnailWidgetService.class)
- .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId)
- .putExtra(Bookmarks._ID, nfi);
- } else {
- fillin = new Intent(Intent.ACTION_VIEW)
- .addCategory(Intent.CATEGORY_BROWSABLE);
- if (!TextUtils.isEmpty(res.mUrl)) {
- fillin.setData(Uri.parse(res.mUrl));
- }
- }
- views.setOnClickFillInIntent(R.id.list_item, fillin);
// Set the title of the bookmark. Use the url as a backup.
- String displayTitle = res.mTitle;
+ String displayTitle = title;
if (TextUtils.isEmpty(displayTitle)) {
// The browser always requires a title for bookmarks, but jic...
- displayTitle = res.mUrl;
+ displayTitle = url;
}
views.setTextViewText(R.id.label, displayTitle);
- if (res.mIsFolder) {
- if (folder != null && res.mId == folder.mId) {
+ if (isFolder) {
+ if (id == mCurrentFolder) {
+ id = mBookmarks.getLong(BOOKMARK_INDEX_PARENT_ID);
views.setImageViewResource(R.id.thumb, R.drawable.thumb_bookmark_widget_folder_back_holo);
} else {
views.setImageViewResource(R.id.thumb, R.drawable.thumb_bookmark_widget_folder_holo);
@@ -276,20 +241,45 @@ public class BookmarkThumbnailWidgetService extends RemoteViewsService {
views.setImageViewResource(R.id.favicon, R.drawable.ic_bookmark_widget_bookmark_holo_dark);
views.setDrawableParameters(R.id.thumb, true, 0, -1, null, -1);
} else {
+ // RemoteViews require a valid bitmap config
+ Options options = new Options();
+ options.inPreferredConfig = Config.ARGB_8888;
+ Bitmap thumbnail = null, favicon = null;
+ byte[] blob = mBookmarks.getBlob(BOOKMARK_INDEX_THUMBNAIL);
views.setDrawableParameters(R.id.thumb, true, 255, -1, null, -1);
- if (res.mThumbnail != null) {
- views.setImageViewBitmap(R.id.thumb, res.mThumbnail);
+ if (blob != null && blob.length > 0) {
+ thumbnail = BitmapFactory.decodeByteArray(
+ blob, 0, blob.length, options);
+ views.setImageViewBitmap(R.id.thumb, thumbnail);
} else {
views.setImageViewResource(R.id.thumb,
R.drawable.browser_thumbnail);
}
- if (res.mIcon != null) {
- views.setImageViewBitmap(R.id.favicon, res.mIcon);
+ blob = mBookmarks.getBlob(BOOKMARK_INDEX_FAVICON);
+ if (blob != null && blob.length > 0) {
+ favicon = BitmapFactory.decodeByteArray(
+ blob, 0, blob.length, options);
+ views.setImageViewBitmap(R.id.favicon, favicon);
} else {
views.setImageViewResource(R.id.favicon,
R.drawable.app_web_browser_sm);
}
}
+ Intent fillin;
+ if (isFolder) {
+ fillin = new Intent(ACTION_CHANGE_FOLDER)
+ .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId)
+ .putExtra(Bookmarks._ID, id);
+ } else {
+ if (!TextUtils.isEmpty(url)) {
+ fillin = new Intent(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.parse(url));
+ } else {
+ fillin = new Intent(BrowserActivity.ACTION_SHOW_BROWSER);
+ }
+ }
+ views.setOnClickFillInIntent(R.id.list_item, fillin);
return views;
}
@@ -305,187 +295,70 @@ public class BookmarkThumbnailWidgetService extends RemoteViewsService {
@Override
public void onCreate() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- mAccountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
- mAccountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
- prefs.registerOnSharedPreferenceChangeListener(this);
- loadData();
}
@Override
public void onDestroy() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
- prefs.unregisterOnSharedPreferenceChangeListener(this);
-
- // Workaround known framework bug
- // This class currently leaks, so free as much memory as we can
- recycleBitmaps();
- mBookmarks.clear();
- mBreadcrumbs.clear();
- if (mLoadTask != null) {
- mLoadTask.cancel(false);
- mLoadTask = null;
+ if (mBookmarks != null) {
+ mBookmarks.close();
+ mBookmarks = null;
}
+ deleteWidgetState(mContext, mWidgetId);
}
@Override
public void onDataSetChanged() {
- }
-
- void loadData() {
- if (mLoadTask != null) {
- mLoadTask.cancel(false);
+ long token = Binder.clearCallingIdentity();
+ syncState();
+ if (mRootFolder < 0 || mCurrentFolder < 0) {
+ // Our state has been zero'd, reset (account change most likely)
+ mRootFolder = getRootFolder();
+ mCurrentFolder = mRootFolder;
+ saveState();
}
- mLoadTask = new LoadBookmarksTask();
- mLoadTask.execute();
+ loadBookmarks();
+ Binder.restoreCallingIdentity(token);
}
- class LoadBookmarksTask extends AsyncTask<Void, Void, List<RenderResult>> {
- private Breadcrumb mFolder;
-
- @Override
- protected void onPreExecute() {
- mFolder = mBreadcrumbs.empty() ? null : mBreadcrumbs.peek();
- }
-
- @Override
- protected List<RenderResult> doInBackground(Void... params) {
- return loadBookmarks(mFolder);
- }
-
- @Override
- protected void onPostExecute(List<RenderResult> result) {
- if (!isCancelled() && result != null) {
- recycleBitmaps();
- mBookmarks = result;
- AppWidgetManager.getInstance(mContext)
- .notifyAppWidgetViewDataChanged(mWidgetId, R.id.bookmarks_list);
- }
+ private void resetBookmarks() {
+ if (mBookmarks != null) {
+ mBookmarks.close();
+ mBookmarks = null;
}
}
- List<RenderResult> loadBookmarks(Breadcrumb folder) {
- String where = null;
- Uri uri;
- if (USE_FOLDERS) {
- uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER;
- if (folder != null) {
- uri = ContentUris.withAppendedId(uri, folder.mId);
- }
- } else {
- uri = BrowserContract.Bookmarks.CONTENT_URI;
- where = Bookmarks.IS_FOLDER + " == 0";
- }
- uri = uri.buildUpon()
- .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, mAccountType)
- .appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, mAccountName)
- .build();
- Cursor c = null;
+ long getRootFolder() {
+ Uri uri = Uri.withAppendedPath(
+ BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, "id");
+ uri = BookmarkUtils.addAccountInfo(mContext, uri.buildUpon()).build();
+ Cursor c = mContext.getContentResolver().query(
+ uri, null, null, null, null);
try {
- c = mContext.getContentResolver().query(uri, PROJECTION,
- where, null, null);
- if (c != null) {
- ArrayList<RenderResult> bookmarks
- = new ArrayList<RenderResult>(c.getCount() + 1);
- if (folder != null) {
- RenderResult res = new RenderResult(
- folder.mId, folder.mTitle, null);
- res.mIsFolder = true;
- bookmarks.add(res);
- }
- while (c.moveToNext()) {
- long id = c.getLong(BOOKMARK_INDEX_ID);
- String title = c.getString(BOOKMARK_INDEX_TITLE);
- String url = c.getString(BOOKMARK_INDEX_URL);
- RenderResult res = new RenderResult(id, title, url);
- res.mIsFolder = c.getInt(BOOKMARK_INDEX_IS_FOLDER) != 0;
- if (!res.mIsFolder) {
- // RemoteViews require a valid bitmap config
- Options options = new Options();
- options.inPreferredConfig = Config.ARGB_8888;
- Bitmap thumbnail = null, favicon = null;
- byte[] blob = c.getBlob(BOOKMARK_INDEX_THUMBNAIL);
- if (blob != null && blob.length > 0) {
- thumbnail = BitmapFactory.decodeByteArray(
- blob, 0, blob.length, options);
- }
- blob = c.getBlob(BOOKMARK_INDEX_FAVICON);
- if (blob != null && blob.length > 0) {
- favicon = BitmapFactory.decodeByteArray(
- blob, 0, blob.length, options);
- }
- res.mThumbnail = thumbnail;
- res.mIcon = favicon;
- }
- bookmarks.add(res);
- }
- if (bookmarks.size() == 0) {
- RenderResult res = new RenderResult(0, "", "");
- Bitmap thumbnail = BitmapFactory.decodeResource(
- mContext.getResources(),
- R.drawable.thumbnail_bookmarks_widget_no_bookmark_holo);
- Bitmap favicon = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
- res.mThumbnail = thumbnail;
- res.mIcon = favicon;
- for (int i = 0; i < 6; i++) {
- bookmarks.add(res);
- }
- }
- return bookmarks;
- }
- } catch (IllegalStateException e) {
- Log.e(TAG, "update bookmark widget", e);
+ c.moveToFirst();
+ return c.getLong(0);
} finally {
- if (c != null) {
- c.close();
- }
+ c.close();
}
- return null;
}
- private void recycleBitmaps() {
- // Do a bit of house cleaning for the system
- if (mBookmarks != null) {
- for (RenderResult res : mBookmarks) {
- if (res.mThumbnail != null) {
- res.mThumbnail.recycle();
- res.mThumbnail = null;
- }
- }
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(
- SharedPreferences prefs, String key) {
- if (BrowserBookmarksPage.PREF_ACCOUNT_TYPE.equals(key)) {
- mAccountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
- mBreadcrumbs.clear();
- loadData();
- }
- if (BrowserBookmarksPage.PREF_ACCOUNT_NAME.equals(key)) {
- mAccountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
- mBreadcrumbs.clear();
- loadData();
+ void loadBookmarks() {
+ resetBookmarks();
+
+ Uri uri = ContentUris.withAppendedId(
+ BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER,
+ mCurrentFolder);
+ uri = BookmarkUtils.addAccountInfo(mContext, uri.buildUpon()).build();
+ mBookmarks = mContext.getContentResolver().query(uri, PROJECTION,
+ null, null, null);
+ if (mCurrentFolder != mRootFolder) {
+ uri = ContentUris.withAppendedId(
+ BrowserContract.Bookmarks.CONTENT_URI,
+ mCurrentFolder);
+ Cursor c = mContext.getContentResolver().query(uri, PROJECTION,
+ null, null, null);
+ mBookmarks = new MergeCursor(new Cursor[] { c, mBookmarks });
}
}
}
- // Class containing the rendering information for a specific bookmark.
- private static class RenderResult {
- final String mTitle;
- final String mUrl;
- Bitmap mThumbnail;
- Bitmap mIcon;
- boolean mIsFolder;
- long mId;
-
- RenderResult(long id, String title, String url) {
- mId = id;
- mTitle = title;
- mUrl = url;
- }
-
- }
-
}
diff --git a/src/com/android/browser/widget/BookmarkWidgetProxy.java b/src/com/android/browser/widget/BookmarkWidgetProxy.java
new file mode 100644
index 0000000..8ab57fc
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkWidgetProxy.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 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.widget;
+
+import com.android.browser.BrowserActivity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class BookmarkWidgetProxy extends BroadcastReceiver {
+
+ private static final String TAG = "BookmarkWidgetProxy";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (BookmarkThumbnailWidgetService.ACTION_CHANGE_FOLDER.equals(intent.getAction())) {
+ BookmarkThumbnailWidgetService.changeFolder(context, intent);
+ } else if (BrowserActivity.ACTION_SHOW_BROWSER.equals(intent.getAction())) {
+ startActivity(context,
+ new Intent(BrowserActivity.ACTION_SHOW_BROWSER,
+ null, context, BrowserActivity.class));
+ } else {
+ Intent view = new Intent(intent);
+ view.setComponent(null);
+ startActivity(context, view);
+ }
+ }
+
+ void startActivity(Context context, Intent intent) {
+ try {
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to start intent activity", e);
+ }
+ }
+}