Copy and PasteAndroid provides a powerful clipboard-based framework for copying and pasting. It supports both simple and complex data types, including text strings, complex data structures, text and binary stream data, and even application assets. Simple text data is stored directly in the clipboard, while complex data is stored as a reference that the pasting application resolves with a content provider. Copying and pasting works both within an application and between applications that implement the framework. Show
Since a part of the framework uses content providers, this topic assumes some familiarity with the Android Content Provider API, which is described in the topic Content Providers. The Clipboard FrameworkWhen you use the clipboard framework, you put data into a clip object, and then put the clip object on the system-wide clipboard. The clip object can take one of three forms: Text A text string. You put the string directly into the clip object, which you then put onto the clipboard. To paste the string, you get the clip object from the clipboard and copy the string to into your application's storage. URI A Uri object representing any form of URI. This is primarily for copying complex data from a content provider. To copy data, you put a Uri object into a clip object and put the clip object onto the clipboard. To paste the data, you get the clip object, get the Uri object, resolve it to a data source such as a content provider, and copy the data from the source into your application's storage. Intent An Intent. This supports copying application shortcuts. To copy data, you create an Intent, put it into a clip object, and put the clip object onto the clipboard. To paste the data, you get the clip object and then copy the Intent object into your application's memory area.The clipboard holds only one clip object at a time. When an application puts a clip object on the clipboard, the previous clip object disappears. If you want to allow users to paste data into your application, you don't have to handle all types of data. You can examine the data on the clipboard before you give users the option to paste it. Besides having a certain data form, the clip object also contains metadata that tells you what MIME type or types are available. This metadata helps you decide if your application can do something useful with the clipboard data. For example, if you have an application that primarily handles text, you may want to ignore clip objects that contain a URI or Intent. You may also want to allow users to paste text regardless of the form of data on the clipboard. To do this, you can force the clipboard data into a text representation, and then paste this text. This is described in the section Coercing the clipboard to text. Clipboard ClassesThis section describes the classes used by the clipboard framework. ClipboardManagerIn the Android system, the system clipboard is represented by the global ClipboardManager class. You do not instantiate this class directly; instead, you get a reference to it by invoking getSystemService(CLIPBOARD_SERVICE). ClipData, ClipData.Item, and ClipDescriptionTo add data to the clipboard, you create a ClipData object that contains both a description of the data and the data itself. The clipboard holds only one ClipData at a time. A ClipData contains a ClipDescription object and one or more ClipData.Item objects. A ClipDescription object contains metadata about the clip. In particular, it contains an array of available MIME types for the clip's data. Additionally, on Android12 (API level31) and higher, the metadata includes information about whether the object contains stylized text and about the type of text in the object. When you put a clip on the clipboard, this information is available to pasting applications, which can examine it to see if they can handle the clip data. A ClipData.Item object contains the text, URI, or Intent data: Text A CharSequence. URI A Uri. This usually contains a content provider URI, although any URI is allowed. The application that provides the data puts the URI on the clipboard. Applications that want to paste the data get the URI from the clipboard and use it to access the content provider (or other data source) and retrieve the data. Intent An Intent. This data type allows you to copy an application shortcut to the clipboard. Users can then paste the shortcut into their applications for later use.You can add more than one ClipData.Item object to a clip. This allows users to copy and paste multiple selections as a single clip. For example, if you have a list widget that allows the user to select more than one item at a time, you can copy all the items to the clipboard at once. To do this, you create a separate ClipData.Item for each list item, and then you add the ClipData.Item objects to the ClipData object. ClipData convenience methodsThe ClipData class provides static convenience methods for creating a ClipData object with a single ClipData.Item object and a simple ClipDescription object: Use newPlainText() to create a clip from a text string. newUri(resolver, label, URI) Returns a ClipData object whose single ClipData.Item object contains a URI. The ClipDescription object's label is set to label. If the URI is a content URI (Uri.getScheme() returns content:), the method uses the ContentResolver object provided in resolver to retrieve the available MIME types from the content provider and store them in ClipDescription. For a URI that is not a content: URI, the method sets the MIME type to MIMETYPE_TEXT_URILIST.Use newUri() to create a clip from a URI, particularly a content: URI. newIntent(label, intent) Returns a ClipData object whose single ClipData.Item object contains an Intent. The ClipDescription object's label is set to label. The MIME type is set to MIMETYPE_TEXT_INTENT.Use newIntent() to create a clip from an Intent object. Coercing the clipboard data to textEven if your application only handles text, you can copy non-text data from the clipboard by converting it with the method ClipData.Item.coerceToText(). This method converts the data in ClipData.Item to text and returns a CharSequence. The value that ClipData.Item.coerceToText() returns is based on the form of data in ClipData.Item: Text If ClipData.Item is text (getText() is not null), coerceToText() returns the text. URI If ClipData.Item is a URI (getUri() is not null), coerceToText() tries to use it as a content URI:
The clipboard framework is summarized in Figure 1. To copy data, an application puts a ClipData object on the ClipboardManager global clipboard. The ClipData contains one or more ClipData.Item objects and one ClipDescription object. To paste data, an application gets the ClipData, gets its MIME type from the ClipDescription, and gets the data either from the ClipData.Item or from the content provider referred to by ClipData.Item. Copying to the ClipboardAs described previously, to copy data to the clipboard you get a handle to the global ClipboardManager object, create a ClipData object, add a ClipDescription and one or more ClipData.Item objects to it, and add the finished ClipData object to the ClipboardManager object. This is described in detail in the following procedure:
Pasting from the ClipboardAs described previously, you paste data from the clipboard by getting the global clipboard object, getting the clip object, looking at its data, and if possible copying the data from the clip object to your own storage. This section explains in detail how to paste the three forms of clipboard data. Pasting plain textTo paste plain text, first get the global clipboard and verify that it can return plain text. Then get the clip object and copy its text to your own storage using getText(), as described in the following procedure:
Pasting data from a content URIIf the ClipData.Item object contains a content URI and you have determined that you can handle one of its MIME types, create a ContentResolver and then call the appropriate content provider method to retrieve the data. The following procedure describes how to get data from a content provider based on a content URI on the clipboard. It checks that a MIME type that the application can use is available from the provider:
Pasting an IntentTo paste an Intent, first get the global clipboard. Examine the ClipData.Item object to see if it contains an Intent. Then call getIntent() to copy the Intent to your own storage. The following snippet demonstrates this: Kotlin// Gets a handle to the Clipboard Manager val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager // Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null val pasteIntent: Intent? = clipboard.primaryClip?.getItemAt(0)?.intent if (pasteIntent != null) { // handle the Intent } else { // ignore the clipboard, or issue an error if your application was expecting an Intent to be // on the clipboard }Java// Gets a handle to the Clipboard Manager ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); // Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent(); if (pasteIntent != null) { // handle the Intent } else { // ignore the clipboard, or issue an error if your application was expecting an Intent to be // on the clipboard }System notification shown when your app accesses clipboard dataOn Android12 (API level31) and higher, the system usually shows a toast message when your app calls getPrimaryClip(). The text inside the message contains the following format: APP pasted from your clipboardThe system doesn't show a toast message when your app does one of the following:
Using Content Providers to Copy Complex DataContent providers support copying complex data such as database records or file streams. To copy the data, you put a content URI on the clipboard. Pasting applications then get this URI from the clipboard and use it to retrieve database data or file stream descriptors. Since the pasting application only has the content URI for your data, it needs to know which piece of data to retrieve. You can provide this information by encoding an identifier for the data on the URI itself, or you can provide a unique URI that will return the data you want to copy. Which technique you choose depends on the organization of your data. The following sections describe how to set up URIs, how to provide complex data, and how to provide file streams. The descriptions assume that you are familiar with the general principles of content provider design. Encoding an identifier on the URIA useful technique for copying data to the clipboard with a URI is to encode an identifier for the data on the URI itself. Your content provider can then get the identifier from the URI and use it to retrieve the data. The pasting application doesn't have to know that the identifier exists; all it has to do is get your "reference" (the URI plus the identifier) from the clipboard, give it your content provider, and get back the data. You usually encode an identifier onto a content URI by concatenating it to the end of the URI. For example, suppose you define your provider URI as the following string: "content://com.example.contacts"If you want to encode a name onto this URI, you would use the following snippet: Kotlinval uriString = "content://com.example.contacts/Smith" // uriString now contains content://com.example.contacts/Smith. // Generates a uri object from the string representation val copyUri = Uri.parse(uriString)JavaString uriString = "content://com.example.contacts" + "/" + "Smith"; // uriString now contains content://com.example.contacts/Smith. // Generates a uri object from the string representation Uri copyUri = Uri.parse(uriString);If you are already using a content provider, you may want to add a new URI path that indicates the URI is for copying. For example, suppose you already have the following URI paths: You could add another path that is specific to copy URIs: "content://com.example.contacts/copying"You could then detect a "copy" URI by pattern-matching and handle it with code that is specific for copying and pasting. You normally use the encoding technique if you're already using a content provider, internal database, or internal table to organize your data. In these cases, you have multiple pieces of data you want to copy, and presumably a unique identifier for each piece. In response to a query from the pasting application, you can look up the data by its identifier and return it. If you don't have multiple pieces of data, then you probably don't need to encode an identifier. You can simply use a URI that is unique to your provider. In response to a query, your provider would return the data it currently contains. Getting a single record by ID is used in the Note Pad sample application to open a note from the notes list. The sample uses the _id field from an SQL database, but you can have any numeric or character identifier you want. Copying data structuresYou set up a content provider for copying and pasting complex data as a subclass of the ContentProvider component. You should also encode the URI you put on the clipboard so that it points to the exact record you want to provide. In addition, you have to consider the existing state of your application:
In the content provider, you will want to override at least the following methods: query() Pasting applications will assume that they can get your data by using this method with the URI you put on the clipboard. To support copying, you should have this method detect URIs that contain a special "copy" path. Your application can then create a "copy" URI to put on the clipboard, containing the copy path and a pointer to the exact record you want to copy. getType() This method should return the MIME type or types for the data you intend to copy. The method newUri() calls getType() in order to put the MIME types into the new ClipData object.MIME types for complex data are described in the topic Content Providers. Notice that you don't have to have any of the other content provider methods such as insert() or update(). A pasting application only needs to get your supported MIME types and copy data from your provider. If you already have these methods, they won't interfere with copy operations. The following snippets demonsrate how to set up your application to copy complex data:
The section Pasting data from a content URI describes how to get a content URI from the clipboard and use it to get and paste data. Copying data streamsYou can copy and paste large amounts of text and binary data as streams. The data can have forms such as the following:
A content provider for data streams provides access to its data with a file descriptor object such as AssetFileDescriptor instead of a Cursor object. The pasting application reads the data stream using this file descriptor. To set up your application to copy a data stream with a provider, follow these steps:
To paste a data stream, an application gets the clip from the clipboard, gets the URI, and uses it in a call to a ContentResolver file descriptor method that opens the stream. The ContentResolver method calls the corresponding ContentProvider method, passing it the content URI. Your provider returns the file descriptor to ContentResolver method. The pasting application then has the responsibility to read the data from the stream. The following list shows the most important file descriptor methods for a content provider. Each of these has a corresponding ContentResolver method with the string "Descriptor" appended to the method name; for example, the ContentResolver analog of openAssetFile() is openAssetFileDescriptor(): openTypedAssetFile() This method should return an asset file descriptor, but only if the provided MIME type is supported by the provider. The caller (the application doing the pasting) provides a MIME type pattern. The content provider (of the application that has copied a URI to the clipboard) returns an AssetFileDescriptor file handle if it can provide that MIME type, or throws an exception if it can not.This method handles subsections of files. You can use it to read assets that the content provider has copied to the clipboard. openAssetFile() This method is a more general form of openTypedAssetFile(). It does not filter for allowed MIME types, but it can read subsections of files. openFile() This is a more general form of openAssetFile(). It can't read subsections of files.You can optionally use the openPipeHelper() method with your file descriptor method. This allows the pasting application to read the stream data in a background thread using a pipe. To use this method, you need to implement the ContentProvider.PipeDataWriter interface. An example of doing this is given in the Note Pad sample application, in the openTypedAssetFile() method of NotePadProvider.java. Designing Effective Copy/Paste FunctionalityTo design effective copy and paste functionality for your application, remember these points:
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates. Last updated 2022-02-14 UTC.
[{
"type": "thumb-down",
"id": "missingTheInformationINeed",
"label":"Missing the information I need"
},{
"type": "thumb-down",
"id": "tooComplicatedTooManySteps",
"label":"Too complicated / too many steps"
},{
"type": "thumb-down",
"id": "outOfDate",
"label":"Out of date"
},{
"type": "thumb-down",
"id": "samplesCodeIssue",
"label":"Samples / code issue"
},{
"type": "thumb-down",
"id": "otherDown",
"label":"Other"
}]
[{
"type": "thumb-up",
"id": "easyToUnderstand",
"label":"Easy to understand"
},{
"type": "thumb-up",
"id": "solvedMyProblem",
"label":"Solved my problem"
},{
"type": "thumb-up",
"id": "otherUp",
"label":"Other"
}]
|