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