BrowserBookmarksPage.java revision 052ce667ce77c4fb3208c0b0dacba7be79c072d9
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.browser; 18 19import android.app.Activity; 20import android.app.AlertDialog; 21import android.app.Fragment; 22import android.app.LoaderManager; 23import android.content.ClipData; 24import android.content.ClipboardManager; 25import android.content.ContentResolver; 26import android.content.ContentUris; 27import android.content.ContentValues; 28import android.content.Context; 29import android.content.CursorLoader; 30import android.content.DialogInterface; 31import android.content.Intent; 32import android.content.Loader; 33import android.content.SharedPreferences; 34import android.database.Cursor; 35import android.graphics.Bitmap; 36import android.graphics.BitmapFactory; 37import android.net.Uri; 38import android.os.Bundle; 39import android.preference.PreferenceManager; 40import android.provider.BrowserContract; 41import android.provider.BrowserContract.Accounts; 42import android.text.TextUtils; 43import android.util.Pair; 44import android.view.ContextMenu; 45import android.view.ContextMenu.ContextMenuInfo; 46import android.view.LayoutInflater; 47import android.view.MenuInflater; 48import android.view.MenuItem; 49import android.view.View; 50import android.view.View.OnClickListener; 51import android.view.ViewGroup; 52import android.webkit.WebIconDatabase.IconListener; 53import android.widget.Adapter; 54import android.widget.AdapterView; 55import android.widget.AdapterView.OnItemClickListener; 56import android.widget.AdapterView.OnItemSelectedListener; 57import android.widget.ArrayAdapter; 58import android.widget.Button; 59import android.widget.GridView; 60import android.widget.Spinner; 61import android.widget.Toast; 62 63import java.util.ArrayList; 64import java.util.Stack; 65 66/** 67 * View showing the user's bookmarks in the browser. 68 */ 69public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener, 70 LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener, IconListener, OnClickListener, 71 OnItemSelectedListener { 72 73 static final int BOOKMARKS_SAVE = 1; 74 static final String LOGTAG = "browser"; 75 76 static final int LOADER_BOOKMARKS = 1; 77 static final int LOADER_ACCOUNTS = 2; 78 static final int LOADER_ACCOUNTS_THEN_BOOKMARKS = 3; 79 80 static final String EXTRA_SHORTCUT = "create_shortcut"; 81 static final String EXTRA_DISABLE_WINDOW = "disable_new_window"; 82 83 static final String ACCOUNT_NAME_UNSYNCED = "Unsynced"; 84 85 public static final String PREF_ACCOUNT_TYPE = "acct_type"; 86 public static final String PREF_ACCOUNT_NAME = "acct_name"; 87 88 static final String DEFAULT_ACCOUNT = "local"; 89 90 BookmarksHistoryCallbacks mCallbacks; 91 GridView mGrid; 92 Spinner mAccountSelector; 93 BrowserBookmarksAdapter mAdapter; 94 boolean mDisableNewWindow; 95 BookmarkItem mContextHeader; 96 boolean mCanceled = false; 97 boolean mCreateShortcut; 98 View mEmptyView; 99 View mContentView; 100 Stack<Pair<String, Uri>> mFolderStack = new Stack<Pair<String, Uri>>(); 101 Button mUpButton; 102 103 @Override 104 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 105 switch (id) { 106 case LOADER_BOOKMARKS: { 107 String accountType = null; 108 String accountName = null; 109 if (args != null) { 110 accountType = args.getString(BookmarksLoader.ARG_ACCOUNT_TYPE); 111 accountName = args.getString(BookmarksLoader.ARG_ACCOUNT_NAME); 112 } 113 return new BookmarksLoader(getActivity(), accountType, accountName); 114 } 115 116 case LOADER_ACCOUNTS: 117 case LOADER_ACCOUNTS_THEN_BOOKMARKS: { 118 return new CursorLoader(getActivity(), Accounts.CONTENT_URI, 119 new String[] { Accounts.ACCOUNT_TYPE, Accounts.ACCOUNT_NAME }, null, null, 120 null); 121 } 122 } 123 throw new UnsupportedOperationException("Unknown loader id " + id); 124 } 125 126 @Override 127 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 128 switch (loader.getId()) { 129 case LOADER_BOOKMARKS: { 130 // Set the visibility of the empty vs. content views 131 if (cursor == null || cursor.getCount() == 0) { 132 mEmptyView.setVisibility(View.VISIBLE); 133 mGrid.setVisibility(View.GONE); 134 } else { 135 mEmptyView.setVisibility(View.GONE); 136 mGrid.setVisibility(View.VISIBLE); 137 } 138 139 // Fill in the "up" button if needed 140 BookmarksLoader bl = (BookmarksLoader) loader; 141 String path = bl.getUri().getPath(); 142 boolean rootFolder = 143 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER.getPath().equals(path); 144 if (rootFolder) { 145 mUpButton.setText(R.string.defaultBookmarksUpButton); 146 mUpButton.setEnabled(false); 147 } else { 148 mUpButton.setText(mFolderStack.peek().first); 149 mUpButton.setEnabled(true); 150 } 151 mUpButton.setVisibility(View.VISIBLE); 152 153 // Give the new data to the adapter 154 mAdapter.changeCursor(cursor); 155 156 break; 157 } 158 159 case LOADER_ACCOUNTS: 160 case LOADER_ACCOUNTS_THEN_BOOKMARKS: { 161 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( 162 getActivity()); 163 String storedAccountType = prefs.getString(PREF_ACCOUNT_TYPE, null); 164 String storedAccountName = prefs.getString(PREF_ACCOUNT_NAME, null); 165 String accountType = 166 TextUtils.isEmpty(storedAccountType) ? DEFAULT_ACCOUNT : storedAccountType; 167 String accountName = 168 TextUtils.isEmpty(storedAccountName) ? DEFAULT_ACCOUNT : storedAccountName; 169 170 Bundle args = null; 171 if (cursor == null || !cursor.moveToFirst()) { 172 // No accounts, set the prefs to the default 173 accountType = DEFAULT_ACCOUNT; 174 accountName = DEFAULT_ACCOUNT; 175 mAccountSelector.setVisibility(View.GONE); 176 } else { 177 int accountPosition = -1; 178 179 if (!DEFAULT_ACCOUNT.equals(accountType) && 180 !DEFAULT_ACCOUNT.equals(accountName)) { 181 // Check to see if the account in prefs still exists 182 cursor.moveToFirst(); 183 do { 184 if (accountType.equals(cursor.getString(0)) 185 && accountName.equals(cursor.getString(1))) { 186 accountPosition = cursor.getPosition(); 187 break; 188 } 189 } while (cursor.moveToNext()); 190 } 191 192 if (accountPosition == -1) { 193 if ((DEFAULT_ACCOUNT.equals(accountType) 194 && DEFAULT_ACCOUNT.equals(accountName))) { 195 // The "unsynced" account is selected 196 accountPosition = cursor.getCount(); 197 } else { 198 // No account is set in prefs and there is at least one, 199 // so pick the first one as the default 200 cursor.moveToFirst(); 201 accountType = cursor.getString(0); 202 accountName = cursor.getString(1); 203 accountPosition = 0; 204 } 205 } 206 207 args = new Bundle(); 208 args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType); 209 args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName); 210 211 // Add in the sync accounts 212 ArrayList<String> accounts = new ArrayList<String>(); 213 cursor.moveToFirst(); 214 do { 215 accounts.add(cursor.getString(1)); 216 } while (cursor.moveToNext()); 217 218 // STOPSHIP: Add in the "unsynced" account temporarily until we 219 // have support for migrated unsynced bookmarks into sync accounts. 220 accounts.add(ACCOUNT_NAME_UNSYNCED); 221 222 mAccountSelector.setAdapter(new ArrayAdapter<String>(getActivity(), 223 android.R.layout.simple_list_item_1, android.R.id.text1, accounts)); 224 mAccountSelector.setVisibility(View.VISIBLE); 225 mAccountSelector.setSelection(accountPosition); 226 } 227 if (!accountType.equals(storedAccountType) 228 || !accountName.equals(storedAccountName)) { 229 prefs.edit() 230 .putString(PREF_ACCOUNT_TYPE, accountType) 231 .putString(PREF_ACCOUNT_NAME, accountName) 232 .apply(); 233 } 234 if (loader.getId() == LOADER_ACCOUNTS_THEN_BOOKMARKS) { 235 getLoaderManager().initLoader(LOADER_BOOKMARKS, args, this); 236 } 237 238 break; 239 } 240 } 241 } 242 243 @Override 244 public void onClick(View view) { 245 if (view == mUpButton) { 246 Pair<String, Uri> pair = mFolderStack.pop(); 247 BookmarksLoader loader = 248 (BookmarksLoader) ((Loader) getLoaderManager().getLoader(LOADER_BOOKMARKS)); 249 loader.setUri(pair.second); 250 loader.forceLoad(); 251 } 252 } 253 254 @Override 255 public boolean onContextItemSelected(MenuItem item) { 256 final Activity activity = getActivity(); 257 // It is possible that the view has been canceled when we get to 258 // this point as back has a higher priority 259 if (mCanceled) { 260 return true; 261 } 262 AdapterView.AdapterContextMenuInfo i = 263 (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 264 // If we have no menu info, we can't tell which item was selected. 265 if (i == null) { 266 return true; 267 } 268 269 switch (item.getItemId()) { 270 case R.id.open_context_menu_id: 271 loadUrl(i.position); 272 break; 273 case R.id.edit_context_menu_id: 274 editBookmark(i.position); 275 break; 276 case R.id.shortcut_context_menu_id: 277 activity.sendBroadcast(createShortcutIntent(i.position)); 278 break; 279 case R.id.delete_context_menu_id: 280 displayRemoveBookmarkDialog(i.position); 281 break; 282 case R.id.new_window_context_menu_id: 283 openInNewWindow(i.position); 284 break; 285 case R.id.share_link_context_menu_id: { 286 Cursor cursor = (Cursor) mAdapter.getItem(i.position); 287 BrowserActivity.sharePage(activity, 288 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE), 289 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL), 290 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON), 291 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL)); 292 break; 293 } 294 case R.id.copy_url_context_menu_id: 295 copy(getUrl(i.position)); 296 break; 297 case R.id.homepage_context_menu_id: { 298 BrowserSettings.getInstance().setHomePage(activity, getUrl(i.position)); 299 Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show(); 300 break; 301 } 302 // Only for the Most visited page 303 case R.id.save_to_bookmarks_menu_id: { 304 Cursor cursor = (Cursor) mAdapter.getItem(i.position); 305 String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 306 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 307 // If the site is bookmarked, the item becomes remove from 308 // bookmarks. 309 Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name); 310 break; 311 } 312 default: 313 return super.onContextItemSelected(item); 314 } 315 return true; 316 } 317 318 Bitmap getBitmap(Cursor cursor, int columnIndex) { 319 byte[] data = cursor.getBlob(columnIndex); 320 if (data == null) { 321 return null; 322 } 323 return BitmapFactory.decodeByteArray(data, 0, data.length); 324 } 325 326 @Override 327 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 328 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; 329 330 final Activity activity = getActivity(); 331 MenuInflater inflater = activity.getMenuInflater(); 332 inflater.inflate(R.menu.bookmarkscontext, menu); 333 334 if (mDisableNewWindow) { 335 menu.findItem(R.id.new_window_context_menu_id).setVisible(false); 336 } 337 338 if (mContextHeader == null) { 339 mContextHeader = new BookmarkItem(activity); 340 } else if (mContextHeader.getParent() != null) { 341 ((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader); 342 } 343 344 populateBookmarkItem(mAdapter, mContextHeader, info.position); 345 346 menu.setHeaderView(mContextHeader); 347 } 348 349 private void populateBookmarkItem(BrowserBookmarksAdapter adapter, BookmarkItem item, 350 int position) { 351 Cursor cursor = (Cursor) mAdapter.getItem(position); 352 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 353 item.setUrl(url); 354 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 355 Bitmap bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 356 if (bitmap == null) { 357 bitmap = CombinedBookmarkHistoryActivity.getIconListenerSet().getFavicon(url); 358 } 359 item.setFavicon(bitmap); 360 } 361 362 /** 363 * Create a new BrowserBookmarksPage. 364 */ 365 @Override 366 public void onCreate(Bundle icicle) { 367 super.onCreate(icicle); 368 369 Bundle args = getArguments(); 370 mCreateShortcut = args == null ? false : args.getBoolean("create_shortcut", false); 371 mDisableNewWindow = args == null ? false : args.getBoolean("disable_new_window", false); 372 } 373 374 @Override 375 public void onAttach(Activity activity) { 376 super.onAttach(activity); 377 mCallbacks = (BookmarksHistoryCallbacks) activity; 378 } 379 380 @Override 381 public View onCreateView(LayoutInflater inflater, ViewGroup container, 382 Bundle savedInstanceState) { 383 Context context = getActivity(); 384 385 View root = inflater.inflate(R.layout.bookmarks, container, false); 386 mEmptyView = root.findViewById(android.R.id.empty); 387 mContentView = root.findViewById(android.R.id.content); 388 389 mGrid = (GridView) root.findViewById(R.id.grid); 390 mGrid.setOnItemClickListener(this); 391 mGrid.setColumnWidth(BrowserActivity.getDesiredThumbnailWidth(getActivity())); 392 if (!mCreateShortcut) { 393 mGrid.setOnCreateContextMenuListener(this); 394 } 395 396 mAccountSelector = (Spinner) root.findViewById(R.id.accounts); 397 mAccountSelector.setOnItemSelectedListener(this); 398 mAccountSelector.setVisibility(View.INVISIBLE); 399 400 mUpButton = (Button) root.findViewById(R.id.up); 401 mUpButton.setEnabled(false); 402 mUpButton.setOnClickListener(this); 403 mUpButton.setVisibility(View.GONE); 404 405 mAdapter = new BrowserBookmarksAdapter(getActivity()); 406 mGrid.setAdapter(mAdapter); 407 408 // Start the loaders 409 LoaderManager lm = getLoaderManager(); 410 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 411 String accountType = prefs.getString(PREF_ACCOUNT_TYPE, null); 412 String accountName = prefs.getString(PREF_ACCOUNT_NAME, null); 413 if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) { 414 // There is an account set, load up that one 415 Bundle args = null; 416 if (!DEFAULT_ACCOUNT.equals(accountType) && !DEFAULT_ACCOUNT.equals(accountName)) { 417 args = new Bundle(); 418 args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType); 419 args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName); 420 } 421 lm.restartLoader(LOADER_BOOKMARKS, args, this); 422 lm.restartLoader(LOADER_ACCOUNTS, null, this); 423 } else { 424 // No account set, load them first 425 lm.restartLoader(LOADER_ACCOUNTS_THEN_BOOKMARKS, null, this); 426 } 427 428 // Add our own listener in case there are favicons that have yet to be loaded. 429 CombinedBookmarkHistoryActivity.getIconListenerSet().addListener(this); 430 431 return root; 432 } 433 434 @Override 435 public void onReceivedIcon(String url, Bitmap icon) { 436 // A new favicon has been loaded, so let anything attached to the adapter know about it 437 // so new icons will be loaded. 438 mAdapter.notifyDataSetChanged(); 439 } 440 441 @Override 442 public void onItemClick(AdapterView parent, View v, int position, long id) { 443 // It is possible that the view has been canceled when we get to 444 // this point as back has a higher priority 445 if (mCanceled) { 446 android.util.Log.e(LOGTAG, "item clicked when dismissing"); 447 return; 448 } 449 450 if (mCreateShortcut) { 451 Intent intent = createShortcutIntent(position); 452 // the activity handles the intent in startActivityFromFragment 453 startActivity(intent); 454 return; 455 } 456 457 Cursor cursor = (Cursor) mAdapter.getItem(position); 458 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 459 if (!isFolder) { 460 mCallbacks.onUrlSelected(getUrl(position), false); 461 } else { 462 String title; 463 if (mFolderStack.size() != 0) { 464 title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 465 } else { 466 // TODO localize 467 title = "Bookmarks"; 468 } 469 LoaderManager manager = getLoaderManager(); 470 BookmarksLoader loader = 471 (BookmarksLoader) ((Loader) manager.getLoader(LOADER_BOOKMARKS)); 472 mFolderStack.push(new Pair(title, loader.getUri())); 473 Uri uri = ContentUris.withAppendedId( 474 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id); 475 loader.setUri(uri); 476 loader.forceLoad(); 477 } 478 } 479 480 @Override 481 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 482 Adapter adapter = parent.getAdapter(); 483 String accountType = "com.google"; 484 String accountName = adapter.getItem(position).toString(); 485 486 Bundle args = null; 487 if (ACCOUNT_NAME_UNSYNCED.equals(accountName)) { 488 accountType = DEFAULT_ACCOUNT; 489 accountName = DEFAULT_ACCOUNT; 490 } else { 491 args = new Bundle(); 492 args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType); 493 args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName); 494 } 495 496 // Remember the selection for later 497 PreferenceManager.getDefaultSharedPreferences(getActivity()).edit() 498 .putString(PREF_ACCOUNT_TYPE, accountType) 499 .putString(PREF_ACCOUNT_NAME, accountName) 500 .apply(); 501 502 getLoaderManager().restartLoader(LOADER_BOOKMARKS, args, this); 503 } 504 505 @Override 506 public void onNothingSelected(AdapterView<?> parent) { 507 // Do nothing 508 } 509 510 private Intent createShortcutIntent(int position) { 511 Cursor cursor = (Cursor) mAdapter.getItem(position); 512 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 513 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 514 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON); 515 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 516 return BookmarkUtils.createAddToHomeIntent(getActivity(), url, title, touchIcon, favicon); 517 } 518 519 private void loadUrl(int position) { 520 mCallbacks.onUrlSelected(getUrl(position), false); 521 } 522 523 private void openInNewWindow(int position) { 524 mCallbacks.onUrlSelected(getUrl(position), true); 525 } 526 527 private void editBookmark(int position) { 528 Intent intent = new Intent(getActivity(), AddBookmarkPage.class); 529 Cursor cursor = (Cursor) mAdapter.getItem(position); 530 Bundle item = new Bundle(); 531 item.putString(BrowserContract.Bookmarks.TITLE, 532 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 533 item.putString(BrowserContract.Bookmarks.URL, 534 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL)); 535 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON); 536 if (data != null) { 537 item.putParcelable(BrowserContract.Bookmarks.FAVICON, 538 BitmapFactory.decodeByteArray(data, 0, data.length)); 539 } 540 item.putInt("id", cursor.getInt(BookmarksLoader.COLUMN_INDEX_ID)); 541 item.putLong(BrowserContract.Bookmarks.PARENT, 542 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT)); 543 intent.putExtra("bookmark", item); 544 startActivityForResult(intent, BOOKMARKS_SAVE); 545 } 546 547 @Override 548 public void onActivityResult(int requestCode, int resultCode, Intent data) { 549 switch(requestCode) { 550 case BOOKMARKS_SAVE: 551 if (resultCode == Activity.RESULT_OK) { 552 Bundle extras; 553 if (data != null && (extras = data.getExtras()) != null) { 554 // If there are extras, then we need to save 555 // the edited bookmark. This is done in updateRow() 556 String title = extras.getString("title"); 557 String url = extras.getString("url"); 558 if (title != null && url != null) { 559 updateRow(extras); 560 } 561 } 562 } 563 break; 564 } 565 } 566 567 /** 568 * Update a row in the database with new information. 569 * @param map Bundle storing id, title and url of new information 570 */ 571 public void updateRow(Bundle map) { 572 573 // Find the record 574 int id = map.getInt("id"); 575 int position = -1; 576 Cursor cursor = mAdapter.getCursor(); 577 for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 578 if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_ID) == id) { 579 position = cursor.getPosition(); 580 break; 581 } 582 } 583 if (position < 0) { 584 return; 585 } 586 587 cursor.moveToPosition(position); 588 ContentValues values = new ContentValues(); 589 String title = map.getString(BrowserContract.Bookmarks.TITLE); 590 if (!title.equals(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE))) { 591 values.put(BrowserContract.Bookmarks.TITLE, title); 592 } 593 String url = map.getString(BrowserContract.Bookmarks.URL); 594 if (!url.equals(cursor.getString(BookmarksLoader.COLUMN_INDEX_URL))) { 595 values.put(BrowserContract.Bookmarks.URL, url); 596 } 597 598 if (map.getBoolean("invalidateThumbnail") == true) { 599 values.putNull(BrowserContract.Bookmarks.THUMBNAIL); 600 } 601 602 if (values.size() > 0) { 603 getActivity().getContentResolver().update( 604 ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), 605 values, null, null); 606 } 607 } 608 609 private void displayRemoveBookmarkDialog(final int position) { 610 // Put up a dialog asking if the user really wants to 611 // delete the bookmark 612 Cursor cursor = (Cursor) mAdapter.getItem(position); 613 Context context = getActivity(); 614 final ContentResolver resolver = context.getContentResolver(); 615 final Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, 616 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 617 618 new AlertDialog.Builder(context) 619 .setTitle(R.string.delete_bookmark) 620 .setIcon(android.R.drawable.ic_dialog_alert) 621 .setMessage(context.getString(R.string.delete_bookmark_warning, 622 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE))) 623 .setPositiveButton(R.string.ok, 624 new DialogInterface.OnClickListener() { 625 public void onClick(DialogInterface dialog, int whichButton) { 626 resolver.delete(uri, null, null); 627 } 628 }) 629 .setNegativeButton(R.string.cancel, null) 630 .show(); 631 } 632 633 private String getUrl(int position) { 634 Cursor cursor = (Cursor) mAdapter.getItem(position); 635 return cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 636 } 637 638 private void copy(CharSequence text) { 639 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService( 640 Context.CLIPBOARD_SERVICE); 641 cm.setPrimaryClip(ClipData.newRawUri(null, null, Uri.parse(text.toString()))); 642 } 643} 644