summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/clipboard/copy-paste.jd
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/guide/topics/clipboard/copy-paste.jd')
-rw-r--r--docs/html/guide/topics/clipboard/copy-paste.jd1094
1 files changed, 1094 insertions, 0 deletions
diff --git a/docs/html/guide/topics/clipboard/copy-paste.jd b/docs/html/guide/topics/clipboard/copy-paste.jd
new file mode 100644
index 0000000..9a50a35
--- /dev/null
+++ b/docs/html/guide/topics/clipboard/copy-paste.jd
@@ -0,0 +1,1094 @@
+page.title=Copying and Pasting
+@jd:body
+<div id="qv-wrapper">
+ <div id="qv">
+ <h2>Quickview</h2>
+ <ul>
+ <li>
+ A clipboard-based framework for copying and pasting data.
+ </li>
+ <li>
+ Supports both simple and complex data, including text strings, complex data
+ structures, text and binary stream data, and application assets.
+ </li>
+ <li>
+ Copies and pastes simple text directly to and from the clipboard.
+ </li>
+ <li>
+ Copies and pastes complex data using a content provider.
+ </li>
+ <li>
+ Requires API 11.
+ </li>
+ </ul>
+ <h2>In this document</h2>
+ <ol>
+ <li>
+ <a href="#Clipboard">The Clipboard Framework</a>
+ </li>
+ <li>
+ <a href="#ClipboardClasses">Clipboard Classes</a>
+ <ol>
+ <li>
+ <a href="#ClipboardManager">ClipboardManager</a>
+ </li>
+ <li>
+ <a href="#ClipClasses">
+ ClipData, ClipDescription, and ClipData.Item
+ </a>
+ </li>
+ <li>
+ <a href="#ClipDataMethods">ClipData convenience methods</a>
+ </li>
+ <li>
+ <a href="#CoerceToText">Coercing the clipboard data to text</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#Copying">Copying to the Clipboard</a>
+ </li>
+ <li>
+ <a href="#Pasting">Pasting from the Clipboard</a>
+ <ol>
+ <li>
+ <a href="#PastePlainText">Pasting plain text</a>
+ </li>
+ <li>
+ <a href="#PasteContentUri">Pasting data from a content URI</a>
+ </li>
+ <li>
+ <a href="#PasteIntent">Pasting an Intent</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#Provider">Using Content Providers to Copy Complex Data</a>
+ <ol>
+ <li>
+ <a href="#Encoding">Encoding an identifier on the URI</a>
+ </li>
+ <li>
+ <a href="#Records">Copying data structures</a>
+ </li>
+ <li>
+ <a href="#Streams">Copying data streams</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#DataDesign">Designing Effective Copy/Paste Functionality</a>
+ </li>
+ </ol>
+ <h2>Key classes</h2>
+ <ol>
+ <li>
+ {@link android.content.ClipboardManager ClipboardManager}
+ </li>
+ <li>
+ {@link android.content.ClipData ClipData}
+ </li>
+ <li>
+ {@link android.content.ClipData.Item ClipData.Item}
+ </li>
+ <li>
+ {@link android.content.ClipDescription ClipDescription}
+ </li>
+ <li>
+ {@link android.net.Uri Uri}
+ </li>
+ <li>
+ {@link android.content.ContentProvider}
+ </li>
+ <li>
+ {@link android.content.Intent Intent}
+ </li>
+ </ol>
+ <h2>Related Samples</h2>
+ <ol>
+ <li>
+ <a href="{@docRoot}resources/samples/NotePad/index.html">
+ Note Pad sample application</a>
+ </li>
+ </ol>
+ <h2>See also</h2>
+ <ol>
+ <li>
+ <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+ </li>
+ </ol>
+ </div>
+</div>
+<p>
+ Android 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.
+</p>
+
+<p>
+ 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
+ <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+</p>
+<h2 id="Clipboard">The Clipboard Framework</h2>
+<p>
+ When 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:
+</p>
+ <dl>
+ <dt>Text</dt>
+ <dd>
+ 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.
+ </dd>
+ <dt>URI</dt>
+ <dd>
+ A {@link android.net.Uri} object representing any form of URI. This is primarily for
+ copying complex data from a content provider. To copy data, you put a
+ {@link android.net.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
+ {@link android.net.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.
+ </dd>
+ <dt>Intent</dt>
+ <dd>
+ An {@link android.content.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.
+ </dd>
+ </dl>
+<p>
+ 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.
+</p>
+<p>
+ 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.
+</p>
+<p>
+ 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 <a href="#CoerceToText">Coercing the
+ clipboard to text</a>.
+</p>
+<h2 id="ClipboardClasses">Clipboard Classes</h2>
+<p>
+ This section describes the classes used by the clipboard framework.
+</p>
+<h3 id="ClipboardManager">ClipboardManager</h3>
+<p>
+ In the Android system, the system clipboard is represented by the global
+ {@link android.content.ClipboardManager} class. You do not instantiate this
+ class directly; instead, you get a reference to it by invoking
+ {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}.
+</p>
+<h3 id="ClipClasses">ClipData, ClipData.Item, and ClipDescription</h3>
+<p>
+ To add data to the clipboard, you create a {@link android.content.ClipData} object that
+ contains both a description of the data and the data itself. The clipboard holds only one
+ {@link android.content.ClipData} at a time. A {@link android.content.ClipData} contains a
+ {@link android.content.ClipDescription} object and one or more
+ {@link android.content.ClipData.Item} objects.
+</p>
+<p>
+ A {@link android.content.ClipDescription} object contains metadata about the clip. In
+ particular, it contains an array of available MIME types for the clip's data. When you put a
+ clip on the clipboard, this array is available to pasting applications, which can examine it to
+ see if they can handle any of available the MIME types.
+</p>
+<p>
+ A {@link android.content.ClipData.Item} object contains the text, URI, or Intent data:
+</p>
+<dl>
+ <dt>Text</dt>
+ <dd>
+ A {@link java.lang.CharSequence}.
+ </dd>
+ <dt>URI</dt>
+ <dd>
+ A {@link android.net.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.
+ </dd>
+ <dt>Intent</dt>
+ <dd>
+ An {@link android.content.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.
+ </dd>
+</dl>
+<p>
+ You can add more than one {@link android.content.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
+ {@link android.content.ClipData.Item} for each list item, and then you add the
+ {@link android.content.ClipData.Item} objects to the {@link android.content.ClipData} object.
+</p>
+<h3 id="ClipDataMethods">ClipData convenience methods</h3>
+<p>
+ The {@link android.content.ClipData} class provides static convenience methods for creating
+ a {@link android.content.ClipData} object with a single {@link android.content.ClipData.Item}
+ object and a simple {@link android.content.ClipDescription} object:
+</p>
+<dl>
+ <dt>
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText(label, text)}
+ </dt>
+ <dd>
+ Returns a {@link android.content.ClipData} object whose single
+ {@link android.content.ClipData.Item} object contains a text string. The
+ {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+ The single MIME type in {@link android.content.ClipDescription} is
+ {@link android.content.ClipDescription#MIMETYPE_TEXT_PLAIN}.
+ <p>
+ Use
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText()}
+ to create a clip from a text string.
+ </dd>
+ <dt>
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri(resolver, label, URI)}
+ </dt>
+ <dd>
+ Returns a {@link android.content.ClipData} object whose single
+ {@link android.content.ClipData.Item} object contains a URI. The
+ {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+ If the URI is a content URI ({@link android.net.Uri#getScheme() Uri.getScheme()} returns
+ <code>content:</code>), the method uses the {@link android.content.ContentResolver} object
+ provided in <code>resolver</code> to retrieve the available MIME types from the
+ content provider and store them in {@link android.content.ClipDescription}. For a URI that
+ is not a <code>content:</code> URI, the method sets the MIME type to
+ {@link android.content.ClipDescription#MIMETYPE_TEXT_URILIST}.
+ <p>
+ Use
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()}
+ to create a clip from a URI, particularly a <code>content:</code> URI.
+ </p>
+ </dd>
+ <dt>
+ {@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent(label, intent)}
+ </dt>
+ <dd>
+ Returns a {@link android.content.ClipData} object whose single
+ {@link android.content.ClipData.Item} object contains an {@link android.content.Intent}.
+ The {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+ The MIME type is set to {@link android.content.ClipDescription#MIMETYPE_TEXT_INTENT}.
+ <p>
+ Use
+{@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent()}
+ to create a clip from an Intent object.
+ </dd>
+</dl>
+<h3 id="CoerceToText">Coercing the clipboard data to text</h3>
+<p>
+ Even if your application only handles text, you can copy non-text data from the
+ clipboard by converting it with the method
+ {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}.
+</p>
+<p>
+ This method converts the data in {@link android.content.ClipData.Item} to text and
+ returns a {@link java.lang.CharSequence}. The value that
+ {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}
+ returns is based on the form of data in {@link android.content.ClipData.Item}:
+</p>
+<dl>
+ <dt><em>Text</em></dt>
+ <dd>
+ If {@link android.content.ClipData.Item} is text
+ ({@link android.content.ClipData.Item#getText()} is not null),
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns the
+ text.
+ </dd>
+ <dt><em>URI</em></dt>
+ <dd>
+ If {@link android.content.ClipData.Item} is a URI
+ ({@link android.content.ClipData.Item#getUri()} is not null),
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} tries to use
+ it as a content URI:
+ <ul>
+ <li>
+ If the URI is a content URI and the provider can return a text stream,
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+ a text stream.
+ </li>
+ <li>
+ If the URI is a content URI but the provider does not offer a text stream,
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+ a representation of the URI. The representation is the same as that returned by
+ {@link android.net.Uri#toString() Uri.toString()}.
+ </li>
+ <li>
+ If the URI is not a content URI,
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+ a representation of the URI. The representation is the same as that returned by
+ {@link android.net.Uri#toString() Uri.toString()}.
+ </li>
+ </ul>
+ </dd>
+ <dt><em>Intent</em></dt>
+ <dd>
+ If {@link android.content.ClipData.Item} is an Intent
+ ({@link android.content.ClipData.Item#getIntent()} is not null),
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} converts it to
+ an Intent URI and returns it. The representation is the same as that returned by
+ {@link android.content.Intent#toUri(int) Intent.toUri(URI_INTENT_SCHEME)}.
+ </dd>
+</dl>
+<p>
+ The clipboard framework is summarized in Figure 1. To copy data, an application puts a
+ {@link android.content.ClipData} object on the {@link android.content.ClipboardManager} global
+ clipboard. The {@link android.content.ClipData} contains one or more
+ {@link android.content.ClipData.Item} objects and one
+ {@link android.content.ClipDescription} object. To paste data, an application gets the
+ {@link android.content.ClipData}, gets its MIME type from the
+ {@link android.content.ClipDescription}, and gets the data either from
+ the {@link android.content.ClipData.Item} or from the content provider referred to by
+ {@link android.content.ClipData.Item}.
+</p>
+ <a name="framework"></a>
+ <img
+ src="{@docRoot}images/ui/clipboard/copy_paste_framework.png"
+ alt="A block diagram of the copy and paste framework" height="400px" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> The Android clipboard framework
+</p>
+<h2 id="Copying">Copying to the Clipboard</h2>
+<p>
+ As described previously, to copy data to the clipboard you get a handle to the global
+ {@link android.content.ClipboardManager} object, create a {@link android.content.ClipData}
+ object, add a {@link android.content.ClipDescription} and one or more
+ {@link android.content.ClipData.Item} objects to it, and add the finished
+ {@link android.content.ClipData} object to the {@link android.content.ClipboardManager} object.
+ This is described in detail in the following procedure:
+</p>
+<ol>
+ <li>
+ If you are copying data using a content URI, set up a content
+ provider.
+ <p>
+ The <a href="{@docRoot}resources/samples/NotePad/index.html">
+ Note Pad</a> sample application is an example of using a content provider for
+ copying and pasting. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html">
+ NotePadProvider</a> class implements the content provider. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePad.html">
+ NotePad</a> class defines a contract between the provider and other applications,
+ including the supported MIME types.
+ </p>
+ </li>
+ <li>
+ Get the system clipboard:
+<pre>
+
+...
+
+// if the user selects copy
+case R.id.menu_copy:
+
+// Gets a handle to the clipboard service.
+ClipboardManager clipboard = (ClipboardManager)
+ getSystemService(Context.CLIPBOARD_SERVICE);
+</pre>
+ </li>
+ <li>
+ <p>
+ Copy the data to a new {@link android.content.ClipData} object:
+ </p>
+ <ul>
+ <li>
+ <h4>For text</h4>
+<pre>
+// Creates a new text clip to put on the clipboard
+ClipData clip = ClipData.newPlainText(&quot;simple text&quot;,&quot;Hello, World!&quot;);
+</pre>
+ </li>
+ <li>
+ <h4>For a URI</h4>
+ <p>
+ This snippet constructs a URI by encoding a record ID onto the content URI
+ for the provider. This technique is covered in more detail
+ in the section <a href="#Encoding">Encoding an identifier on the URI</a>:
+ </p>
+<pre>
+// Creates a Uri based on a base Uri and a record ID based on the contact's last name
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares the Uri to paste to the clipboard
+Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + &quot;/&quot; + lastName);
+
+...
+
+// Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
+// get MIME types from provider. The clip object's label is &quot;URI&quot;, and its data is
+// the Uri previously created.
+ClipData clip = ClipData.newUri(getContentResolver(),&quot;URI&quot;,copyUri);
+</pre>
+ </li>
+ <li>
+ <h4>For an Intent</h4>
+ <p>
+ This snippet constructs an Intent for an application
+ and then puts it in the clip object:
+ </p>
+<pre>
+// Creates the Intent
+Intent appIntent = new Intent(this, com.example.demo.myapplication.class);
+
+...
+
+// Creates a clip object with the Intent in it. Its label is &quot;Intent&quot; and its data is
+// the Intent object created previously
+ClipData clip = ClipData.newIntent(&quot;Intent&quot;,appIntent);
+</pre>
+ </li>
+ </ul>
+ </li>
+ <li>
+ Put the new clip object on the clipboard:
+<pre>
+// Set the clipboard's primary clip.
+clipboard.setPrimaryClip(clip);
+</pre>
+ </li>
+</ol>
+<h2 id="Pasting">Pasting from the Clipboard</h2>
+<p>
+ As 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 describes in detail how to do this for
+ the three forms of clipboard data.
+</p>
+<h3 id="PastePlainText">Pasting plain text</h3>
+<p>
+ To 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
+ {@link android.content.ClipData.Item#getText()}, as described in the following procedure:
+</p>
+<ol>
+ <li>
+ Get the global {@link android.content.ClipboardManager} object using
+ {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}. Also
+ declare a global variable to contain the pasted text:
+<pre>
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+String pasteData = &quot;&quot;;
+
+</pre>
+ </li>
+ <li>
+ Next, determine if you should enable or disable the &quot;paste&quot; option in the
+ current Activity. You should verify that the clipboard contains a clip and that you
+ can handle the type of data represented by the clip:
+<pre>
+// Gets the ID of the &quot;paste&quot; menu item
+MenuItem mPasteItem = menu.findItem(R.id.menu_paste);
+
+// If the clipboard doesn't contain data, disable the paste menu item.
+// If it does contain data, decide if you can handle the data.
+if (!(clipboard.hasPrimaryClip())) {
+
+ mPasteItem.setEnabled(false);
+
+ } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
+
+ // This disables the paste menu item, since the clipboard has data but it is not plain text
+ mPasteItem.setEnabled(false);
+ } else {
+
+ // This enables the paste menu item, since the clipboard contains plain text.
+ mPasteItem.setEnabled(true);
+ }
+}
+</pre>
+ </li>
+ <li>
+ Copy the data from the clipboard. This point in the program is only reachable if the
+ &quot;paste&quot; menu item is enabled, so you can assume that the clipboard contains
+ plain text. You do not yet know if it contains a text string or a URI that points to plain
+ text. The following snippet tests this, but it only shows the code for handling plain text:
+<pre>
+// Responds to the user selecting &quot;paste&quot;
+case R.id.menu_paste:
+
+// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
+// text. Assumes that this application can only handle one item at a time.
+ ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
+
+// Gets the clipboard as text.
+pasteData = item.getText();
+
+// If the string contains data, then the paste operation is done
+if (pasteData != null) {
+ return;
+
+// The clipboard does not contain text. If it contains a URI, attempts to get data from it
+} else {
+ Uri pasteUri = item.getUri();
+
+ // If the URI contains something, try to get text from it
+ if (pasteUri != null) {
+
+ // calls a routine to resolve the URI and get data from it. This routine is not
+ // presented here.
+ pasteData = resolveUri(Uri);
+ return;
+ } else {
+
+ // Something is wrong. The MIME type was plain text, but the clipboard does not contain either
+ // text or a Uri. Report an error.
+ Log.e(&quot;Clipboard contains an invalid data type&quot;);
+ return;
+ }
+}
+</pre>
+ </li>
+</ol>
+<h3 id="PasteContentUri">Pasting data from a content URI</h3>
+<p>
+ If the {@link android.content.ClipData.Item} object contains a content URI and you
+ have determined that you can handle one of its MIME types, create a
+ {@link android.content.ContentResolver} and then call the appropriate content provider
+ method to retrieve the data.
+</p>
+<p>
+ 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:
+</p>
+<ol>
+ <li>
+ Declare a global variable to contain the MIME type:
+<pre>
+// Declares a MIME type constant to match against the MIME types offered by the provider
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+ </li>
+ <li>
+ Get the global clipboard. Also get a content resolver so you can access the content
+ provider:
+<pre>
+// Gets a handle to the Clipboard Manager
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+// Gets a content resolver instance
+ContentResolver cr = getContentResolver();
+</pre>
+ </li>
+ <li>
+ Get the primary clip from the clipboard, and get its contents as a URI:
+<pre>
+// Gets the clipboard data from the clipboard
+ClipData clip = clipboard.getPrimaryClip();
+
+if (clip != null) {
+
+ // Gets the first item from the clipboard data
+ ClipData.Item item = clip.getItemAt(0);
+
+ // Tries to get the item's contents as a URI
+ Uri pasteUri = item.getUri();
+</pre>
+ </li>
+ <li>
+ Test to see if the URI is a content URI by calling
+ {@link android.content.ContentResolver#getType(Uri) getType(Uri)}. This method returns
+ null if <code>Uri</code> does not point to a valid content provider:
+<pre>
+ // If the clipboard contains a URI reference
+ if (pasteUri != null) {
+
+ // Is this a content URI?
+ String uriMimeType = cr.getType(pasteUri);
+</pre>
+ </li>
+ <li>
+ Test to see if the content provider supports a MIME type that the current application
+ understands. If it does, call
+ {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+ ContentResolver.query()} to get the data. The return value is a
+ {@link android.database.Cursor}:
+<pre>
+ // If the return value is not null, the Uri is a content Uri
+ if (uriMimeType != null) {
+
+ // Does the content provider offer a MIME type that the current application can use?
+ if (uriMimeType.equals(MIME_TYPE_CONTACT)) {
+
+ // Get the data from the content provider.
+ Cursor pasteCursor = cr.query(uri, null, null, null, null);
+
+ // If the Cursor contains data, move to the first record
+ if (pasteCursor != null) {
+ if (pasteCursor.moveToFirst()) {
+
+ // get the data from the Cursor here. The code will vary according to the
+ // format of the data model.
+ }
+ }
+
+ // close the Cursor
+ pasteCursor.close();
+ }
+ }
+ }
+}
+</pre>
+ </li>
+</ol>
+<h3 id="PasteIntent">Pasting an Intent</h3>
+<p>
+ To paste an Intent, first get the global clipboard. Examine the
+ {@link android.content.ClipData.Item} object to see if it contains an Intent. Then call
+ {@link android.content.ClipData.Item#getIntent()} to copy the Intent to your own storage.
+ The following snippet demonstrates this:
+</p>
+<pre>
+// 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
+}
+</pre>
+<h2 id="Provider">Using Content Providers to Copy Complex Data</h2>
+<p>
+ Content 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.
+</p>
+<p>
+ 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.
+</p>
+<p>
+ 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.
+</p>
+<h3 id="Encoding">Encoding an identifier on the URI</h3>
+<p>
+ A 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 &quot;reference&quot; (the URI plus the identifier) from
+ the clipboard, give it your content provider, and get back the data.
+</p>
+<p>
+ 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:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;
+</pre>
+<p>
+ If you want to encode a name onto this URI, you would use the following snippet:
+</p>
+<pre>
+String uriString = &quot;content:&#47;&#47;com.example.contacts&quot; + &quot;/&quot; + &quot;Smith&quot;
+
+// uriString now contains content://com.example.contacts/Smith.
+
+// Generates a uri object from the string representation
+Uri copyUri = Uri.parse(uriString);
+</pre>
+<p>
+ 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:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;/people
+&quot;content://com.example.contacts&quot;/people/detail
+&quot;content://com.example.contacts&quot;/people/images
+</pre>
+<p>
+ You could add another path that is specific to copy URIs:
+</p>
+<pre>
+&quot;content://com.example.contacts/copying&quot;
+</pre>
+<p>
+ You could then detect a &quot;copy&quot; URI by pattern-matching and handle it with code that
+ is specific for copying and pasting.
+</p>
+<p>
+ 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.
+</p>
+<p>
+ 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.
+</p>
+<p>
+ Getting a single record by ID is used in the
+ <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample application to
+ open a note from the notes list. The sample uses the <code>_id</code> field from an SQL
+ database, but you can have any numeric or character identifier you want.
+</p>
+<h3 id="Records">Copying data structures</h3>
+<p>
+ You set up a content provider for copying and pasting complex data as a subclass of the
+ {@link android.content.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:
+</p>
+<ul>
+ <li>
+ If you already have a content provider, you can add to its functionality. You may only
+ need to modify its
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+ method to handle URIs coming from applications that want to paste data. You will
+ probably want to modify the method to handle a &quot;copy&quot; URI pattern.
+ </li>
+ <li>
+ If your application maintains an internal database, you may
+ want to move this database into a content provider to facilitate copying from it.
+ </li>
+ <li>
+ If you are not currently using a database, you can implement a simple content provider
+ whose sole purpose is to offer data to applications that are pasting from the
+ clipboard.
+ </li>
+</ul>
+<p>
+In the content provider, you will want to override at least the following methods:
+</p>
+<dl>
+ <dt>
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+ </dt>
+ <dd>
+ 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 &quot;copy&quot; path. Your application can then
+ create a &quot;copy&quot; URI to put on the clipboard, containing the copy path and
+ a pointer to the exact record you want to copy.
+ </dd>
+ <dt>
+ {@link android.content.ContentProvider#getType(Uri) getType()}
+ </dt>
+ <dd>
+ This method should return the MIME type or types for the data you intend to copy. The method
+ {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()} calls
+ {@link android.content.ContentProvider#getType(Uri) getType()} in order to put the MIME
+ types into the new {@link android.content.ClipData} object.
+ <p>
+ MIME types for complex data are described in the topic
+ <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+ </p>
+ </dd>
+</dl>
+<p>
+ Notice that you don't have to have any of the other content provider methods such as
+ {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} or
+ {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) 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.
+</p>
+<p>
+ The following snippets demonsrate how to set up your application to copy complex data:
+</p>
+<ol>
+ <li>
+ <p>
+ In the global constants for your application,
+ declare a base URI string and a path that identifies URI strings you are
+ using to copy data. Also declare a MIME type for the copied data:
+ </p>
+<pre>
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares a MIME type for the copied data
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+ </li>
+ <li>
+ In the Activity from which users copy data,
+ set up the code to copy data to the clipboard. In response to a copy request, put
+ the URI on the clipboard:
+<pre>
+public class MyCopyActivity extends Activity {
+
+ ...
+
+// The user has selected a name and is requesting a copy.
+case R.id.menu_copy:
+
+ // Appends the last name to the base URI
+ // The name is stored in &quot;lastName&quot;
+ uriString = CONTACTS + COPY_PATH + &quot;/&quot; + lastName;
+
+ // Parses the string into a URI
+ Uri copyUri = Uri.parse(uriString);
+
+ // Gets a handle to the clipboard service.
+ ClipboardManager clipboard = (ClipboardManager)
+ getSystemService(Context.CLIPBOARD_SERVICE);
+
+ ClipData clip = ClipData.newUri(getContentResolver(), &quot;URI&quot;, copyUri);
+
+ // Set the clipboard's primary clip.
+ clipboard.setPrimaryClip(clip);
+</pre>
+ </li>
+
+ <li>
+ <p>
+ In the global scope of your content provider, create a URI matcher and add a URI
+ pattern that will match URIs you put on the clipboard:
+ </p>
+<pre>
+public class MyCopyProvider extends ContentProvider {
+
+ ...
+
+// A Uri Match object that simplifies matching content URIs to patterns.
+private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+// An integer to use in switching based on the incoming URI pattern
+private static final int GET_SINGLE_CONTACT = 0;
+
+...
+
+// Adds a matcher for the content URI. It matches
+// &quot;content://com.example.contacts/copy/*&quot;
+sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);
+</pre>
+ </li>
+ <li>
+ <p>
+ Set up the
+ {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) query()}
+ method. This method can handle different URI patterns, depending on how you code it, but
+ only the pattern for the clipboard copying operation is shown:
+ </p>
+<pre>
+// Sets up your provider's query() method.
+public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+
+ ...
+
+ // Switch based on the incoming content URI
+ switch (sUriMatcher.match(uri)) {
+
+ case GET_SINGLE_CONTACT:
+
+ // query and return the contact for the requested name. Here you would decode
+ // the incoming URI, query the data model based on the last name, and return the result
+ // as a Cursor.
+
+ ...
+
+}
+</pre>
+ </li>
+ <li>
+ <p>
+ Set up the {@link android.content.ContentProvider#getType(Uri) getType()} method to
+ return an appropriate MIME type for copied data:
+ </p>
+<pre>
+// Sets up your provider's getType() method.
+public String getType(Uri uri) {
+
+ ...
+
+ switch (sUriMatcher.match(uri)) {
+
+ case GET_SINGLE_CONTACT:
+
+ return (MIME_TYPE_CONTACT);
+</pre>
+ </li>
+</ol>
+<p>
+ The section <a href="#PasteContentUri">Pasting data from a content URI</a>
+ describes how to get a content URI from the clipboard and use it to get and paste data.
+</p>
+<h3 id="Streams">Copying data streams</h3>
+<p>
+ You can copy and paste large amounts of text and binary data as streams. The data can have
+ forms such as the following:
+</p>
+ <ul>
+ <li>
+ Files stored on the actual device.
+ </li>
+ <li>
+ Streams from sockets.
+ </li>
+ <li>
+ Large amounts of data stored in a provider's underlying database system.
+ </li>
+ </ul>
+<p>
+ A content provider for data streams provides access to its data with a file descriptor object
+ such as {@link android.content.res.AssetFileDescriptor} instead of a
+ {@link android.database.Cursor} object. The pasting application reads the data stream using
+ this file descriptor.
+</p>
+<p>
+ To set up your application to copy a data stream with a provider, follow these steps:
+</p>
+<ol>
+ <li>
+ Set up a content URI for the data stream you are putting on the clipboard. Options
+ for doing this include the following:
+ <ul>
+ <li>
+ Encode an identifier for the data stream onto the URI,
+ as described in the section
+ <a href="#Encoding">Encoding an identifier on the URI</a>, and then maintain a
+ table in your provider that contains identifiers and the corresponding stream name.
+ </li>
+ <li>
+ Encode the stream name directly on the URI.
+ </li>
+ <li>
+ Use a unique URI that always returns the current stream from the provider. If you
+ use this option, you have to remember to update your provider to point to a
+ different stream whenever you copy the stream to the clipboard via the URI.
+ </li>
+ </ul>
+ </li>
+ <li>
+ Provide a MIME type for each type of data stream you plan to offer. Pasting applications
+ need this information to determine if they can paste the data on the clipboard.
+ </li>
+ <li>
+ Implement one of the {@link android.content.ContentProvider} methods that returns
+ a file descriptor for a stream. If you encode identifiers on the content URI, use this
+ method to determine which stream to open.
+ </li>
+ <li>
+ To copy the data stream to the clipboard, construct the content URI and place it
+ on the clipboard.
+ </li>
+</ol>
+<p>
+ To paste a data stream, an application gets the clip from the clipboard, gets the URI, and
+ uses it in a call to a {@link android.content.ContentResolver} file descriptor method that
+ opens the stream. The {@link android.content.ContentResolver} method calls the corresponding
+ {@link android.content.ContentProvider} method, passing it the content URI. Your provider
+ returns the file descriptor to {@link android.content.ContentResolver} method. The pasting
+ application then has the responsibility to read the data from the stream.
+</p>
+<p>
+ The following list shows the most important file descriptor methods for a content provider.
+ Each of these has a corresponding {@link android.content.ContentResolver} method with the
+ string &quot;Descriptor&quot; appended to the method name; for example, the
+ {@link android.content.ContentResolver} analog of
+ {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()} is
+{@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) openAssetFileDescriptor()}:
+</p>
+<dl>
+ <dt>
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}
+ </dt>
+ <dd>
+ 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 {@link android.content.res.AssetFileDescriptor} file handle if it
+ can provide that MIME type, or throws an exception if it can not.
+ <p>
+ This method handles subsections of files. You can use it to read assets that the
+ content provider has copied to the clipboard.
+ </p>
+ </dd>
+ <dt>
+ {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}
+ </dt>
+ <dd>
+ This method is a more general form of
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}.
+ It does not filter for allowed MIME types, but it can read subsections of files.
+ </dd>
+ <dt>
+ {@link android.content.ContentProvider#openFile(Uri, String) openFile()}
+ </dt>
+ <dd>
+ This is a more general form of
+ {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}. It can't
+ read subsections of files.
+ </dd>
+</dl>
+<p>
+ You can optionally use the
+{@link android.content.ContentProvider#openPipeHelper(Uri, String, Bundle, T, ContentProvider.PipeDataWriter) 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
+ {@link android.content.ContentProvider.PipeDataWriter} interface. An example of doing this is
+ given in the <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample
+ application, in the <code>openTypedAssetFile()</code> method of
+ <code>NotePadProvider.java</code>.
+</p>
+<h2 id="DataDesign">Designing Effective Copy/Paste Functionality</h2>
+<p>
+ To design effective copy and paste functionality for your application, remember these
+ points:
+</p>
+ <ul>
+ <li>
+ At any time, there is only one clip on the clipboard. A new copy operation by
+ any application in the system overwrites the previous clip. Since the user may
+ navigate away from your application and do a copy before returning, you can't assume
+ that the clipboard contains the clip that the user previously copied in <em>your</em>
+ application.
+ </li>
+ <li>
+ The intended purpose of multiple {@link android.content.ClipData.Item}
+ objects per clip is to support copying and pasting of multiple selections rather than
+ different forms of reference to a single selection. You usually want all of the
+ {@link android.content.ClipData.Item} objects in a clip to have the same form, that is,
+ they should all be simple text, content URI, or {@link android.content.Intent}, but not
+ a mixture.
+ </li>
+ <li>
+ When you provide data, you can offer different MIME representations. Add the MIME types
+ you support to the {@link android.content.ClipDescription}, and then
+ implement the MIME types in your content provider.
+ </li>
+ <li>
+ When you get data from the clipboard, your application is responsible for checking the
+ available MIME types and then deciding which one, if any, to use. Even if there is a
+ clip on the clipboard and the user requests a paste, your application is not required
+ to do the paste. You <em>should</em> do the paste if the MIME type is compatible. You
+ may choose to coerce the data on the clipboard to text using
+ {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} if you
+ choose. If your application supports more than one of the available MIME types, you can
+ allow the user to choose which one to use.
+ </li>
+ </ul>