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