1 page.title=Copy and Paste 2 @jd:body 3 <div id="qv-wrapper"> 4 <div id="qv"> 5 <h2>Quickview</h2> 6 <ul> 7 <li> 8 A clipboard-based framework for copying and pasting data. 9 </li> 10 <li> 11 Supports both simple and complex data, including text strings, complex data 12 structures, text and binary stream data, and application assets. 13 </li> 14 <li> 15 Copies and pastes simple text directly to and from the clipboard. 16 </li> 17 <li> 18 Copies and pastes complex data using a content provider. 19 </li> 20 <li> 21 Requires API 11. 22 </li> 23 </ul> 24 <h2>In this document</h2> 25 <ol> 26 <li> 27 <a href="#Clipboard">The Clipboard Framework</a> 28 </li> 29 <li> 30 <a href="#ClipboardClasses">Clipboard Classes</a> 31 <ol> 32 <li> 33 <a href="#ClipboardManager">ClipboardManager</a> 34 </li> 35 <li> 36 <a href="#ClipClasses"> 37 ClipData, ClipDescription, and ClipData.Item 38 </a> 39 </li> 40 <li> 41 <a href="#ClipDataMethods">ClipData convenience methods</a> 42 </li> 43 <li> 44 <a href="#CoerceToText">Coercing the clipboard data to text</a> 45 </li> 46 </ol> 47 </li> 48 <li> 49 <a href="#Copying">Copying to the Clipboard</a> 50 </li> 51 <li> 52 <a href="#Pasting">Pasting from the Clipboard</a> 53 <ol> 54 <li> 55 <a href="#PastePlainText">Pasting plain text</a> 56 </li> 57 <li> 58 <a href="#PasteContentUri">Pasting data from a content URI</a> 59 </li> 60 <li> 61 <a href="#PasteIntent">Pasting an Intent</a> 62 </li> 63 </ol> 64 </li> 65 <li> 66 <a href="#Provider">Using Content Providers to Copy Complex Data</a> 67 <ol> 68 <li> 69 <a href="#Encoding">Encoding an identifier on the URI</a> 70 </li> 71 <li> 72 <a href="#Records">Copying data structures</a> 73 </li> 74 <li> 75 <a href="#Streams">Copying data streams</a> 76 </li> 77 </ol> 78 </li> 79 <li> 80 <a href="#DataDesign">Designing Effective Copy/Paste Functionality</a> 81 </li> 82 </ol> 83 <h2>Key classes</h2> 84 <ol> 85 <li> 86 {@link android.content.ClipboardManager ClipboardManager} 87 </li> 88 <li> 89 {@link android.content.ClipData ClipData} 90 </li> 91 <li> 92 {@link android.content.ClipData.Item ClipData.Item} 93 </li> 94 <li> 95 {@link android.content.ClipDescription ClipDescription} 96 </li> 97 <li> 98 {@link android.net.Uri Uri} 99 </li> 100 <li> 101 {@link android.content.ContentProvider} 102 </li> 103 <li> 104 {@link android.content.Intent Intent} 105 </li> 106 </ol> 107 <h2>Related Samples</h2> 108 <ol> 109 <li> 110 <a href="{@docRoot}resources/samples/NotePad/index.html"> 111 Note Pad sample application</a> 112 </li> 113 </ol> 114 <h2>See also</h2> 115 <ol> 116 <li> 117 <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> 118 </li> 119 </ol> 120 </div> 121 </div> 122 <p> 123 Android provides a powerful clipboard-based framework for copying and pasting. It 124 supports both simple and complex data types, including text strings, complex data 125 structures, text and binary stream data, and even application assets. Simple text data is stored 126 directly in the clipboard, while complex data is stored as a reference that the pasting 127 application resolves with a content provider. Copying and pasting works both within an 128 application and between applications that implement the framework. 129 </p> 130 131 <p> 132 Since a part of the framework uses content providers, this topic assumes some 133 familiarity with the Android Content Provider API, which is described in the topic 134 <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>. 135 </p> 136 <h2 id="Clipboard">The Clipboard Framework</h2> 137 <p> 138 When you use the clipboard framework, you put data into a clip object, and then 139 put the clip object on the system-wide clipboard. The clip object can take one of three forms: 140 </p> 141 <dl> 142 <dt>Text</dt> 143 <dd> 144 A text string. You put the string directly into the clip object, which you then put onto 145 the clipboard. To paste the string, you get the clip object from the clipboard and copy 146 the string to into your application's storage. 147 </dd> 148 <dt>URI</dt> 149 <dd> 150 A {@link android.net.Uri} object representing any form of URI. This is primarily for 151 copying complex data from a content provider. To copy data, you put a 152 {@link android.net.Uri} object into a clip object and put the clip object onto 153 the clipboard. To paste the data, you get the clip object, get the 154 {@link android.net.Uri} object, resolve it to a data source such as a content provider, 155 and copy the data from the source into your application's storage. 156 </dd> 157 <dt>Intent</dt> 158 <dd> 159 An {@link android.content.Intent}. This supports copying application shortcuts. To copy 160 data, you create an Intent, put it into a clip object, and put the clip object onto the 161 clipboard. To paste the data, you get the clip object and then copy the Intent object 162 into your application's memory area. 163 </dd> 164 </dl> 165 <p> 166 The clipboard holds only one clip object at a time. When an application puts a clip object on 167 the clipboard, the previous clip object disappears. 168 </p> 169 <p> 170 If you want to allow users to paste data into your application, you don't have to handle all 171 types of data. You can examine the data on the clipboard before you give users the option to 172 paste it. Besides having a certain data form, the clip object also contains metadata that tells 173 you what MIME type or types are available. This metadata helps you decide if your application 174 can do something useful with the clipboard data. For example, if you have an application that 175 primarily handles text you may want to ignore clip objects that contain a URI or Intent. 176 </p> 177 <p> 178 You may also want to allow users to paste text regardless of the form of data on the 179 clipboard. To do this, you can force the clipboard data into a text representation, and then 180 paste this text. This is described in the section <a href="#CoerceToText">Coercing the 181 clipboard to text</a>. 182 </p> 183 <h2 id="ClipboardClasses">Clipboard Classes</h2> 184 <p> 185 This section describes the classes used by the clipboard framework. 186 </p> 187 <h3 id="ClipboardManager">ClipboardManager</h3> 188 <p> 189 In the Android system, the system clipboard is represented by the global 190 {@link android.content.ClipboardManager} class. You do not instantiate this 191 class directly; instead, you get a reference to it by invoking 192 {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}. 193 </p> 194 <h3 id="ClipClasses">ClipData, ClipData.Item, and ClipDescription</h3> 195 <p> 196 To add data to the clipboard, you create a {@link android.content.ClipData} object that 197 contains both a description of the data and the data itself. The clipboard holds only one 198 {@link android.content.ClipData} at a time. A {@link android.content.ClipData} contains a 199 {@link android.content.ClipDescription} object and one or more 200 {@link android.content.ClipData.Item} objects. 201 </p> 202 <p> 203 A {@link android.content.ClipDescription} object contains metadata about the clip. In 204 particular, it contains an array of available MIME types for the clip's data. When you put a 205 clip on the clipboard, this array is available to pasting applications, which can examine it to 206 see if they can handle any of available the MIME types. 207 </p> 208 <p> 209 A {@link android.content.ClipData.Item} object contains the text, URI, or Intent data: 210 </p> 211 <dl> 212 <dt>Text</dt> 213 <dd> 214 A {@link java.lang.CharSequence}. 215 </dd> 216 <dt>URI</dt> 217 <dd> 218 A {@link android.net.Uri}. This usually contains a content provider URI, although any 219 URI is allowed. The application that provides the data puts the URI on the clipboard. 220 Applications that want to paste the data get the URI from the clipboard and use it to 221 access the content provider (or other data source) and retrieve the data. 222 </dd> 223 <dt>Intent</dt> 224 <dd> 225 An {@link android.content.Intent}. This data type allows you to copy an application shortcut 226 to the clipboard. Users can then paste the shortcut into their applications for later use. 227 </dd> 228 </dl> 229 <p> 230 You can add more than one {@link android.content.ClipData.Item} object to a clip. This allows 231 users to copy and paste multiple selections as a single clip. For example, if you have a list 232 widget that allows the user to select more than one item at a time, you can copy all the items 233 to the clipboard at once. To do this, you create a separate 234 {@link android.content.ClipData.Item} for each list item, and then you add the 235 {@link android.content.ClipData.Item} objects to the {@link android.content.ClipData} object. 236 </p> 237 <h3 id="ClipDataMethods">ClipData convenience methods</h3> 238 <p> 239 The {@link android.content.ClipData} class provides static convenience methods for creating 240 a {@link android.content.ClipData} object with a single {@link android.content.ClipData.Item} 241 object and a simple {@link android.content.ClipDescription} object: 242 </p> 243 <dl> 244 <dt> 245 {@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText(label, text)} 246 </dt> 247 <dd> 248 Returns a {@link android.content.ClipData} object whose single 249 {@link android.content.ClipData.Item} object contains a text string. The 250 {@link android.content.ClipDescription} object's label is set to <code>label</code>. 251 The single MIME type in {@link android.content.ClipDescription} is 252 {@link android.content.ClipDescription#MIMETYPE_TEXT_PLAIN}. 253 <p> 254 Use 255 {@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText()} 256 to create a clip from a text string. 257 </dd> 258 <dt> 259 {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri(resolver, label, URI)} 260 </dt> 261 <dd> 262 Returns a {@link android.content.ClipData} object whose single 263 {@link android.content.ClipData.Item} object contains a URI. The 264 {@link android.content.ClipDescription} object's label is set to <code>label</code>. 265 If the URI is a content URI ({@link android.net.Uri#getScheme() Uri.getScheme()} returns 266 <code>content:</code>), the method uses the {@link android.content.ContentResolver} object 267 provided in <code>resolver</code> to retrieve the available MIME types from the 268 content provider and store them in {@link android.content.ClipDescription}. For a URI that 269 is not a <code>content:</code> URI, the method sets the MIME type to 270 {@link android.content.ClipDescription#MIMETYPE_TEXT_URILIST}. 271 <p> 272 Use 273 {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()} 274 to create a clip from a URI, particularly a <code>content:</code> URI. 275 </p> 276 </dd> 277 <dt> 278 {@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent(label, intent)} 279 </dt> 280 <dd> 281 Returns a {@link android.content.ClipData} object whose single 282 {@link android.content.ClipData.Item} object contains an {@link android.content.Intent}. 283 The {@link android.content.ClipDescription} object's label is set to <code>label</code>. 284 The MIME type is set to {@link android.content.ClipDescription#MIMETYPE_TEXT_INTENT}. 285 <p> 286 Use 287 {@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent()} 288 to create a clip from an Intent object. 289 </dd> 290 </dl> 291 <h3 id="CoerceToText">Coercing the clipboard data to text</h3> 292 <p> 293 Even if your application only handles text, you can copy non-text data from the 294 clipboard by converting it with the method 295 {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}. 296 </p> 297 <p> 298 This method converts the data in {@link android.content.ClipData.Item} to text and 299 returns a {@link java.lang.CharSequence}. The value that 300 {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()} 301 returns is based on the form of data in {@link android.content.ClipData.Item}: 302 </p> 303 <dl> 304 <dt><em>Text</em></dt> 305 <dd> 306 If {@link android.content.ClipData.Item} is text 307 ({@link android.content.ClipData.Item#getText()} is not null), 308 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns the 309 text. 310 </dd> 311 <dt><em>URI</em></dt> 312 <dd> 313 If {@link android.content.ClipData.Item} is a URI 314 ({@link android.content.ClipData.Item#getUri()} is not null), 315 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} tries to use 316 it as a content URI: 317 <ul> 318 <li> 319 If the URI is a content URI and the provider can return a text stream, 320 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns 321 a text stream. 322 </li> 323 <li> 324 If the URI is a content URI but the provider does not offer a text stream, 325 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns 326 a representation of the URI. The representation is the same as that returned by 327 {@link android.net.Uri#toString() Uri.toString()}. 328 </li> 329 <li> 330 If the URI is not a content URI, 331 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns 332 a representation of the URI. The representation is the same as that returned by 333 {@link android.net.Uri#toString() Uri.toString()}. 334 </li> 335 </ul> 336 </dd> 337 <dt><em>Intent</em></dt> 338 <dd> 339 If {@link android.content.ClipData.Item} is an Intent 340 ({@link android.content.ClipData.Item#getIntent()} is not null), 341 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} converts it to 342 an Intent URI and returns it. The representation is the same as that returned by 343 {@link android.content.Intent#toUri(int) Intent.toUri(URI_INTENT_SCHEME)}. 344 </dd> 345 </dl> 346 <p> 347 The clipboard framework is summarized in Figure 1. To copy data, an application puts a 348 {@link android.content.ClipData} object on the {@link android.content.ClipboardManager} global 349 clipboard. The {@link android.content.ClipData} contains one or more 350 {@link android.content.ClipData.Item} objects and one 351 {@link android.content.ClipDescription} object. To paste data, an application gets the 352 {@link android.content.ClipData}, gets its MIME type from the 353 {@link android.content.ClipDescription}, and gets the data either from 354 the {@link android.content.ClipData.Item} or from the content provider referred to by 355 {@link android.content.ClipData.Item}. 356 </p> 357 <a name="framework"></a> 358 <img 359 src="{@docRoot}images/ui/clipboard/copy_paste_framework.png" 360 alt="A block diagram of the copy and paste framework" height="400px" id="figure1" /> 361 <p class="img-caption"> 362 <strong>Figure 1.</strong> The Android clipboard framework 363 </p> 364 <h2 id="Copying">Copying to the Clipboard</h2> 365 <p> 366 As described previously, to copy data to the clipboard you get a handle to the global 367 {@link android.content.ClipboardManager} object, create a {@link android.content.ClipData} 368 object, add a {@link android.content.ClipDescription} and one or more 369 {@link android.content.ClipData.Item} objects to it, and add the finished 370 {@link android.content.ClipData} object to the {@link android.content.ClipboardManager} object. 371 This is described in detail in the following procedure: 372 </p> 373 <ol> 374 <li> 375 If you are copying data using a content URI, set up a content 376 provider. 377 <p> 378 The <a href="{@docRoot}resources/samples/NotePad/index.html"> 379 Note Pad</a> sample application is an example of using a content provider for 380 copying and pasting. The 381 <a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html"> 382 NotePadProvider</a> class implements the content provider. The 383 <a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePad.html"> 384 NotePad</a> class defines a contract between the provider and other applications, 385 including the supported MIME types. 386 </p> 387 </li> 388 <li> 389 Get the system clipboard: 390 <pre> 391 392 ... 393 394 // if the user selects copy 395 case R.id.menu_copy: 396 397 // Gets a handle to the clipboard service. 398 ClipboardManager clipboard = (ClipboardManager) 399 getSystemService(Context.CLIPBOARD_SERVICE); 400 </pre> 401 </li> 402 <li> 403 <p> 404 Copy the data to a new {@link android.content.ClipData} object: 405 </p> 406 <ul> 407 <li> 408 <h4>For text</h4> 409 <pre> 410 // Creates a new text clip to put on the clipboard 411 ClipData clip = ClipData.newPlainText("simple text","Hello, World!"); 412 </pre> 413 </li> 414 <li> 415 <h4>For a URI</h4> 416 <p> 417 This snippet constructs a URI by encoding a record ID onto the content URI 418 for the provider. This technique is covered in more detail 419 in the section <a href="#Encoding">Encoding an identifier on the URI</a>: 420 </p> 421 <pre> 422 // Creates a Uri based on a base Uri and a record ID based on the contact's last name 423 // Declares the base URI string 424 private static final String CONTACTS = "content://com.example.contacts"; 425 426 // Declares a path string for URIs that you use to copy data 427 private static final String COPY_PATH = "/copy"; 428 429 // Declares the Uri to paste to the clipboard 430 Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + "/" + lastName); 431 432 ... 433 434 // Creates a new URI clip object. The system uses the anonymous getContentResolver() object to 435 // get MIME types from provider. The clip object's label is "URI", and its data is 436 // the Uri previously created. 437 ClipData clip = ClipData.newUri(getContentResolver(),"URI",copyUri); 438 </pre> 439 </li> 440 <li> 441 <h4>For an Intent</h4> 442 <p> 443 This snippet constructs an Intent for an application 444 and then puts it in the clip object: 445 </p> 446 <pre> 447 // Creates the Intent 448 Intent appIntent = new Intent(this, com.example.demo.myapplication.class); 449 450 ... 451 452 // Creates a clip object with the Intent in it. Its label is "Intent" and its data is 453 // the Intent object created previously 454 ClipData clip = ClipData.newIntent("Intent",appIntent); 455 </pre> 456 </li> 457 </ul> 458 </li> 459 <li> 460 Put the new clip object on the clipboard: 461 <pre> 462 // Set the clipboard's primary clip. 463 clipboard.setPrimaryClip(clip); 464 </pre> 465 </li> 466 </ol> 467 <h2 id="Pasting">Pasting from the Clipboard</h2> 468 <p> 469 As described previously, you paste data from the clipboard by getting the global clipboard 470 object, getting the clip object, looking at its data, and if possible copying the data from 471 the clip object to your own storage. This section describes in detail how to do this for 472 the three forms of clipboard data. 473 </p> 474 <h3 id="PastePlainText">Pasting plain text</h3> 475 <p> 476 To paste plain text, first get the global clipboard and verify that it can return plain text. 477 Then get the clip object and copy its text to your own storage using 478 {@link android.content.ClipData.Item#getText()}, as described in the following procedure: 479 </p> 480 <ol> 481 <li> 482 Get the global {@link android.content.ClipboardManager} object using 483 {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}. Also 484 declare a global variable to contain the pasted text: 485 <pre> 486 ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 487 488 String pasteData = ""; 489 490 </pre> 491 </li> 492 <li> 493 Next, determine if you should enable or disable the "paste" option in the 494 current Activity. You should verify that the clipboard contains a clip and that you 495 can handle the type of data represented by the clip: 496 <pre> 497 // Gets the ID of the "paste" menu item 498 MenuItem mPasteItem = menu.findItem(R.id.menu_paste); 499 500 // If the clipboard doesn't contain data, disable the paste menu item. 501 // If it does contain data, decide if you can handle the data. 502 if (!(clipboard.hasPrimaryClip())) { 503 504 mPasteItem.setEnabled(false); 505 506 } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) { 507 508 // This disables the paste menu item, since the clipboard has data but it is not plain text 509 mPasteItem.setEnabled(false); 510 } else { 511 512 // This enables the paste menu item, since the clipboard contains plain text. 513 mPasteItem.setEnabled(true); 514 } 515 } 516 </pre> 517 </li> 518 <li> 519 Copy the data from the clipboard. This point in the program is only reachable if the 520 "paste" menu item is enabled, so you can assume that the clipboard contains 521 plain text. You do not yet know if it contains a text string or a URI that points to plain 522 text. The following snippet tests this, but it only shows the code for handling plain text: 523 <pre> 524 // Responds to the user selecting "paste" 525 case R.id.menu_paste: 526 527 // Examines the item on the clipboard. If getText() does not return null, the clip item contains the 528 // text. Assumes that this application can only handle one item at a time. 529 ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); 530 531 // Gets the clipboard as text. 532 pasteData = item.getText(); 533 534 // If the string contains data, then the paste operation is done 535 if (pasteData != null) { 536 return; 537 538 // The clipboard does not contain text. If it contains a URI, attempts to get data from it 539 } else { 540 Uri pasteUri = item.getUri(); 541 542 // If the URI contains something, try to get text from it 543 if (pasteUri != null) { 544 545 // calls a routine to resolve the URI and get data from it. This routine is not 546 // presented here. 547 pasteData = resolveUri(Uri); 548 return; 549 } else { 550 551 // Something is wrong. The MIME type was plain text, but the clipboard does not contain either 552 // text or a Uri. Report an error. 553 Log.e("Clipboard contains an invalid data type"); 554 return; 555 } 556 } 557 </pre> 558 </li> 559 </ol> 560 <h3 id="PasteContentUri">Pasting data from a content URI</h3> 561 <p> 562 If the {@link android.content.ClipData.Item} object contains a content URI and you 563 have determined that you can handle one of its MIME types, create a 564 {@link android.content.ContentResolver} and then call the appropriate content provider 565 method to retrieve the data. 566 </p> 567 <p> 568 The following procedure describes how to get data from a content provider based on a 569 content URI on the clipboard. It checks that a MIME type that the application can use 570 is available from the provider: 571 </p> 572 <ol> 573 <li> 574 Declare a global variable to contain the MIME type: 575 <pre> 576 // Declares a MIME type constant to match against the MIME types offered by the provider 577 public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact" 578 </pre> 579 </li> 580 <li> 581 Get the global clipboard. Also get a content resolver so you can access the content 582 provider: 583 <pre> 584 // Gets a handle to the Clipboard Manager 585 ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 586 587 // Gets a content resolver instance 588 ContentResolver cr = getContentResolver(); 589 </pre> 590 </li> 591 <li> 592 Get the primary clip from the clipboard, and get its contents as a URI: 593 <pre> 594 // Gets the clipboard data from the clipboard 595 ClipData clip = clipboard.getPrimaryClip(); 596 597 if (clip != null) { 598 599 // Gets the first item from the clipboard data 600 ClipData.Item item = clip.getItemAt(0); 601 602 // Tries to get the item's contents as a URI 603 Uri pasteUri = item.getUri(); 604 </pre> 605 </li> 606 <li> 607 Test to see if the URI is a content URI by calling 608 {@link android.content.ContentResolver#getType(Uri) getType(Uri)}. This method returns 609 null if <code>Uri</code> does not point to a valid content provider: 610 <pre> 611 // If the clipboard contains a URI reference 612 if (pasteUri != null) { 613 614 // Is this a content URI? 615 String uriMimeType = cr.getType(pasteUri); 616 </pre> 617 </li> 618 <li> 619 Test to see if the content provider supports a MIME type that the current application 620 understands. If it does, call 621 {@link android.content.ContentResolver#query(Uri, String[], String, String[], String) 622 ContentResolver.query()} to get the data. The return value is a 623 {@link android.database.Cursor}: 624 <pre> 625 // If the return value is not null, the Uri is a content Uri 626 if (uriMimeType != null) { 627 628 // Does the content provider offer a MIME type that the current application can use? 629 if (uriMimeType.equals(MIME_TYPE_CONTACT)) { 630 631 // Get the data from the content provider. 632 Cursor pasteCursor = cr.query(uri, null, null, null, null); 633 634 // If the Cursor contains data, move to the first record 635 if (pasteCursor != null) { 636 if (pasteCursor.moveToFirst()) { 637 638 // get the data from the Cursor here. The code will vary according to the 639 // format of the data model. 640 } 641 } 642 643 // close the Cursor 644 pasteCursor.close(); 645 } 646 } 647 } 648 } 649 </pre> 650 </li> 651 </ol> 652 <h3 id="PasteIntent">Pasting an Intent</h3> 653 <p> 654 To paste an Intent, first get the global clipboard. Examine the 655 {@link android.content.ClipData.Item} object to see if it contains an Intent. Then call 656 {@link android.content.ClipData.Item#getIntent()} to copy the Intent to your own storage. 657 The following snippet demonstrates this: 658 </p> 659 <pre> 660 // Gets a handle to the Clipboard Manager 661 ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 662 663 // Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null 664 Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent(); 665 666 if (pasteIntent != null) { 667 668 // handle the Intent 669 670 } else { 671 672 // ignore the clipboard, or issue an error if your application was expecting an Intent to be 673 // on the clipboard 674 } 675 </pre> 676 <h2 id="Provider">Using Content Providers to Copy Complex Data</h2> 677 <p> 678 Content providers support copying complex data such as database records or file streams. 679 To copy the data, you put a content URI on the clipboard. Pasting applications then get this 680 URI from the clipboard and use it to retrieve database data or file stream descriptors. 681 </p> 682 <p> 683 Since the pasting application only has the content URI for your data, it needs to know which 684 piece of data to retrieve. You can provide this information by encoding an identifier for the 685 data on the URI itself, or you can provide a unique URI that will return the data you want to 686 copy. Which technique you choose depends on the organization of your data. 687 </p> 688 <p> 689 The following sections describe how to set up URIs, how to provide complex data, and how to 690 provide file streams. The descriptions assume that you are familiar with the general principles 691 of content provider design. 692 </p> 693 <h3 id="Encoding">Encoding an identifier on the URI</h3> 694 <p> 695 A useful technique for copying data to the clipboard with a URI is to encode an identifier for 696 the data on the URI itself. Your content provider can then get the identifier from the URI and 697 use it to retrieve the data. The pasting application doesn't have to know that the identifier 698 exists; all it has to do is get your "reference" (the URI plus the identifier) from 699 the clipboard, give it your content provider, and get back the data. 700 </p> 701 <p> 702 You usually encode an identifier onto a content URI by concatenating it to the end of the URI. 703 For example, suppose you define your provider URI as the following string: 704 </p> 705 <pre> 706 "content://com.example.contacts" 707 </pre> 708 <p> 709 If you want to encode a name onto this URI, you would use the following snippet: 710 </p> 711 <pre> 712 String uriString = "content://com.example.contacts" + "/" + "Smith" 713 714 // uriString now contains content://com.example.contacts/Smith. 715 716 // Generates a uri object from the string representation 717 Uri copyUri = Uri.parse(uriString); 718 </pre> 719 <p> 720 If you are already using a content provider, you may want to add a new URI path that indicates 721 the URI is for copying. For example, suppose you already have the following URI paths: 722 </p> 723 <pre> 724 "content://com.example.contacts"/people 725 "content://com.example.contacts"/people/detail 726 "content://com.example.contacts"/people/images 727 </pre> 728 <p> 729 You could add another path that is specific to copy URIs: 730 </p> 731 <pre> 732 "content://com.example.contacts/copying" 733 </pre> 734 <p> 735 You could then detect a "copy" URI by pattern-matching and handle it with code that 736 is specific for copying and pasting. 737 </p> 738 <p> 739 You normally use the encoding technique if you're already using a content provider, internal 740 database, or internal table to organize your data. In these cases, you have multiple pieces of 741 data you want to copy, and presumably a unique identifier for each piece. In response to a 742 query from the pasting application, you can look up the data by its identifier and return it. 743 </p> 744 <p> 745 If you don't have multiple pieces of data, then you probably don't need to encode an identifier. 746 You can simply use a URI that is unique to your provider. In response to a query, your provider 747 would return the data it currently contains. 748 </p> 749 <p> 750 Getting a single record by ID is used in the 751 <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample application to 752 open a note from the notes list. The sample uses the <code>_id</code> field from an SQL 753 database, but you can have any numeric or character identifier you want. 754 </p> 755 <h3 id="Records">Copying data structures</h3> 756 <p> 757 You set up a content provider for copying and pasting complex data as a subclass of the 758 {@link android.content.ContentProvider} component. You should also encode the URI you put on 759 the clipboard so that it points to the exact record you want to provide. In addition, you 760 have to consider the existing state of your application: 761 </p> 762 <ul> 763 <li> 764 If you already have a content provider, you can add to its functionality. You may only 765 need to modify its 766 {@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()} 767 method to handle URIs coming from applications that want to paste data. You will 768 probably want to modify the method to handle a "copy" URI pattern. 769 </li> 770 <li> 771 If your application maintains an internal database, you may 772 want to move this database into a content provider to facilitate copying from it. 773 </li> 774 <li> 775 If you are not currently using a database, you can implement a simple content provider 776 whose sole purpose is to offer data to applications that are pasting from the 777 clipboard. 778 </li> 779 </ul> 780 <p> 781 In the content provider, you will want to override at least the following methods: 782 </p> 783 <dl> 784 <dt> 785 {@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()} 786 </dt> 787 <dd> 788 Pasting applications will assume that they can get your data by using this method with 789 the URI you put on the clipboard. To support copying, you should have this method 790 detect URIs that contain a special "copy" path. Your application can then 791 create a "copy" URI to put on the clipboard, containing the copy path and 792 a pointer to the exact record you want to copy. 793 </dd> 794 <dt> 795 {@link android.content.ContentProvider#getType(Uri) getType()} 796 </dt> 797 <dd> 798 This method should return the MIME type or types for the data you intend to copy. The method 799 {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()} calls 800 {@link android.content.ContentProvider#getType(Uri) getType()} in order to put the MIME 801 types into the new {@link android.content.ClipData} object. 802 <p> 803 MIME types for complex data are described in the topic 804 <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>. 805 </p> 806 </dd> 807 </dl> 808 <p> 809 Notice that you don't have to have any of the other content provider methods such as 810 {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} or 811 {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) update()}. 812 A pasting application only needs to get your supported MIME types and copy data from your 813 provider. If you already have these methods, they won't interfere with copy operations. 814 </p> 815 <p> 816 The following snippets demonsrate how to set up your application to copy complex data: 817 </p> 818 <ol> 819 <li> 820 <p> 821 In the global constants for your application, 822 declare a base URI string and a path that identifies URI strings you are 823 using to copy data. Also declare a MIME type for the copied data: 824 </p> 825 <pre> 826 // Declares the base URI string 827 private static final String CONTACTS = "content://com.example.contacts"; 828 829 // Declares a path string for URIs that you use to copy data 830 private static final String COPY_PATH = "/copy"; 831 832 // Declares a MIME type for the copied data 833 public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact" 834 </pre> 835 </li> 836 <li> 837 In the Activity from which users copy data, 838 set up the code to copy data to the clipboard. In response to a copy request, put 839 the URI on the clipboard: 840 <pre> 841 public class MyCopyActivity extends Activity { 842 843 ... 844 845 // The user has selected a name and is requesting a copy. 846 case R.id.menu_copy: 847 848 // Appends the last name to the base URI 849 // The name is stored in "lastName" 850 uriString = CONTACTS + COPY_PATH + "/" + lastName; 851 852 // Parses the string into a URI 853 Uri copyUri = Uri.parse(uriString); 854 855 // Gets a handle to the clipboard service. 856 ClipboardManager clipboard = (ClipboardManager) 857 getSystemService(Context.CLIPBOARD_SERVICE); 858 859 ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri); 860 861 // Set the clipboard's primary clip. 862 clipboard.setPrimaryClip(clip); 863 </pre> 864 </li> 865 866 <li> 867 <p> 868 In the global scope of your content provider, create a URI matcher and add a URI 869 pattern that will match URIs you put on the clipboard: 870 </p> 871 <pre> 872 public class MyCopyProvider extends ContentProvider { 873 874 ... 875 876 // A Uri Match object that simplifies matching content URIs to patterns. 877 private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 878 879 // An integer to use in switching based on the incoming URI pattern 880 private static final int GET_SINGLE_CONTACT = 0; 881 882 ... 883 884 // Adds a matcher for the content URI. It matches 885 // "content://com.example.contacts/copy/*" 886 sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT); 887 </pre> 888 </li> 889 <li> 890 <p> 891 Set up the 892 {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) query()} 893 method. This method can handle different URI patterns, depending on how you code it, but 894 only the pattern for the clipboard copying operation is shown: 895 </p> 896 <pre> 897 // Sets up your provider's query() method. 898 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 899 String sortOrder) { 900 901 ... 902 903 // Switch based on the incoming content URI 904 switch (sUriMatcher.match(uri)) { 905 906 case GET_SINGLE_CONTACT: 907 908 // query and return the contact for the requested name. Here you would decode 909 // the incoming URI, query the data model based on the last name, and return the result 910 // as a Cursor. 911 912 ... 913 914 } 915 </pre> 916 </li> 917 <li> 918 <p> 919 Set up the {@link android.content.ContentProvider#getType(Uri) getType()} method to 920 return an appropriate MIME type for copied data: 921 </p> 922 <pre> 923 // Sets up your provider's getType() method. 924 public String getType(Uri uri) { 925 926 ... 927 928 switch (sUriMatcher.match(uri)) { 929 930 case GET_SINGLE_CONTACT: 931 932 return (MIME_TYPE_CONTACT); 933 </pre> 934 </li> 935 </ol> 936 <p> 937 The section <a href="#PasteContentUri">Pasting data from a content URI</a> 938 describes how to get a content URI from the clipboard and use it to get and paste data. 939 </p> 940 <h3 id="Streams">Copying data streams</h3> 941 <p> 942 You can copy and paste large amounts of text and binary data as streams. The data can have 943 forms such as the following: 944 </p> 945 <ul> 946 <li> 947 Files stored on the actual device. 948 </li> 949 <li> 950 Streams from sockets. 951 </li> 952 <li> 953 Large amounts of data stored in a provider's underlying database system. 954 </li> 955 </ul> 956 <p> 957 A content provider for data streams provides access to its data with a file descriptor object 958 such as {@link android.content.res.AssetFileDescriptor} instead of a 959 {@link android.database.Cursor} object. The pasting application reads the data stream using 960 this file descriptor. 961 </p> 962 <p> 963 To set up your application to copy a data stream with a provider, follow these steps: 964 </p> 965 <ol> 966 <li> 967 Set up a content URI for the data stream you are putting on the clipboard. Options 968 for doing this include the following: 969 <ul> 970 <li> 971 Encode an identifier for the data stream onto the URI, 972 as described in the section 973 <a href="#Encoding">Encoding an identifier on the URI</a>, and then maintain a 974 table in your provider that contains identifiers and the corresponding stream name. 975 </li> 976 <li> 977 Encode the stream name directly on the URI. 978 </li> 979 <li> 980 Use a unique URI that always returns the current stream from the provider. If you 981 use this option, you have to remember to update your provider to point to a 982 different stream whenever you copy the stream to the clipboard via the URI. 983 </li> 984 </ul> 985 </li> 986 <li> 987 Provide a MIME type for each type of data stream you plan to offer. Pasting applications 988 need this information to determine if they can paste the data on the clipboard. 989 </li> 990 <li> 991 Implement one of the {@link android.content.ContentProvider} methods that returns 992 a file descriptor for a stream. If you encode identifiers on the content URI, use this 993 method to determine which stream to open. 994 </li> 995 <li> 996 To copy the data stream to the clipboard, construct the content URI and place it 997 on the clipboard. 998 </li> 999 </ol> 1000 <p> 1001 To paste a data stream, an application gets the clip from the clipboard, gets the URI, and 1002 uses it in a call to a {@link android.content.ContentResolver} file descriptor method that 1003 opens the stream. The {@link android.content.ContentResolver} method calls the corresponding 1004 {@link android.content.ContentProvider} method, passing it the content URI. Your provider 1005 returns the file descriptor to {@link android.content.ContentResolver} method. The pasting 1006 application then has the responsibility to read the data from the stream. 1007 </p> 1008 <p> 1009 The following list shows the most important file descriptor methods for a content provider. 1010 Each of these has a corresponding {@link android.content.ContentResolver} method with the 1011 string "Descriptor" appended to the method name; for example, the 1012 {@link android.content.ContentResolver} analog of 1013 {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()} is 1014 {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) openAssetFileDescriptor()}: 1015 </p> 1016 <dl> 1017 <dt> 1018 {@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()} 1019 </dt> 1020 <dd> 1021 This method should return an asset file descriptor, but only if the provided MIME type is 1022 supported by the provider. The caller (the application doing the pasting) provides a MIME 1023 type pattern. The content provider (of the application that has copied a URI to the 1024 clipboard) returns an {@link android.content.res.AssetFileDescriptor} file handle if it 1025 can provide that MIME type, or throws an exception if it can not. 1026 <p> 1027 This method handles subsections of files. You can use it to read assets that the 1028 content provider has copied to the clipboard. 1029 </p> 1030 </dd> 1031 <dt> 1032 {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()} 1033 </dt> 1034 <dd> 1035 This method is a more general form of 1036 {@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}. 1037 It does not filter for allowed MIME types, but it can read subsections of files. 1038 </dd> 1039 <dt> 1040 {@link android.content.ContentProvider#openFile(Uri, String) openFile()} 1041 </dt> 1042 <dd> 1043 This is a more general form of 1044 {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}. It can't 1045 read subsections of files. 1046 </dd> 1047 </dl> 1048 <p> 1049 You can optionally use the 1050 {@link android.content.ContentProvider#openPipeHelper(Uri, String, Bundle, T, ContentProvider.PipeDataWriter) openPipeHelper()} 1051 method with your file descriptor method. This allows the pasting application to read the 1052 stream data in a background thread using a pipe. To use this method, you need to implement the 1053 {@link android.content.ContentProvider.PipeDataWriter} interface. An example of doing this is 1054 given in the <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample 1055 application, in the <code>openTypedAssetFile()</code> method of 1056 <code>NotePadProvider.java</code>. 1057 </p> 1058 <h2 id="DataDesign">Designing Effective Copy/Paste Functionality</h2> 1059 <p> 1060 To design effective copy and paste functionality for your application, remember these 1061 points: 1062 </p> 1063 <ul> 1064 <li> 1065 At any time, there is only one clip on the clipboard. A new copy operation by 1066 any application in the system overwrites the previous clip. Since the user may 1067 navigate away from your application and do a copy before returning, you can't assume 1068 that the clipboard contains the clip that the user previously copied in <em>your</em> 1069 application. 1070 </li> 1071 <li> 1072 The intended purpose of multiple {@link android.content.ClipData.Item} 1073 objects per clip is to support copying and pasting of multiple selections rather than 1074 different forms of reference to a single selection. You usually want all of the 1075 {@link android.content.ClipData.Item} objects in a clip to have the same form, that is, 1076 they should all be simple text, content URI, or {@link android.content.Intent}, but not 1077 a mixture. 1078 </li> 1079 <li> 1080 When you provide data, you can offer different MIME representations. Add the MIME types 1081 you support to the {@link android.content.ClipDescription}, and then 1082 implement the MIME types in your content provider. 1083 </li> 1084 <li> 1085 When you get data from the clipboard, your application is responsible for checking the 1086 available MIME types and then deciding which one, if any, to use. Even if there is a 1087 clip on the clipboard and the user requests a paste, your application is not required 1088 to do the paste. You <em>should</em> do the paste if the MIME type is compatible. You 1089 may choose to coerce the data on the clipboard to text using 1090 {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} if you 1091 choose. If your application supports more than one of the available MIME types, you can 1092 allow the user to choose which one to use. 1093 </li> 1094 </ul> 1095