文本和输入:复制和粘贴

Android提供了一个功能强大的基于剪贴板的复制和粘贴框架。 它支持简单和复杂的数据类型,包括文本字符串,复杂数据结构,文本和二进制流数据,甚至应用程序资产。 简单的文本数据直接存储在剪贴板中,而复杂数据则作为粘贴应用程序与内容提供者解析的参考进行存储。 复制和粘贴在应用程序中以及在实现框架的应用程序之间工作。


由于框架的一部分使用内容提供者,因此本主题假定您熟悉Android内容提供程序API,这里是其描述:内容提供者



一、剪贴板框架

使用剪贴板框架时,将数据放入剪辑对象中,然后将剪辑对象放在系统范围的剪贴板上。 剪辑对象可以采用三种形式之一:

1、Text

一个文本字符串。 您将字符串直接放入剪辑对象中,然后将其放在剪贴板上。 要粘贴字符串,您可以从剪贴板中获取剪辑对象,并将该字符串复制到应用程序的存储空间中。


2、URI

一个Uri对象表示URI的任何形式。这主要用于复制内容提供商的复杂数据。 要复制数据,您将Uri对象放入剪辑对象中,并将剪辑对象放在剪贴板上。 要粘贴数据,您将获取剪辑对象,获取Uri对象,将其解析为数据源(如内容提供者),并将数据从源代码复制到应用程序的存储中。


3、Intent

意图。 这支持复制应用程序快捷方式。 要复制数据,您将创建一个Intent,将其放入剪辑对象中,并将剪辑对象放在剪贴板上。 要粘贴数据,您将获取剪辑对象,然后将Intent对象复制到应用程序的内存区域。


剪贴板一次只保留一个剪辑对象。 当应用程序将剪辑对象放在剪贴板上时,上一个剪辑对象消失。


如果要允许用户将数据粘贴到应用程序中,则不必处理所有类型的数据。 在给用户选择粘贴之前,您可以检查剪贴板上的数据。 除了具有某种数据形式之外,剪辑对象还包含可以告诉您哪些MIME类型或类型可用的元数据。 此元数据可帮助您决定应用程序是否可以对剪贴板数据进行有用的操作。 例如,如果您有一个主要处理文本的应用程序,则可能需要忽略包含URI或Intent的剪辑对象。


您可能还希望允许用户粘贴文本,而不管剪贴板上的数据形式如何。 为此,您可以强制剪贴板数据进入文本表示,然后粘贴此文本。 这将在将剪贴板强制为文本的部分中进行描述。



二、剪贴板类

本节介绍剪贴板框架使用的类。


一)、ClipboardManager

在Android系统中,系统剪贴板由全局ClipboardManager类表示。 你不直接实例化这个类; 而是通过调用getSystemService(CLIPBOARD_SERVICE)来获得对它的引用。


二)、ClipData,ClipData.Item和ClipDescription

要将数据添加到剪贴板,您将创建一个ClipData对象,其中包含数据和数据本身的描述。 剪贴板一次只保留一个ClipData。 ClipData包含一个ClipDescription对象和一个或多个ClipData.Item对象。


ClipDescription对象包含有关剪辑的元数据。 特别地,它包含剪辑数据的可用MIME类型的数组。 当您将剪辑放在剪贴板上时,此阵列可用于粘贴应用程序,可以检查它是否可以处理任何可用的MIME类型。


ClipData.Item对象包含文本,URI或Intent数据:

1、Text

一个CharSequence.


2、URI

一个Uri。这通常包含内容提供商URI,尽管允许任何URI。 提供数据的应用程序将URI放在剪贴板上。 想要粘贴数据的应用程序从剪贴板获取URI,并使用它访问内容提供程序(或其他数据源)并检索数据。


3、Intent

意图。 此数据类型允许您将应用程序快捷方式复制到剪贴板。 用户可以将快捷方式粘贴到应用程序中以备以后使用。


您可以向剪辑添加多个ClipData.Item对象。 这允许用户将多个选择复制并粘贴为单个剪辑。 例如,如果您有一个列表窗口小部件,允许用户一次选择多个项目,则可以将所有项目一次复制到剪贴板。 为此,您可以为每个列表项创建一个单独的ClipData.Item,然后将ClipData.Item对象添加到ClipData对象。


三)、ClipData便捷方法

ClipData类提供了使用单个ClipData.Item对象和简单的ClipDescription对象创建ClipData对象的静态便捷方法:
newPlainText(label, text)
返回一个ClipData对象,该对象的单个ClipData.Item对象包含一个文本字符串。 ClipDescription对象的标签设置为标签。 ClipDescription中的单个MIME类型为MIMETYPE_TEXT_PLAIN。
使用newPlainText()从文本字符串创建一个剪辑。

newUri(resolver, label, URI)
返回一个ClipData对象,该对象的单个ClipData.Item对象包含一个URI。 ClipDescription对象的标签设置为标签。 如果URI是内容URI(Uri.getScheme()返回内容:),则该方法使用解析器中提供的ContentResolver对象从内容提供者检索可用的MIME类型并将其存储在ClipDescription中。 对于不是内容的URI:URI,该方法将MIME类型设置为MIMETYPE_TEXT_URILIST。
使用newUri()从URI创建一个剪辑,特别是一个内容:URI。

newIntent(label, intent)
返回一个ClipData对象,该对象的单个ClipData.Item对象包含一个Intent。 ClipDescription对象的标签设置为标签。 MIME类型设置为MIMETYPE_TEXT_INTENT。
使用newIntent()从Intent对象创建一个剪辑。


四)、将剪贴板数据强制转换为文本
即使您的应用程序只处理文本,您可以通过使用ClipData.Item.coerceToText()方法转换剪贴板来复制非文本数据。

此方法将ClipData.Item中的数据转换为文本并返回CharSequence。 ClipData.Item.coerceToText()返回的值基于ClipData.Item中数据的形式:
1、Text
如果ClipData.Item是text(getText()不为null),coerceToText()返回文本。

2、URI
如果ClipData.Item是一个URI(getUri()不为空),coerceToText()将尝试将其用作内容URI:
1)、如果URI是内容URI,并且提供者可以返回文本流,则coerceToText()返回文本流。
2)、如果URI是内容URI,但提供者不提供文本流,则coerceToText()返回URI的表示形式。 该表示与Uri.toString()返回的表示相同。
3)、如果URI不是内容URI,则coerceToText()返回URI的表示形式。 该表示与Uri.toString()返回的表示相同。

3、intent
如果ClipData.Item是一个Intent(getIntent()不为null),coerceToText()将它转换为Intent URI并返回它。 该表示与Intent.toUri(URI_INTENT_SCHEME)返回的表示相同。

剪贴板框架总结在图1中。要复制数据,应用程序将ClipData对象放在ClipboardManager全局剪贴板上。 ClipData包含一个或多个ClipData.Item对象和一个ClipDescription对象。 要粘贴数据,应用程序将获取ClipData,从ClipDescription获取其MIME类型,并从ClipData.Item或ClipData.Item引用的内容提供者获取数据。


图1. Android剪贴板框架



三、复制到剪贴板
如前所述,要将数据复制到剪贴板,您可以获取全局ClipboardManager对象的句柄,创建一个ClipData对象,向其中添加一个ClipDescription和一个或多个ClipData.Item对象,并将完成的ClipData对象添加到ClipboardManager对象。 这将在以下过程中详细描述:
1、如果您使用内容URI复制数据,请设置内容提供商。
Note Pad示例应用程序是使用内容提供商进行复制和粘贴的示例。 NotePadProvider类实现内容提供者。 NotePad类定义了提供程序和其他应用程序之间的合同,包括支持的MIME类型。

2、获取系统剪贴板:
...

// if the user selects copy
case R.id.menu_copy:

// Gets a handle to the clipboard service.
ClipboardManager clipboard = (ClipboardManager)
        getSystemService(Context.CLIPBOARD_SERVICE);

3、将数据复制到新的ClipData对象:
 1)、对于文本
// Creates a new text clip to put on the clipboard
ClipData clip = ClipData.newPlainText("simple text", "Hello, World!");
 2)、对于Uri
该片段通过将记录ID编码到提供者的内容URI上来构造URI。 该技术在URI中编码标识符的部分中有更详细的介绍:
// 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 = "content://com.example.contacts";

// Declares a path string for URIs that you use to copy data
private static final String COPY_PATH = "/copy";

// Declares the Uri to paste to the clipboard
Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + "/" + 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 "URI", and its data is
// the Uri previously created.
ClipData clip = ClipData.newUri(getContentResolver(), "URI", copyUri);
 3)、对于意图
此片段为应用程序构建一个Intent,然后将其放在剪辑对象中:
// 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 "Intent" and its data is
// the Intent object created previously
ClipData clip = ClipData.newIntent("Intent", appIntent);


4、将新剪辑对象放在剪贴板上:
// Set the clipboard's primary clip.
clipboard.setPrimaryClip(clip);


四、从剪贴板粘贴
如前所述,您可以通过获取全局剪贴板对象,获取剪辑对象,查看其数据以及如果可能将剪辑对象中的数据复制到自己的存储中,从剪贴板粘贴数据。 本节详细介绍如何为三种形式的剪贴板数据进行此操作。

一)、粘贴纯文本
要粘贴纯文本,首先获取全局剪贴板,并确认它可以返回纯文本。 然后获取剪辑对象,并使用getText()将其文本复制到您自己的存储中,如以下过程所述:
1、使用getSystemService(CLIPBOARD_SERVICE)获取全局ClipboardManager对象。 还声明一个全局变量来包含粘贴的文本:
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String pasteData = "";

2、接下来,确定是否应启用或禁用当前活动中的“粘贴”选项。 您应该验证剪贴板是否包含剪辑,并且可以处理由剪辑表示的数据类型:
// Gets the ID of the "paste" 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);
    }
}

3、复制剪贴板中的数据。 程序中的这一点只有在“粘贴”菜单项启用时才可以访问,因此您可以假设剪贴板包含纯文本。 您还不知道它是否包含指向纯文本的文本字符串或URI。 以下代码片段测试这个,但它只显示处理纯文本的代码:
// Responds to the user selecting "paste"
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("Clipboard contains an invalid data type");
    return;
    }
}


二)、从内容URI粘贴数据
如果ClipData.Item对象包含内容URI,并且您确定可以处理其中一种MIME类型,请创建一个ContentResolver,然后调用适当的内容提供方法来检索数据。

以下过程描述了如何根据剪贴板上的内容URI从内容提供商获取数据。 它检查应用程序可以使用的MIME类型,其可从提供程序获得:

1、声明一个全局变量来包含MIME类型:
// Declares a MIME type constant to match against the MIME types offered by the provider
public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";

2、获取全局剪贴板。 还得到一个内容解析器,以便您可以访问内容提供者:
// Gets a handle to the Clipboard Manager
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);

// Gets a content resolver instance
ContentResolver cr = getContentResolver();

3、从剪贴板获取主剪辑,并将其内容作为URI获取:
// 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();

4、通过调用getType(Uri)来测试URI是否是内容URI。 如果Uri不指向有效的内容提供者,则此方法返回null:
// If the clipboard contains a URI reference
    if (pasteUri != null) {

        // Is this a content URI?
        String uriMimeType = cr.getType(pasteUri);


5、测试以查看内容提供者是否支持当前应用程序理解的MIME类型。 如果是,请调用ContentResolver.query()获取数据。 返回值是一个Cursor:
// 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();
             }
         }
     }
}


三)、粘贴意图
要粘贴意图,首先获取全局剪贴板。 检查ClipData.Item对象,看它是否包含一个Intent。 然后调用getIntent()将Intent复制到您自己的存储。 以下代码段演示如下:
// 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
}


五、使用内容提供商复制复杂数据
内容提供商支持复制数据,如数据库记录或文件流。 要复制数据,您将内容URI放在剪贴板上。 粘贴应用程序然后从剪贴板获取此URI,并使用它来检索数据库数据或文件流描述符。

由于粘贴应用程序仅具有数据的内容URI,因此需要知道要检索的数据。 您可以通过编码URI本身上的数据的标识符来提供此信息,或者您可以提供将返回要复制的数据的唯一URI。 您选择的技术取决于您的数据的组织。

以下部分介绍如何设置URI,如何提供复杂数据以及如何提供文件流。 这些描述假设您熟悉内容提供商设计的一般原则。

一)、在URI上编码标识符
使用URI将数据复制到剪贴板的有用技术是对URI本身上的数据进行编码。 然后,您的内容提供商可以从URI获取标识符,并使用它来检索数据。 粘贴应用程序不必知道标识符存在; 所有它必须做的是从剪贴板获取你的“参考”(URI加标识符),给它你的内容提供者,并获取数据。

通常,通过将标识符连接到URI的末尾来将标识符编码到内容URI上。 例如,假设您将提供者URI定义为以下字符串:
"content://com.example.contacts"

如果要将名称编码到此URI上,则可以使用以下代码段:
String 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);

如果您已经在使用内容提供商,则可能需要添加一个新的URI路径,以指示URI用于复制。 例如,假设您已经具有以下URI路径:
"content://com.example.contacts"/people
"content://com.example.contacts"/people/detail
"content://com.example.contacts"/people/images

您可以添加另一个特定于复制URI的路径:
"content://com.example.contacts/copying"

然后,您可以通过模式匹配检测“copy”URI,并使用特定于复制和粘贴的代码处理它。

如果您已经在使用内容提供程序,内部数据库或内部表来组织数据,则通常使用编码技术。 在这些情况下,您有多个要复制的数据,大概是每个片段的唯一标识符。为了 响应来自粘贴应用程序的查询,您可以通过其标识符查找数据并返回。

如果您没有多个数据段,则可能不需要对标识符进行编码。 您可以简单地使用您的提供商唯一的URI。 为了响应查询,您的提供器将返回其当前包含的数据。

通过使用在笔记本实例应用程序中来打开从笔记本列表中打开一个注释的ID,来获取单个记录。该示例使用SQL数据库中的_id字段,但您可以具有所需的任何数字或字符标识符。


二)、复制数据结构
您设置了一个内容提供者,用于复制和粘贴复杂数据作为ContentProvider组件的子类。 您还应该编码您放在剪贴板上的URI,以便它指向要提供的确切记录。 此外,您必须考虑应用程序的现有状态:
1、如果您已经有内容提供商,您可以添加其功能。 您可能只需要修改其query()方法来处理来自想要粘贴数据的应用程序的URI。 您可能需要修改方法来处理“copy”URI模式。

2、如果您的应用程序维护内部数据库,则可能需要将此数据库移动到内容提供程序中,以便于从中复制。

3、如果您当前没有使用数据库,您可以实现一个简单的内容提供商,其唯一目的是向从剪贴板粘贴的应用程序提供数据。

在内容提供商中,您至少要覆盖以下方法:
query()
粘贴应用程序将假设他们可以通过使用此方法获取您的数据与您放在剪贴板上的URI。 为了支持复制,您应该使用此方法来检测包含特殊“copy”路径的URI。 然后,您的应用程序可以创建一个“copy”URI以放在剪贴板上,其中包含复制路径和指向要复制的确切记录的指针。

getType()
此方法应返回您要复制的数据的MIME类型或类型。 方法newUri()调用getType(),以便将MIME类型放入新的ClipData对象。

主题“内容提供商”中介绍了复杂数据的MIME类型。

请注意,您不必具有任何其他内容提供器的方法,例如insert()或update()。 粘贴应用程序只需要获得您支持的MIME类型并从您的提供器复制数据。 如果您已经有这些方法,它们不会干扰复制操作。

以下代码演示了如何设置应用程序以复制复杂数据:
1、在应用程序的全局常量中,声明一个基本URI字符串和一个标识用于复制数据的URI字符串的路径。 还声明复制数据的MIME类型:
// Declares the base URI string
private static final String CONTACTS = "content://com.example.contacts";

// Declares a path string for URIs that you use to copy data
private static final String COPY_PATH = "/copy";

// Declares a MIME type for the copied data
public static final String MIME_TYPE_CONTACT = "vnd.android.cursor.item/vnd.example.contact";

2、在用户复制数据的活动中,设置代码将数据复制到剪贴板。 响应复制请求,将URI放在剪贴板上:
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 "lastName"
    uriString = CONTACTS + COPY_PATH + "/" + 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(), "URI", copyUri);

    // Set the clipboard's primary clip.
    clipboard.setPrimaryClip(clip);

3、在您的内容提供器的全球范围内,创建一个URI匹配器,并添加一个与您放在剪贴板上的URI匹配的URI模式:

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
// "content://com.example.contacts/copy/*"
sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);

4、设置query()方法。 该方法可以根据您的代码如何处理不同的URI模式,但仅显示剪贴板复制操作的模式:

// 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.

    ...

}

5、设置getType()方法为复制的数据返回适当的MIME类型:

// Sets up your provider's getType() method.
public String getType(Uri uri) {
    ...

    switch (sUriMatcher.match(uri)) {
    case GET_SINGLE_CONTACT:
        return (MIME_TYPE_CONTACT);
    ...
    }
}

从内容URI粘贴数据的部分描述了如何从剪贴板获取内容URI,并使用它来获取和粘贴数据。


三)、复制数据流

您可以将大量文本和二进制数据复制并粘贴为流。 数据可以具有以下形式:

1、存储在实际设备上的文件。

2、来自套接口的流。

3、存储在提供器底层数据库系统中的大量数据。


数据流的内容提供者使用诸如AssetFileDescriptor之类的文件描述符对象来访问其数据,而不是Cursor对象。 粘贴应用程序使用该文件描述符读取数据流。


要设置应用程序以与提供器一起复制数据流,请按照下列步骤操作:

1、为您放置在剪贴板上的数据流设置内容URI。 这样做的选项包括:

 1)、将数据流的标识符编码到URI上,如在URI上编码标识符一节所述,然后在提供程序中维护包含标识符和相应流名称的表。

 2)、直接在URI上编码流名称。

 3)、使用始终从提供程序返回当前流的唯一URI。 如果您使用此选项,则必须记住,通过URI将流复制到剪贴板时,请更新您的提供器以指向不同的流。


2、为您计划提供的每种类型的数据流提供MIME类型。 粘贴应用程序需要此信息来确定是否可以将数据粘贴到剪贴板上。


3、实现一个ContentProvider方法返回流的文件描述符。 如果您对内容URI上的标识符进行编码,请使用此方法确定要打开的流。


4、要将数据流复制到剪贴板,请构建内容URI并将其放在剪贴板上。


要粘贴数据流,应用程序从剪贴板获取剪辑,获取URI,并在调用打开流的ContentResolver文件描述符方法时使用它。 ContentResolver方法调用相应的ContentProvider方法,传递内容URI。 您的提供器将文件描述符返回到ContentResolver方法。 因此,粘贴应用程序有责任从流中读取数据。


以下列表显示了内容提供者最重要的文件描述符方法。 它们中的每一个都具有相应的ContentResolver方法,其中附加了方法名称的字符串“Descriptor”; 例如,OpenAssetFile()的ContentResolver类似程序是openAssetFileDescriptor():


openTypedAssetFile()

此方法应返回资产文件描述符,但只有提供者支持的MIME类型。 调用者(执行粘贴的应用程序)提供MIME类型模式。 内容提供者(将URI复制到剪贴板的应用程序)返回一个AssetFileDescriptor文件句柄,如果它可以提供该MIME类型,或者如果不能,则会抛出异常。


此方法处理文件的子部分。 您可以使用它来读取内容提供者已经复制到剪贴板的资产。


openAssetFile()

这个方法是一个更通用的openTypedAssetFile()形式。 它不会过滤允许的MIME类型,但它可以读取文件的小节。


openFile()

这是一个更通用的openAssetFile()形式。 它无法读取文件的小节。


您可以选择使用openPipeHelper()方法与文件描述符方法。 这允许粘贴应用程序使用管道读取后台线程中的流数据。 要使用此方法,您需要实现ContentProvider.PipeDataWriter接口。 在NotePad示例应用程序中,在NotePadProvider.java的openTypedAssetFile()方法中给出了一个这样做的例子。



六、设计有效的复制/粘贴功能

要为应用程序设计有效的复制和粘贴功能,请记住以下几点:

1、在任何时候,剪贴板上只有一个剪辑。 系统中任何应用程序的新的复制操作将覆盖上一个剪辑。 由于用户可能会离开您的应用程序并在返回之前执行复制,因此您不能假定剪贴板包含用户以前在应用程序中复制的剪辑。


2、每个剪辑的多个ClipData.Item对象的预期目的是支持复制和粘贴多个选择,而不是对单个选择的不同形式的引用。 您通常希望剪辑中的所有ClipData.Item对象具有相同的形式,即它们应该是简单的文本,内容URI或Intent,而不是混合形式。


3、提供数据时,您可以提供不同的MIME表示。 将支持的MIME类型添加到ClipDescription,然后在内容提供器中实现MIME类型。


4、当您从剪贴板获取数据时,您的应用程序负责检查可用的MIME类型,然后确定要使用的MIME类型。 即使剪贴板上有剪辑,用户要求粘贴,则您的应用程序不需要进行粘贴。 如果MIME类型兼容,您应该进行粘贴。 您可以选择使用coerceToText()将剪贴板上的数据强制转换为文本。 如果您的应用程序支持多种可用MIME类型,您可以允许用户选择要使用的MIME类型。

版权声明:本文为Explorer_day原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Explorer_day/article/details/71255431

智能推荐

Rtthread学习笔记(十三)RT-Thread Studio开启硬件看门狗Watchdog

一、开启硬件看门狗Watchdog 1、配置RT-Thread Settings 2、开启stm32f1xx_hal_conf.h中的宏定义 3.使用RT接口函数初始化硬件看门狗...

TYVJ 4864 天天去哪吃 || 清北学堂金秋杯大奖赛

题目描述: 记录一下i这个值上次出现的位置在哪里,就是pre...

java反编译

jvm 把Boolean类型的值flag当做int类型处理。​​​ Foo.java: 由 class 文件生成 jasm 文件:java -jar asmtools.jar jdis Foo.class > Foo.jasm  修改jasm文件: 执行反编译: java -jar jd-gui-1.6.6.jar File 打开Foo.class文件:b修改为2 重新执行java...

【学习笔记】03-v-html的学习和示例

v-html的认识和使用 示例: 显示结果: 注意:v-html是有复制的...

Java实现在线考试系统(系统介绍)

1.和现在有的考试系统有以下几种优势: a.和现在有的系统比较起来,本系统有科目、章节、老师、学生、班级等信息的管理,还有批阅试卷查看已批阅试卷等。传统的考试系统划分并不细,业务功能简单。 b.和学校的考试系统还有外面的考试系统比较起来,本系统是B/S结构,学校的考试系统一般为C/S结构,性能方面不如B/S结构,并且C/S接口需要安装客户端,客户端压力很大,我的系统只需要电脑具有浏览器,在同一局域...

猜你喜欢

计算机视觉--多视几何初步尝试

基础矩阵的原理 K和K’分别是两个相机的参数矩阵。p和p’是X在平面π的坐标表示。所以可以得出 具体计算过程 代码: #!/usr/bin/env python coding: utf-8 from PIL import Image from numpy import * from pylab import * import numpy as np from imp ...

java初学者怎么学习才可以快速入门

java初学者怎么学习才可以快速入门 一、了解JAVA 我们要知道:Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言。 Java之父:詹姆斯·高斯林 1.1 java的三个体系 Java SE(Java Platform Standard Edition)。Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境...

字段属性之主键&增删改查&自增长&唯一键约束

字段属性之主键&自增长&唯一键约束 主键 主键:primary key 主要的键 一张表中只有一个字段可以使用对应的键,用来唯一的约束该字段里面的数据,不能重复,这种称之为主键 一张表只能最多一个主键 增加主键 SQL操作中有多种方式增加主键大体分为三种 1.在创建表的时候直接在字段之后跟primary key关键字(主键本身不允许为空) 优点:非常直接:缺点:只能使用一个字段作为...

linux下 基于libmad的socket多用户mp3音频在线播放服务器

在众多大神的帮助下,这个在线播放流媒体服务器终于完成啦。。。。 这个mp3流媒体服务器设计的思路是,服务器程序server用多线程实现和多个客户端的通信(这是必然的),然后发送给客户端当前的音频列表公客户端选择,之后根据k客户端的选择给多个客户端传输相应mp3文件的数据,同时,客户端进行实时地音频解码并播放。 关于libmad开源mp3音频解码库的使用,见上一篇博客吧。。。。 在服务器程序这一端,...

Nginx

Nginx Nginx简介: Nginx是一个高性能的http和反向代理服务器,特点是有内存少,并发能力强,事实上Nginx的并发能力确实在同类型网页服务器中表现较好, Nginx用作web服务器:Nginx可以作为静态页面的web服务器,同时还支持CGI语言,但不支持java,java程序只能通过Tomcat配合完成。Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率,能经受...