




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Copy and Paste版本:Android 4.0 r1快速查看 用于复制粘贴数据的基于剪贴板的框架。 同时支持简单和复杂的数据,包括文本串、复杂的数据结构、文本和二进制流数据、程序asset。 直接从剪贴板复制粘贴简单文本。 用content provider复制粘贴复杂数据。 需要API 11版本。在本文中剪贴板框架剪贴板类ClipboardManagerClipData、ClipDescription和ClipData.ItemClipData常用方法将剪贴板中数据强制转换为文本复制到剪贴板中从剪贴板中粘贴复制到剪贴板中粘贴普通文本从content URI粘贴数据粘贴Intent利用Content Provider复制复杂数据将ID置入URI编码复制数据结构复制数据流设计高效的复制/粘贴功能关键类ClipboardManagerClipDataClipData.ItemClipDescriptionUriContentProviderIntent相关示例Note Pad示例程序参阅Content ProvidersAndroid为复制和粘贴提供了强大的基于剪贴板的框架。该框架同时支持简单和复杂数据类型,包括文本字符串、复杂数据结构、文本和二进制流数据、甚至程序asset。简单文本数据直接存储于剪贴板内,而复杂数据则保存为一个引用,粘贴应用可利用内容提供器(content provider)进行解析。复制和粘贴可在应用程序内部或多个实现此框架的应用程序之间进行。因为框架的一部分用到了content provider,本文讨论的内容与Android Content Provider API有些类似,这些API已在Content Provider一章中描述。剪贴板框架使用剪贴板框架时,可把数据放入剪辑(clip)对象,然后把该对象放入系统级剪贴板中。clip对象可以是以下三种形式:Text文本串。可以直接把字符串放入clip对象,然后把clip对象放入剪贴板中。需要粘贴字符串时,从剪贴板中获取clip对象,然后把字符串拷贝到应用程序的存储中即可。URIUri对象表示任何形式的URI。这主要用于从content provider复制复杂数据。复制数据时,先将Uri对象放入一个clip对象,再把clip对象放入剪贴板中。需要粘贴数据时,先获取clip对象,再获取Uri对象,再把Uri解析到诸如content provider之类的数据源中,然后就能从此数据源中把数据拷贝到应用程序的存储中了。Intent一个Intent。这为复制应用程序快捷方式提供了支持。复制数据时,先创建一个Intent并把它放入一个clip对象,再把clip对象放入剪贴板。需要粘贴数据时,可以获取clip对象并把Intent对象拷贝到应用程序的内存中。剪贴板同时仅保存一个clip对象。当应用程序把一个clip对象放入剪贴板时,前一个clip对象将会消失。如果要允许用户把数据粘贴到应用程序中,没必要对所有类型数据都进行处理。在让用户选择粘贴之前,可以先对剪贴板中的数据进行检测。除了包含指定格式的数据之外,clip对象还包含了元数据,它能说明数据是属于哪种格式或MIME类型。此元数据有助于应用程序确定对剪贴板数据执行合适的操作。比如,假定应用程序主要是处理文本信息的,那就可以忽略包含URI和Intent的clip对象。还有可能要允许用户只粘贴文本,而不论剪贴板中的数据格式如何。要实现这个目标,可以把剪贴板数据强制转换为文本格式,然后粘贴这些文本。这将在将剪贴板内数据强制转换为文本一节中描述。剪贴板类本节描述类剪贴板框架中所用到的类。ClipboardManager在Android系统中,系统剪贴板由全局ClipboardManager类表示。此类不需要直接初始化,而是提交getSystemService(CLIPBOARD_SERVICE)来获取一个引用。ClipData、ClipData.Item和ClipDescription要把数据加入剪贴板,可以创建一个ClipData对象,它包含了数据描述信息和数据本身。剪贴板每次只保存一个ClipData对象。一个ClipData包含了一个ClipDescription对象和一个以上的ClipData.Item对象。ClipDescription对象包含了clip相关的元数据信息。特别重要的是,它包含了一个clip数据所对应MIME类型的数组。把clip放入剪贴板后,粘贴应用程序可以利用此数组,程序可以检查此数组以确定其对这些MIME类型的处理能力。一个ClipData.Item对象包含了文本、URI或Intent数据:Text一个CharSequence。URI一个Uri。虽然可以是任何URI值,但通常是包含一个content provider URI。提供数据的应用程序把URI放入剪贴板。需要粘贴数据的应用程序从剪贴板中获取URI,并将它用于访问content provider(或者其它数据源)并取回数据。Intent一个Intent。本数据类型允许把应用程序的快捷方式复制到剪贴板中。用户可以在后续的使用中把快捷方式粘贴到其它应用程序中。可以在一个clip中加入多个ClipData.Item对象。这使得用户可以把多个选中值复制为同一个clip。比如,如果有一个列表widget允许用户一次选择多个选项,就可以把所有选中项一次复制到剪贴板中。要实现这一点,为每个列表项创建一个ClipData.Item,然后把这些ClipData.Item对象加入ClipData对象即可。ClipData常用方法ClipData类提供了便捷的静态方法来创建一个ClipData对象,附带一个ClipData.Item对象和一个简单的ClipDescription对象作为参数:newPlainText(label, text)返回包含了单个ClipData.Item对象的ClipData对象,此item对象内含一个文本字符串。ClipDescription对象的标签设置为label。ClipDescription的MIME类型是MIMETYPE_TEXT_PLAIN。newPlainText()用于创建一个文本字符串clip。newUri(resolver, label, URI)返回一个包含单个ClipData.Item的ClipData对象,此item对象内含一个URI。ClipDescription对象的标签设置为label。如果URI是一个content类型的URI(Uri.getScheme()返回content:),则该方法将用resolver的ContentResolver对象从content provider中获取可用的MIME类型,并把这些类型保存到ClipDescription中。对于不是content:的URI,该方法把MIME type设置为MIMETYPE_TEXT_URILIST。newUri()用于创建一个URI的clip,特别是content:URI。newIntent(label, intent)返回一个包含单个ClipData.Item的ClipData对象,此item对象内含一个Intent。ClipDescription对象的标签设置为label。MIME类型置为MIMETYPE_TEXT_INTENT。newIntent()用于创建一个Intent对象的clip。将剪贴板内数据强制转换为文本如果应用程序仅需处理文本,可用ClipData.Item.coerceToText()方法转换一下,就可以从剪贴板复制非文本数据。本方法将把ClipData.Item中的数据转换为文本,并且返回一个CharSequence。ClipData.Item.coerceToText()的返回值根据ClipData.Item中的数据格式来确定:Text如果ClipData.Item是文本(getText()不为null),则coerceToText()返回文本。URIClipData.Item是个URI(getUri()不为null),则coerceToText()会尝试将其视为content URI:如果URI是个content URI且provider能够返回文本流,则coerceToText()返回文本流。如果URI是个content URI但provider无法提供文本流,则coerceToText()返回URI的字符串表示形式。该字符串表示形式与Uri.toString()的返回值一致。如果URI不是一个content URI,则coerceToText()返回URI的字符串表示形式。该字符串表示形式与Uri.toString()的返回值一致。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指向的content provider中读取数据。复制到剪贴板中如前所述,如果要把数据复制到剪贴板(剪贴板句柄指向全局的ClipboardManager对象),需要创建一个ClipData对象,再把一个ClipDescription和一个以上的ClipData.Item对象加入其中,最后把这个ClipData添加到ClipboardManager对象中去。详细情况描述如下:1.如果要复制content URI类型的数据,先要建立一个content provider。Note Pad例程是一个使用content provider复制粘贴数据的示例。NotePadProvider类实现了content provider。NotePad类定义了该provider和其它应用程序的交互方式,包括所用的MIME类型。2.获取系统剪贴板:./如果用户选中复制caseR.id.menu_copy:/获取一个剪贴板服务的句柄ClipboardManagerclipboard=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);3.把数据复制到一个新建的ClipData对象:o 对于文本/创建一个新的文本clip,用于放入剪贴板中ClipDataclip=ClipData.newPlainText(simple text,Hello, World!);o 对于URI以下代码段通过构造了一个URI,把记录ID编入provider用到的content URI中。更多的技术细节在把ID编入URI一节中详述:/根据基本的Uri和联系人姓氏的记录ID,创建一个Uri/声明基本URI字符串privatestaticfinalStringCONTACTS=content:/com.example.contacts;/声明URI的路径字符串,用于复制数据privatestaticfinalStringCOPY_PATH=/copy;/声明需粘帖到剪贴板中的UriUricopyUri=Uri.parse(CONTACTS+COPY_PATH+/+lastName);./新建一个URI clip对象。系统使用匿名/ getContentResolver()对象读取provider的MIME类型。/ clip对象的标签是URI,数据是上述创建的UriClipDataclip=ClipData.newUri(getContentResolver(),URI,copyUri);o 对于Intent以下代码段构造了一个Intent并将其放入clip对象中:/创建IntentIntentappIntent=newIntent(this,com.example.demo.myapplication.class);./创建一个包含Intent的clip对象,标签是Intent,/数据是上述Intent对象ClipDataclip=ClipData.newIntent(Intent,appIntent);4.把新建的clip对象放入剪贴板:/设置剪贴板的主clip.clipboard.setPrimaryClip(clip);从剪贴板中粘贴如上所述,要从剪贴板粘贴数据,需先获得全局剪贴板对象,再获取clip对象,然后查找其中的数据,最后从clip对象中把数据拷贝到自己的存储中。本节详细描述了如何针对三种剪贴板数据的格式进行这些操作。粘贴普通文本要粘贴普通文本,首先获得全局剪贴板,并确认能否返回普通文本,然后获取clip对象,用getText()把其中文本拷贝到自己的存储中,步骤如下:1.用getSystemService(CLIPBOARD_SERVICE)获得全局ClipboardManager对象。还要声明一个全局变量来存放粘贴到的文本:ClipboardManagerclipboard=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);StringpasteData=;2.下一步,确定是否需要启用或禁用当前Activity的“粘贴”选项。还应验证一下剪贴板中是否包含了clip并且程序有能力处理其数据类型:/获取“粘贴”菜单项的IDMenuItemmPasteItem=menu.findItem(R.id.menu_paste);/如果剪贴板中没有数据,则禁用“粘贴”菜单项/如果包含数据,确定是否能够处理数据if(!(clipboard.hasPrimaryClip()mPasteItem.setEnabled(false);elseif(!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)/禁用粘贴菜单,因为剪贴板中虽有数据但不是普通文本mPasteItem.setEnabled(false);else/启用粘贴菜单,因为剪贴板中包含普通文本数据mPasteItem.setEnabled(true);3.从剪贴板中拷贝数据。仅当“粘贴”菜单项启用时,程序才会运行至此,所以这时可以假定剪贴板已经包含了普通文本。不过还不清楚里面包含了文本字符串还是指向普通文本的URI。以下代码段会进行检测,但只是展示了处理普通文本这部分代码:/对用户选中“粘贴”作出响应caseR.id.menu_paste:/检测剪贴板中的数据项。如果getText()不返回null,/则表示clip项包含了文本。假定本程序一次仅处理一个数据项ClipData.Itemitem=clipboard.getPrimaryClip().getItemAt(0);/获取剪贴板中的文本pasteData=item.getText();/如果字符串包含了数据,粘贴操作完成if(pasteData!=null)return;/剪贴板未包含文本。如果包含了URI,则尝试从URI获取数据。elseUripasteUri=item.getUri();/如果URI包含了数据,则尝试获取文本if(pasteUri!=null)/调用解析URI并获取数据的过程函数。/此过程函数不在此处展示。pasteData=resolveUri(Uri);return;else/出错。虽然MIME类型是普通文本,但剪贴板所含的不是文本和Uri。/报告错误Log.e(Clipboard contains an invalid data type);return;从content URI粘贴数据如果ClipData.Item对象包含了一个content URI,程序也确认能处理其中的MIME类型,则可创建一个ContentResolver并调用合适的content provider方法来获取数据。以下过程描述了如何根据剪贴板中的content URI从content provider获取数据。程序会先检查MIME类型,确认能够使用该provider提供的数据:1.声明全局变量,用于存放MIME类型:/声明MIME类型常量,对应provider所提供的MIME类型PublicstaticfinalStringMIME_TYPE_CONTACT=vnd.android.cursor.item/vnd.example.contact2.获取全局剪贴板。再创建一个content resolver用于访问content provider:/获取Clipboard Manager的句柄ClipboardManagerclipboard=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);/创建一个content resolver实例ContentResolvercr=getContentResolver();3.从剪贴板获取主clip,并把内容解析为URI:/获取剪贴板数据ClipDataclip=clipboard.getPrimaryClip();if(clip!=null)/获取剪贴板的第一项数据ClipData.Itemitem=clip.getItemAt(0);/试图将数据作为URI读取UripasteUri=item.getUri();4.通过调用getType(Uri),判断URI是否为content URI。如果Uri未指向合法的content provider,该方法返回null:/如果剪贴板包含URI引用if(pasteUri!=null)/是content URI ?StringuriMimeType=cr.getType(pasteUri);5.判断content provider是否支持应用程序能够识别的MIME类型。如果支持,则调用ContentResolver.query()来获取数据。返回值是一个Cursor:/返回值不为null,表示Uri是content Uriif(uriMimeType!=null)/ content provider提供的MIME类型当前程序是否可用?if(uriMimeType.equals(MIME_TYPE_CONTACT)/获取content provider数据CursorpasteCursor=cr.query(uri,null,null,null,null);/如果Cursor包含数据,则移至第一条记录if(pasteCursor!=null)if(pasteCursor.moveToFirst()/获取Cursor数据。/代码根据数据格式不同而有所变化/关闭CursorpasteCursor.close();粘贴Intent要粘贴一个意图Intent,首先获取全局剪贴板,再检查ClipData.Item对象是否包含Intent。然后调用getIntent()来把Intent拷贝到程序的存储中。以下代码段演示了这一过程:/获取Clipboard Manager句柄ClipboardManagerclipboard=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);/通过判断getIntent()是否为null,检查clip item是否包含Intent。IntentpasteIntent=clipboard.getPrimaryClip().getItemAt(0).getIntent();if(pasteIntent!=null)/处理Intentelse/忽略剪贴板内容;/假如程序认为剪贴板应该包含Intent,可在此报告错误利用Content Provider复制复杂数据Content provider支持对复杂数据的复制,比如数据库记录或文件流之类。在复制数据时,把一个content URI放入剪贴板中。然后粘贴应用程序从剪贴板中获取此URI,并用它读取数据库数据或者文件流的描述符。由于粘贴应用程序只是将content URI作为数据读取,因此还需要知道应获取数据的哪些部分。可以把所需数据的ID编入URI本身,或者让URI只精确返回所需复制部分的数据。采用哪种方式取决于数据是如何组织在一起的。以下章节描述了如何创建URI、如何提供复杂数据、如何提供文件流。以下假定开发人员已经熟悉了content provider的一般设计规则。将ID置入URI编码利用URI把数据复制到剪贴板时,有一项实用技术就是把数据的ID置入URI编码本身。然后content provider可以从URI得到ID,并用ID来读取数据。粘贴应用程序不必知道ID是否存在,要做的所有操作就是从剪贴板获取“引用”(URI加ID),并把它交给content provider,然后读取数据。通常的编码方式是把ID附在content URI后面。比如,假定已定义provider URI如下:content:/com.example.contacts如果需要把名称置入URI,应该使用如下代码:StringuriString=content:/com.example.contacts+/+Smith/现在uriString包含了content:/com.example.contacts/Smith/根据字符串变量创建uri对象UricopyUri=Uri.parse(uriString);如果程序中已经用到了content provider,只需新增一个指示复制数据的URI路径。比如,假设已存在以下URI路径:content:/com.example.contacts/peoplecontent:/com.example.contacts/people/detailcontent:/com.example.contacts/people/images下面加入一个用于复制的URI:content:/com.example.contacts/copying可以利用模式匹配来检测到copy URI,并用代码进行复制和粘贴处理。如果是用content provider、内部数据库、内部表来组织数据,通常即可使用以上编码技术。这种情况下会有多块数据需要复制,很可能每块数据都会有一个唯一ID。当粘贴应用程序查询时,可以用此ID查找并返回数据。如果没有多块数据需要复制,可能就不必把ID进行编码。可以简单地使用能够唯一标识provider的URI即可。查询时,provider将会返回它包含的数据。Note Pad示例程序中就用ID获取了单条记录,以便从note列表中打开一条note。此示例使用了SQL数据库中的_id字段,不过可以根据需要使用任何数字或字符ID。复制数据结构为了复制和粘贴复杂数据,应该创建一个content provider,它是ContentProvider组件的子类。还应该将编码后的URI放入剪贴板,此URI指向了需提供的正确记录。此外,还必须考虑应用程序的现状:如果已有一个content provider,可以增加它的功能。可能只需要修改query()方法,使得它能处理粘贴程序所需的URI即可。有可能要修改方法来对URI中的“copy”进行模式匹配。如果应用程序拥有内部数据库,可能需要将此数据库移入content provider,便于从中拷贝数据。如果目前没有用到数据库,可以实现一个简单的content provider,它的唯一用途就是为程序提供粘贴自剪贴板的数据。在content provider中,至少会需要覆盖以下方法:query()粘贴应用程序将会假定,通过此方法能够获取剪贴板中URI指定的数据。为了支持复制功能,应该在本方法中对包含指定“复制”路径的URI进行检测。然后,程序可以创建一个“复制”URI并放入剪贴板中,此URI包含了复制路径和指向实际复制记录的指针。getType()本方法应该返回MIME类型或者需复制数据的类型。为了把MIME类型放入新建的ClipData对象,newUri()方法将会调用getType()。复杂数据的MIME类型在Content Providers一节中描述。注意,其它的content provider方法是没必要用到的,比如insert()或update()。粘贴应用程序只需要获取所用的MIME类型并从provider拷贝数据。如果已经实现了这些方法,那它们也不会影响复制操作。以下代码段演示了如何建立复制复杂数据的应用程序:1.声明全局常量,定义基本URI字符串和路径,用于指明复制数据的URI字符串。同时声明需复制数据的MIME类型:/声明基本URI字符串privatestaticfinalStringCONTACTS=content:/com.example.contacts;/声明用于复制数据的URI路径字符串privatestaticfinalStringCOPY_PATH=/copy;/声明需复制数据的MIME类型publicstaticfinalStringMIME_TYPE_CONTACT=vnd.android.cursor.item/vnd.example.contact2.用户复制数据的Activity中,创建把数据复制到剪贴板的代码。在响应复制请求时,将URI放入剪贴板中:publicclassMyCopyActivityextendsActivity./用户已经选中了姓名并请求复制case.id.menu_copy:/在基本URI后附加姓名/姓名存于lastNameuriString=CONTACTS+COPY_PATH+/+lastName;/字符串编码为URIUricopyUri=Uri.parse(uriString);/获取剪贴板服务的句柄ClipboardManagerclipboard d=(ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE););ClipDataclip=ClipData.newUri(getContentResolver(),URI,copyUri););/ /设置剪贴板的主clip.clipboard.setPrimaryClip(clip););3.在content provider的全局部分(global scope),创建一个URI匹配器,并加入与剪贴板URI相匹配的URI模式。publicclassMyCopyProviderextendsContentProvider./ Uriri匹配器对象,用于简化对content URI模式匹配操作。privatestaticfinalUriMatchersURIMatcher=newUriMatcher(UriMatcher.NO_MATCH););/整数,用于URI模式的开关变量。privatestaticfinalintGET_SINGLE_CONTACT=0;./为content URI加入匹配器。/匹配content:/com.example.contacts/copy/*sUriMatcher.addURI(CONTACTS,names/*,GET_SINGLE_CONTACT);4.建立query()方法。在本方法中可用不同的代码处理各种URI模式,不过下面仅列出了剪贴板复制操作所用到的模式:/建立provider的query()方法publicCursorquery(Uriuri,Stringprojection,Stringselection,StringselectionArgs,StringsortOrder)./基于传入的content URI进行分支switch(sUriMatcher.match(uri)caseGET_SINGLE_CONTACT:/根据请求的姓名查询并返回contact。/在此应对传入的URI解码,基于姓名查询数据并返回结果Cursor.5.建立getType()方法,返回合适的返回数据MIME类型:/建立provider的getType()方法publicStringgetType(Uriuri).switch(sUriMatcher.match(uri)GET_SINGLE_CONTACT:return(MIME_TYPE_CONTACT););从content URI粘贴数据一节描述了如何从剪贴板获取content URI,并用它读取并粘贴数据。复制数据流可以将大量的文本和二进制数据以流的形式进行复制和粘贴。数据可以具有如下格式:保存在物理设备上的文件。来自socket的流。保存在provider底层数据库系统中的大量数据。数据流content provider用文件描述符对象而不是CursorAssetFileDescriptor。粘贴应用程序利用此文件描述符来读取数据流。流。要建立用provider复制数据流的应用程序,请按以下步骤进行:1.为放入剪贴板的数据流建立content URI。可有以下选择:o将数据流的ID编入URI,如上将ID编入URI所述,然后在provider中保存一张表,其中包含了ID和相关的流名称。o将流名称直接编入URI。o用唯一的URI,总是从provider返回当前流。如果选用此项,则每次通过URI把流复制到剪贴板时,必须记得更新provider,使它指向新的流。2.为每类提供的数据流指定一个MIME类型。粘贴应用程序需要此信息来确定能否粘贴剪贴板中的数据。3.实现ContentProvider中的一个方法,返回流的文件描述符。如果ID已编入content URI,则用此方法来确定需要打开的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新解读《GB-T 31313-2014萤石 粒度的筛分测定》
- 产品品牌代理合同范本大全6篇
- 2025水产采购合同3篇
- 黑芝麻收购合同范本
- 电梯改造施工合同范本
- 保养合同范本模板
- 私人墙绘合同范本
- 建材供应合同范本简易
- 冷库货物装卸合同范本
- 商业房产托管合同范本
- 新药发现与开发第一章概论
- 思想道德与法治2021版第一章教案
- SC/T 9010-2000渔港总体设计规范
- 方太- IPD流程基础知识培训
- 乡镇应急信息报送制度
- 农业机械化发展历程课件
- 新生儿内科专业质控中心督查内容与要求评分表
- 实验动物遗传学及质量控制课件
- 新能源概论全解课件
- 《中国的行政区划》- 完整版课件
- 《中国公民科学素质基准》题库500题(精品)
评论
0/150
提交评论