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