一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android開發(fā)者指南

 dmw_zgl 2014-12-30

Copy and Paste

版本:Android 4.0 r1

 快速查看

  • 用于復(fù)制粘貼數(shù)據(jù)的基于剪貼板的框架。
  • 同時(shí)支持簡單和復(fù)雜的數(shù)據(jù),包括文本串、復(fù)雜的數(shù)據(jù)結(jié)構(gòu)、文本和二進(jìn)制流數(shù)據(jù)、程序 asset
  • 直接從剪貼板復(fù)制粘貼簡單文本。
  • content provider復(fù)制粘貼復(fù)雜數(shù)據(jù)。
  • 需要API 11版本。

在本文中

剪貼板框架

剪貼板類

ClipboardManager

ClipData、ClipDescription和ClipData.Item

ClipData常用方法

將剪貼板中數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為文本

復(fù)制到剪貼板中

從剪貼板中粘貼

復(fù)制到剪貼板中

粘貼普通文本

從content URI粘貼數(shù)據(jù)

粘貼Intent

利用Content Provider復(fù)制復(fù)雜數(shù)據(jù)

將ID置入U(xiǎn)RI編碼

復(fù)制數(shù)據(jù)結(jié)構(gòu)

復(fù)制數(shù)據(jù)流

設(shè)計(jì)高效的復(fù)制/粘貼功能

關(guān)鍵類

ClipboardManager

ClipData

ClipData.Item

ClipDescription

Uri

ContentProvider

Intent

相關(guān)示例

Note Pad示例程序

參閱

Content Providers

Android為復(fù)制和粘貼提供了強(qiáng)大的基于剪貼板的框架。該框架同時(shí)支持簡單和復(fù)雜數(shù)據(jù)類型,包括文本字符串、復(fù)雜數(shù)據(jù)結(jié)構(gòu)、文本和二進(jìn)制流數(shù)據(jù)、甚至程序asset。簡單文本數(shù)據(jù)直接存儲(chǔ)于剪貼板內(nèi),而復(fù)雜數(shù)據(jù)則保存為一個(gè)引用,粘貼應(yīng)用可利用內(nèi)容提供器(content provider)進(jìn)行解析。復(fù)制和粘貼可在應(yīng)用程序內(nèi)部或多個(gè)實(shí)現(xiàn)此框架的應(yīng)用程序之間進(jìn)行。

因?yàn)榭蚣艿囊徊糠钟玫搅?span style="font-family: Arial;">content provider,本文討論的內(nèi)容與Android Content Provider API有些類似,這些API已在Content Provider一章中描述。

 

使用剪貼板框架時(shí),可把數(shù)據(jù)放入剪輯(clip)對(duì)象,然后把該對(duì)象放入系統(tǒng)級(jí)剪貼板中。clip對(duì)象可以是以下三種形式:

Text

文本串。可以直接把字符串放入clip對(duì)象,然后把clip對(duì)象放入剪貼板中。需要粘貼字符串時(shí),從剪貼板中獲取clip對(duì)象,然后把字符串拷貝到應(yīng)用程序的存儲(chǔ)中即可。

URI

Uri對(duì)象表示任何形式的URI。這主要用于從content provider復(fù)制復(fù)雜數(shù)據(jù)。復(fù)制數(shù)據(jù)時(shí),先將Uri對(duì)象放入一個(gè)clip對(duì)象,再把clip對(duì)象放入剪貼板中。需要粘貼數(shù)據(jù)時(shí),先獲取clip對(duì)象,再獲取Uri對(duì)象,再把Uri解析到諸如content provider之類的數(shù)據(jù)源中,然后就能從此數(shù)據(jù)源中把數(shù)據(jù)拷貝到應(yīng)用程序的存儲(chǔ)中了。

Intent

一個(gè)Intent。這為復(fù)制應(yīng)用程序快捷方式提供了支持。復(fù)制數(shù)據(jù)時(shí),先創(chuàng)建一個(gè)Intent并把它放入一個(gè)clip對(duì)象,再把clip對(duì)象放入剪貼板。需要粘貼數(shù)據(jù)時(shí),可以獲取clip 對(duì)象并把Intent對(duì)象拷貝到應(yīng)用程序的內(nèi)存中。

剪貼板同時(shí)僅保存一個(gè)clip對(duì)象。當(dāng)應(yīng)用程序把一個(gè)clip對(duì)象放入剪貼板時(shí),前一個(gè)clip對(duì)象將會(huì)消失。

如果要允許用戶把數(shù)據(jù)粘貼到應(yīng)用程序中,沒必要對(duì)所有類型數(shù)據(jù)都進(jìn)行處理。在讓用戶選擇粘貼之前,可以先對(duì)剪貼板中的數(shù)據(jù)進(jìn)行檢測。除了包含指定格式的數(shù)據(jù)之外,clip對(duì)象還包含了元數(shù)據(jù),它能說明數(shù)據(jù)是屬于哪種格式或MIME類型。此元數(shù)據(jù)有助于應(yīng)用程序確定對(duì)剪貼板數(shù)據(jù)執(zhí)行合適的操作。比如,假定應(yīng)用程序主要是處理文本信息的,那就可以忽略包含URIIntentclip對(duì)象。

還有可能要允許用戶只粘貼文本,而不論剪貼板中的數(shù)據(jù)格式如何。要實(shí)現(xiàn)這個(gè)目標(biāo),可以把剪貼板數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為文本格式,然后粘貼這些文本。這將在將剪貼板內(nèi)數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為文本一節(jié)中描述。

 

本節(jié)描述類剪貼板框架中所用到的類。

ClipboardManager

Android系統(tǒng)中,系統(tǒng)剪貼板由全局ClipboardManager類表示。此類不需要直接初始化,而是提交getSystemService(CLIPBOARD_SERVICE)來獲取一個(gè)引用。

 

ClipDataClipData.ItemClipDescription

要把數(shù)據(jù)加入剪貼板,可以創(chuàng)建一個(gè)ClipData對(duì)象,它包含了數(shù)據(jù)描述信息和數(shù)據(jù)本身。剪貼板每次只保存一個(gè)ClipData對(duì)象。一個(gè)ClipData包含了一個(gè)ClipDescription對(duì)象和一個(gè)以上的ClipData.Item對(duì)象。

ClipDescription對(duì)象包含了clip相關(guān)的元數(shù)據(jù)信息。特別重要的是,它包含了一個(gè)clip數(shù)據(jù)所對(duì)應(yīng)MIME類型的數(shù)組。把clip放入剪貼板后,粘貼應(yīng)用程序可以利用此數(shù)組,程序可以檢查此數(shù)組以確定其對(duì)這些MIME類型的處理能力。

一個(gè)ClipData.Item對(duì)象包含了文本、URIIntent數(shù)據(jù):

Text

一個(gè)CharSequence。

URI

一個(gè)Uri。雖然可以是任何URI值,但通常是包含一個(gè)content provider URI。提供數(shù)據(jù)的應(yīng)用程序把URI放入剪貼板。需要粘貼數(shù)據(jù)的應(yīng)用程序從剪貼板中獲取URI,并將它用于訪問content provider(或者其它數(shù)據(jù)源)并取回?cái)?shù)據(jù)。

Intent

一個(gè)Intent。本數(shù)據(jù)類型允許把應(yīng)用程序的快捷方式復(fù)制到剪貼板中。用戶可以在后續(xù)的使用中把快捷方式粘貼到其它應(yīng)用程序中。

可以在一個(gè)clip中加入多個(gè)ClipData.Item對(duì)象。這使得用戶可以把多個(gè)選中值復(fù)制為同一個(gè)clip。比如,如果有一個(gè)列表widget允許用戶一次選擇多個(gè)選項(xiàng),就可以把所有選中項(xiàng)一次復(fù)制到剪貼板中。要實(shí)現(xiàn)這一點(diǎn),為每個(gè)列表項(xiàng)創(chuàng)建一個(gè)ClipData.Item,然后把這些ClipData.Item對(duì)象加入ClipData對(duì)象即可。

 

ClipData常用方法

ClipData類提供了便捷的靜態(tài)方法來創(chuàng)建一個(gè)ClipData對(duì)象,附帶一個(gè)ClipData.Item對(duì)象和一個(gè)簡單的ClipDescription對(duì)象作為參數(shù)

newPlainText(label, text)

返回包含了單個(gè)ClipData.Item對(duì)象的ClipData對(duì)象,此item對(duì)象內(nèi)含一個(gè)文本字符串。ClipDescription對(duì)象的標(biāo)簽設(shè)置為labelClipDescriptionMIME 類型是MIMETYPE_TEXT_PLAIN。

newPlainText()用于創(chuàng)建一個(gè)文本字符串clip

newUri(resolver, label, URI)

返回一個(gè)包含單個(gè)ClipData.ItemClipData對(duì)象,此item對(duì)象內(nèi)含一個(gè)URIClipDescription對(duì)象的標(biāo)簽設(shè)置為label。如果URI是一個(gè)content類型的URIUri.getScheme()返回content:),則該方法將用resolverContentResolver對(duì)象從content provider中獲取可用的MIME類型,并把這些類型保存到ClipDescription中。對(duì)于不是content:URI ,該方法把MIME type設(shè)置為MIMETYPE_TEXT_URILIST

newUri()用于創(chuàng)建一個(gè)URIclip,特別是content: URI

newIntent(label, intent)

返回一個(gè)包含單個(gè)ClipData.ItemClipData對(duì)象,此item對(duì)象內(nèi)含一個(gè)IntentClipDescription對(duì)象的標(biāo)簽設(shè)置為label。MIME類型置為MIMETYPE_TEXT_INTENT

newIntent()用于創(chuàng)建一個(gè)Intent對(duì)象的clip。

 

將剪貼板內(nèi)數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為文本

如果應(yīng)用程序僅需處理文本,可用ClipData.Item.coerceToText()方法轉(zhuǎn)換一下,就可以從剪貼板復(fù)制非文本數(shù)據(jù)。

本方法將把ClipData.Item中的數(shù)據(jù)轉(zhuǎn)換為文本,并且返回一個(gè)CharSequence。ClipData.Item.coerceToText()的返回值根據(jù)ClipData.Item中的數(shù)據(jù)格式來確定:

Text

如果ClipData.Item是文本(getText()不為null),則coerceToText()返回文本。

URI

ClipData.Item是個(gè)URIgetUri()不為null),則coerceToText()會(huì)嘗試將其視為content URI

·           如果URI是個(gè)content URIprovider能夠返回文本流,則coerceToText()返回文本流。

·           如果URI是個(gè)content URIprovider無法提供文本流,則coerceToText()返回URI字符串表示形式。該字符串表示形式Uri.toString()的返回值一致。

·           如果URI不是一個(gè)content URI,則coerceToText()返回URI字符串表示形式。字符串表示形式Uri.toString()的返回值一致。

Intent

如果ClipData.Item是個(gè)IntentgetIntent()不為null),則coerceToText()將其轉(zhuǎn)換為Intent URI后返回。該字符串表示形式與Intent.toUri(URI_INTENT_SCHEME)的返回值一致。

剪貼板的整體框架如圖1所示。在復(fù)制數(shù)據(jù)時(shí),應(yīng)用程序?qū)?span style="font-family: Courier new; color: #007000">ClipData對(duì)象放入全局的ClipboardManager剪貼板中。ClipData內(nèi)含了一個(gè)或多個(gè)ClipData.Item對(duì)象,以及一個(gè)ClipDescription對(duì)象。在粘貼數(shù)據(jù)時(shí),應(yīng)用程序先獲取ClipData,從ClipDescription中讀取MIME類型信息,再從ClipData.Item中或ClipData.Item指向的content provider中讀取數(shù)據(jù)。

A block diagram of the copy and paste framework

1. Android剪貼板框架

 

如前所述,如果要把數(shù)據(jù)復(fù)制到剪貼板(剪貼板句柄指向全局的ClipboardManager對(duì)象),需要?jiǎng)?chuàng)建一個(gè)ClipData對(duì)象,再把一個(gè)ClipDescription和一個(gè)以上的ClipData.Item對(duì)象加入其中,最后把這個(gè)ClipData添加到ClipboardManager對(duì)象中去。詳細(xì)情況描述如下:

1.    如果要復(fù)制content URI類型的數(shù)據(jù),先要建立一個(gè)content provider
Note Pad
例程是一個(gè)使用content provider復(fù)制粘貼數(shù)據(jù)的示例。NotePadProvider類實(shí)現(xiàn)了content providerNotePad類定義了該provider和其它應(yīng)用程序的交互方式,包括所用的MIME類型。

2.    獲取系統(tǒng)剪貼板:

... 

// 如果用戶選中復(fù)制

case R.id.menu_copy: 

// 獲取一個(gè)剪貼板服務(wù)的句柄

ClipboardManager clipboard =(ClipboardManager) 

getSystemService(Context.CLIPBOARD_SERVICE);

3.    把數(shù)據(jù)復(fù)制到一個(gè)新建的ClipData對(duì)象:

  • 對(duì)于文本

    // 創(chuàng)建一個(gè)新的文本clip,用于放入剪貼板中

    ClipData clip =ClipData.newPlainText("simple text","Hello, World!");

  • 對(duì)于URI

    以下代碼段通過構(gòu)造了一個(gè)URI ,把記錄ID編入provider用到的content URI中。更多的技術(shù)細(xì)節(jié)在ID編入URI一節(jié)中詳述:

    // 根據(jù)基本的Uri和聯(lián)系人姓氏的記錄ID,創(chuàng)建一個(gè)Uri

    // 聲明基本URI字符串

    privatestaticfinalString CONTACTS ="content://com.example.contacts"; 

    // 聲明URI的路徑字符串,用于復(fù)制數(shù)據(jù)

    privatestaticfinalString COPY_PATH ="/copy"; 

    // 聲明需粘帖到剪貼板中的Uri

    Uri copyUri =Uri.parse(CONTACTS + COPY_PATH +"/"+ lastName); 

     ... 

    // 新建一個(gè)URI clip對(duì)象。系統(tǒng)使用匿名

    // getContentResolver()對(duì)象讀取provider MIME類型。

    // clip對(duì)象的標(biāo)簽是"URI",數(shù)據(jù)是上述創(chuàng)建的Uri

    ClipData clip =ClipData.newUri(getContentResolver(),"URI",copyUri);

     

  • 對(duì)于Intent

    以下代碼段構(gòu)造了一個(gè)Intent并將其放入clip對(duì)象中:

    // 創(chuàng)建Intent 

    Intent appIntent =newIntent(this, com.example.demo.myapplication.class); 

     

    ... 

     

    // 創(chuàng)建一個(gè)包含Intentclip對(duì)象,標(biāo)簽是"Intent"

    // 數(shù)據(jù)是上述Intent對(duì)象

    ClipData clip =ClipData.newIntent("Intent",appIntent);

4.    把新建的clip對(duì)象放入剪貼板:

// 設(shè)置剪貼板的主clip. 

clipboard.setPrimaryClip(clip);

 

如上所述,要從剪貼板粘貼數(shù)據(jù),需先獲得全局剪貼板對(duì)象,再獲取clip對(duì)象,然后查找其中的數(shù)據(jù),最后從clip對(duì)象中把數(shù)據(jù)拷貝到自己的存儲(chǔ)中。本節(jié)詳細(xì)描述了如何針對(duì)三種剪貼板數(shù)據(jù)的格式進(jìn)行這些操作。

 

粘貼普通文本

要粘貼普通文本,首先獲得全局剪貼板,并確認(rèn)能否返回普通文本,然后獲取clip對(duì)象,用getText()把其中文本拷貝到自己的存儲(chǔ)中,步驟如下:

1.   getSystemService(CLIPBOARD_SERVICE)獲得全局ClipboardManager對(duì)象。還要聲明一個(gè)全局變量來存放粘貼到的文本:

ClipboardManager clipboard =(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 

String pasteData ="";

2.    下一步,確定是否需要啟用或禁用當(dāng)前Activity的“粘貼”選項(xiàng)。還應(yīng)驗(yàn)證一下剪貼板中是否包含了clip并且程序有能力處理其數(shù)據(jù)類型:

// 獲取“粘貼”菜單項(xiàng)的ID

MenuItem mPasteItem = menu.findItem(R.id.menu_paste);  

// 如果剪貼板中沒有數(shù)據(jù),則禁用“粘貼”菜單項(xiàng)

// 如果包含數(shù)據(jù),確定是否能夠處理數(shù)據(jù)

if(!(clipboard.hasPrimaryClip())){  

    mPasteItem.setEnabled(false);  

    }elseif(!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))){ 

         // 禁用粘貼菜單,因?yàn)榧糍N板中雖有數(shù)據(jù)但不是普通文本

        mPasteItem.setEnabled(false); 

    }else{ 

         // 啟用粘貼菜單,因?yàn)榧糍N板中包含普通文本數(shù)據(jù)

        mPasteItem.setEnabled(true); 

    } 

}

3.    從剪貼板中拷貝數(shù)據(jù)。僅當(dāng)“粘貼”菜單項(xiàng)啟用時(shí),程序才會(huì)運(yùn)行至此,所以這時(shí)可以假定剪貼板已經(jīng)包含了普通文本。不過還不清楚里面包含了文本字符串還是指向普通文本的URI。以下代碼段會(huì)進(jìn)行檢測,但只是展示了處理普通文本這部分代碼:

// 對(duì)用戶選中“粘貼”作出響應(yīng)

case R.id.menu_paste: 

 // 檢測剪貼板中的數(shù)據(jù)項(xiàng)。如果getText()不返回null

// 則表示clip項(xiàng)包含了文本。假定本程序一次僅處理一個(gè)數(shù)據(jù)項(xiàng)

 ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); 

 // 獲取剪貼板中的文本

pasteData = item.getText(); 

 // 如果字符串包含了數(shù)據(jù),粘貼操作完成

if(pasteData !=null){ 

    return; 

 // 剪貼板未包含文本。如果包含了URI,則嘗試從URI獲取數(shù)據(jù)。

}else{ 

    Uri pasteUri = item.getUri(); 

     // 如果URI包含了數(shù)據(jù),則嘗試獲取文本

    if(pasteUri !=null){ 

         // 調(diào)用解析URI并獲取數(shù)據(jù)的過程函數(shù)。

        // 此過程函數(shù)不在此處展示。

        pasteData = resolveUri(Uri); 

        return; 

    }else{ 

     // 出錯(cuò)。雖然MIME類型是普通文本,但剪貼板所含的不是文本和Uri

    // 報(bào)告錯(cuò)誤

    Log.e("Clipboard contains an invalid data type"); 

    return; 

    } 

}

 

content URI粘貼數(shù)據(jù)

如果ClipData.Item對(duì)象包含了一個(gè)content URI,程序也確認(rèn)能處理其中的MIME 類型,則可創(chuàng)建一個(gè)ContentResolver并調(diào)用合適的content provider方法來獲取數(shù)據(jù)。

以下過程描述了如何根據(jù)剪貼板中的content URIcontent provider獲取數(shù)據(jù)。程序會(huì)先檢查MIME類型,確認(rèn)能夠使用該provider提供的數(shù)據(jù):

1.    聲明全局變量,用于存放MIME類型:

// 聲明MIME類型常量,對(duì)應(yīng)provider所提供的MIME類型

publicstaticfinalString MIME_TYPE_CONTACT ="vnd.android.cursor.item/vnd.example.contact"

2.    獲取全局剪貼板。再創(chuàng)建一個(gè)content resolver用于訪問content provider

// 獲取Clipboard Manager的句柄 

ClipboardManager clipboard =(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 

 // 創(chuàng)建一個(gè)content resolver實(shí)例

ContentResolver cr = getContentResolver();

3.    從剪貼板獲取主clip,并把內(nèi)容解析為URI:

// 獲取剪貼板數(shù)據(jù)

ClipData clip = clipboard.getPrimaryClip(); 

 if(clip !=null){ 

    // 獲取剪貼板的第一項(xiàng)數(shù)據(jù)

    ClipData.Item item = clip.getItemAt(0); 

    // 試圖將數(shù)據(jù)作為URI讀取

    Uri pasteUri = item.getUri();

4.    通過調(diào)用getType(Uri),判斷URI是否為content URI。如果Uri未指向合法的content provider,該方法返回null

    // 如果剪貼板包含URI引用

    if(pasteUri !=null){ 

        // content URI ? 

        String uriMimeType = cr.getType(pasteUri);

5.    判斷content provider是否支持應(yīng)用程序能夠識(shí)別的MIME類型。如果支持,則調(diào)用ContentResolver.query()來獲取數(shù)據(jù)。返回值是一個(gè)Cursor

        // 返回值不為null,表示Uricontent Uri 

        if(uriMimeType !=null){ 

            // content provider提供的MIME類型當(dāng)前程序是否可用?

            if(uriMimeType.equals(MIME_TYPE_CONTACT)){ 

                // 獲取content provider數(shù)據(jù)

                Cursor pasteCursor = cr.query(uri,null,null,null,null); 

                // 如果Cursor包含數(shù)據(jù),則移至第一條記錄

                if(pasteCursor !=null){ 

                    if(pasteCursor.moveToFirst()){ 

                    // 獲取Cursor數(shù)據(jù)。

                    // 代碼根據(jù)數(shù)據(jù)格式不同而有所變化

                    } 

                } 

                // 關(guān)閉Cursor 

                pasteCursor.close(); 

             } 

         } 

     } 

}

 

粘貼Intent

要粘貼一個(gè)意圖Intent,首先獲取全局剪貼板,再檢查ClipData.Item對(duì)象是否包含Intent。然后調(diào)用getIntent()來把Intent拷貝到程序的存儲(chǔ)中。以下代碼段演示了這一過程:

// 獲取Clipboard Manager句柄 

ClipboardManager clipboard =(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 

// 通過判斷getIntent()是否為null 檢查clip item是否包含Intent。

Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent(); 

if(pasteIntent !=null){ 

    // 處理Intent 

}else{ 

    // 忽略剪貼板內(nèi)容;

    // 假如程序認(rèn)為剪貼板應(yīng)該包含Intent,可在此報(bào)告錯(cuò)誤

}

 

利用Content Provider復(fù)制復(fù)雜數(shù)據(jù)

Content provider支持對(duì)復(fù)雜數(shù)據(jù)的復(fù)制,比如數(shù)據(jù)庫記錄或文件流之類。在復(fù)制數(shù)據(jù)時(shí),把一個(gè)content URI放入剪貼板中。然后粘貼應(yīng)用程序從剪貼板中獲取此URI,并用它讀取數(shù)據(jù)庫數(shù)據(jù)或者文件流的描述符。

由于粘貼應(yīng)用程序只是將content URI作為數(shù)據(jù)讀取,因此還需要知道應(yīng)獲取數(shù)據(jù)的哪些部分。可以把所需數(shù)據(jù)的ID編入URI本身,或者讓URI只精確返回所需復(fù)制部分的數(shù)據(jù)。采用哪種方式取決于數(shù)據(jù)是如何組織在一起的。

以下章節(jié)描述了如何創(chuàng)建URI、如何提供復(fù)雜數(shù)據(jù)、如何提供文件流。以下假定開發(fā)人員已經(jīng)熟悉了content provider的一般設(shè)計(jì)規(guī)則。

 

ID置入URI編碼

利用URI把數(shù)據(jù)復(fù)制到剪貼板時(shí),有一項(xiàng)實(shí)用技術(shù)就是把數(shù)據(jù)的ID置入URI編碼本身。然后content provider可以從URI得到ID,并用ID來讀取數(shù)據(jù)。粘貼應(yīng)用程序不必知道ID是否存在,要做的所有操作就是從剪貼板獲取“引用”(URIID),并把它交給content provider,然后讀取數(shù)據(jù)。

通常的編碼方式是把ID附在content URI后面。比如,假定已定義provider URI如下:

"content://com.example.contacts"

如果需要把名稱置入URI,應(yīng)該使用如下代碼:

String uriString ="content://com.example.contacts"+"/"+"Smith" 

// 現(xiàn)在uriString包含了content://com.example.contacts/Smith 

// 根據(jù)字符串變量創(chuàng)建uri對(duì)象

Uri copyUri =Uri.parse(uriString);

如果程序中已經(jīng)用到了content provider,只需新增一個(gè)指示復(fù)制數(shù)據(jù)的URI路徑。比如,假設(shè)已存在以下URI路徑:

"content://com.example.contacts"/people 

"content://com.example.contacts"/people/detail 

"content://com.example.contacts"/people/images

下面加入一個(gè)用于復(fù)制的URI

"content://com.example.contacts/copying"

可以利用模式匹配來檢測到"copy" URI,并用代碼進(jìn)行復(fù)制和粘貼處理。

如果是用content provider、內(nèi)部數(shù)據(jù)庫、內(nèi)部表來組織數(shù)據(jù),通常即可使用以上編碼技術(shù)。這種情況下會(huì)有多塊數(shù)據(jù)需要復(fù)制,很可能每塊數(shù)據(jù)都會(huì)有一個(gè)唯一ID當(dāng)粘貼應(yīng)用程序查詢時(shí),可以用此ID查找并返回?cái)?shù)據(jù)。

如果沒有多塊數(shù)據(jù)需要復(fù)制,可能就不必把ID進(jìn)行編碼??梢院唵蔚厥褂媚軌蛭ㄒ粯?biāo)識(shí)providerURI即可。查詢時(shí),provider將會(huì)返回它包含的數(shù)據(jù)。

Note Pad示例程序中就用ID獲取了單條記錄,以便從note列表中打開一條note。此示例使用了SQL數(shù)據(jù)庫中的_id字段,不過可以根據(jù)需要使用任何數(shù)字或字符ID

 

復(fù)制數(shù)據(jù)結(jié)構(gòu)

為了復(fù)制和粘貼復(fù)雜數(shù)據(jù),應(yīng)該創(chuàng)建一個(gè)content provider,它是ContentProvider組件的子類。還應(yīng)該將編碼后的URI放入剪貼板,此URI指向了需提供的正確記錄。此外,還必須考慮應(yīng)用程序的現(xiàn)狀:

·       如果已有一個(gè)content provider,可以增加它的功能??赡苤恍枰薷?span style="font-family: Courier new; color: #007000">query()方法,使得它能處理粘貼程序所需的URI即可。有可能要修改方法來對(duì)URI中的“copy”進(jìn)行模式匹配。

·       如果應(yīng)用程序擁有內(nèi)部數(shù)據(jù)庫,可能需要將此數(shù)據(jù)庫移入content provider,便于從中拷貝數(shù)據(jù)。

·       如果目前沒有用到數(shù)據(jù)庫,可以實(shí)現(xiàn)一個(gè)簡單的content provider,它的唯一用途就是為程序提供粘貼自剪貼板的數(shù)據(jù)。

content provider中,至少會(huì)需要覆蓋以下方法:

query()

粘貼應(yīng)用程序?qū)?huì)假定,通過此方法能夠獲取剪貼板中URI指定的數(shù)據(jù)。為了支持復(fù)制功能,應(yīng)該在本方法中對(duì)包含指定“復(fù)制”路徑的URI進(jìn)行檢測。然后,程序可以創(chuàng)建一個(gè)“復(fù)制”URI并放入剪貼板中,此URI包含了復(fù)制路徑和指向?qū)嶋H復(fù)制記錄的指針。

getType()

本方法應(yīng)該返回MIME類型或者需復(fù)制數(shù)據(jù)的類型。為了把MIME類型放入新建的ClipData對(duì)象,newUri()方法將會(huì)調(diào)用getType()。

復(fù)雜數(shù)據(jù)的MIME類型在Content Providers一節(jié)中描述。

注意,其它的content provider方法是沒必要用到的,比如insert()update()。粘貼應(yīng)用程序只需要獲取所用的MIME類型并從provider拷貝數(shù)據(jù)。如果已經(jīng)實(shí)現(xiàn)了這些方法,那它們也不會(huì)影響復(fù)制操作。

以下代碼段演示了如何建立復(fù)制復(fù)雜數(shù)據(jù)的應(yīng)用程序:

1.    聲明全局常量,定義基本URI字符串和路徑,用于指明復(fù)制數(shù)據(jù)的URI字符串。同時(shí)聲明需復(fù)制數(shù)據(jù)的MIME類型:

// 聲明基本URI字符串

privatestaticfinalString CONTACTS ="content://com.example.contacts"; 

// 聲明用于復(fù)制數(shù)據(jù)的URI路徑字符串

privatestaticfinalString COPY_PATH ="/copy"; 

 

// 聲明需復(fù)制數(shù)據(jù)的MIME類型

publicstaticfinalString MIME_TYPE_CONTACT ="vnd.android.cursor.item/vnd.example.contact"

2.    用戶復(fù)制數(shù)據(jù)的Activity中,創(chuàng)建把數(shù)據(jù)復(fù)制到剪貼板的代碼。在響應(yīng)復(fù)制請(qǐng)求時(shí),將URI放入剪貼板中:

publicclassMyCopyActivityextendsActivity{ 

    ... 

// 用戶已經(jīng)選中了姓名并請(qǐng)求復(fù)制

case<="" span="">.id.menu_copy: 

    // 在基本URI后附加姓名

    // 姓名存于"lastName" 

    uriString = CONTACTS + COPY_PATH +"/"+ lastName;<="" span="">

    // 字符串編碼為URI 

    Uri copyUri =Uri.parse(uriString);;     // 獲取剪貼板服務(wù)的句柄

    ClipboardManager clipboard d =(ClipboardManager) 

        getSystemService(Context.CLIPBOARD_SERVICE););    ClipData clip =ClipData.newUri(getContentResolver(),"URI", copyUri););    // / 設(shè)置剪貼板的主clip.    clipboard.setPrimaryClip(clip););

3.   content provider的全局部分(global scope),創(chuàng)建一個(gè)URI匹配器,并加入與剪貼板URI相匹配的URI模式。

publicclassMyCopyProviderextendsContentProvider{>{    .....// Uriri匹配器對(duì)象,用于簡化對(duì)content URI模式匹配操作。

privatestaticfinalUriMatcher sURIMatcher =newUriMatcher(UriMatcher.NO_MATCH););// 整數(shù),用于URI模式的開關(guān)變量。

privatestaticfinalint GET_SINGLE_CONTACT =>=0;.....// content URI加入匹配器。

// 匹配"content://com.example.contacts/copy/*" 

sUriMatcher.addURI(CONTACTS,"names/*", GET_SINGLE_CONTACT);

4.    建立query()方法。在本方法中可用不同的代碼處理各種URI模式,不過下面僅列出了剪貼板復(fù)制操作所用到的模式:

// 建立providerquery()方法

publicCursor query(Uri uri,String[] projection,String selection,String[] selectionArgs, 

    String sortOrder){ 

    ... 

    // 基于傳入的content URI進(jìn)行分支 

    switch(sUriMatcher.match(uri)){ 

    case GET_SINGLE_CONTACT: 

        // 根據(jù)請(qǐng)求的姓名查詢并返回contact

        // 在此應(yīng)對(duì)傳入的URI解碼,基于姓名查詢數(shù)據(jù)并返回結(jié)果Cursor

    ... 

}

5.    建立getType()方法,返回合適的返回?cái)?shù)據(jù)MIME類型:

// 建立providergetType()方法

publicString getType(Uri uri){ 

 

    ...

    switch(sUriMatcher.match(uri)))){ 

    GET_SINGLE_CONTACT: 

            return(MIME_TYPE_CONTACT););

content URI粘貼數(shù)據(jù)一節(jié)描述了如何從剪貼板獲取content URI,并用它讀取并粘貼數(shù)據(jù)。

 

復(fù)制數(shù)據(jù)流

可以將大量的文本和二進(jìn)制數(shù)據(jù)以流的形式進(jìn)行復(fù)制和粘貼。數(shù)據(jù)可以具有如下格式:

·       保存在物理設(shè)備上的文件。

·       來自socket的流。

·       保存在provider底層數(shù)據(jù)庫系統(tǒng)中的大量數(shù)據(jù)。

數(shù)據(jù)流content provider用文件描述符對(duì)象而不是Cursor< span="">AssetFileDescriptor。粘貼應(yīng)用程序利用此文件描述符來讀取數(shù)據(jù)流。流。

要建立用provider復(fù)制數(shù)據(jù)流的應(yīng)用程序,請(qǐng)按以下步驟進(jìn)行:

1.    為放入剪貼板的數(shù)據(jù)流建立content URI。可有以下選擇:

o                將數(shù)據(jù)流的ID編入URI,如上ID編入URI所述,然后在provider中保存一張表,其中包含了ID和相關(guān)的流名稱。

o                將流名稱直接編入URI。

o                用唯一的URI,總是從provider返回當(dāng)前流。如果選用此項(xiàng),則每次通過URI把流復(fù)制到剪貼板時(shí),必須記得更新provider,使它指向新的流。

2.    為每類提供的數(shù)據(jù)流指定一個(gè)MIME類型。粘貼應(yīng)用程序需要此信息來確定能否粘貼剪貼板中的數(shù)據(jù)。

3.    實(shí)現(xiàn)ContentProvider中的一個(gè)方法,返回流的文件描述符。如果ID已編入content URI,則用此方法來確定需要打開的流。

4.    把數(shù)據(jù)復(fù)制到剪貼板時(shí),構(gòu)造content URI并放入剪貼板中。

要粘貼數(shù)據(jù)流時(shí),應(yīng)用程序先從剪貼板獲取clip,讀取URI,然后調(diào)用ContentResolver文件描述符方法打開流。ContentResolver方法將調(diào)用相應(yīng)的ContentProvider方法,把content URI傳入其中。provider把文件描述符返回給ContentResolver方法。這時(shí)粘貼程序就能讀取流中的數(shù)據(jù)了。

以下列表展示了對(duì)content provider而言最重要的文件描述符方法。每個(gè)方法都有后綴名為“Descriptor< span="">ContentResolver方法與之相對(duì)應(yīng)。比如,模擬openAssetFile()ContentResolveropenAssetFileDescriptor()

openTypedAssetFile()
僅當(dāng)給出的MIME類型能被provider支持時(shí),本方法返回一個(gè)asset文件描述符。調(diào)用方(執(zhí)行粘貼的應(yīng)用)提供MIME類型模式。如果能提供此類型MIME的話,content provider(把URI復(fù)制到剪貼板的應(yīng)用)將返回一個(gè)AssetFileDescriptor文件句柄,不能提供則拋出異常。常。
本方法用于處理文件的片段,可以用它讀取content provider拷入剪貼板的asset

openAssetFile()
本方法是比openTypedAssetFile()更通用的方法。它不對(duì)支持的MIME類型進(jìn)行判斷過濾,但可用于讀取文件的片段。

openFile()
這是比openAssetFile()更加通用的格式。它不能讀取文件片段。

可以選用openPipeHelper()方法作為文件描述符方法,這讓粘貼應(yīng)用可以用管道在后臺(tái)讀取流數(shù)據(jù)。使用此方法需要實(shí)現(xiàn)ContentProvider.PipeDataWriter接口。在Note Pad示例程序中有相關(guān)例程,位于NotePadProvider.java中的openTypedAssetFile()方法。

 

要為應(yīng)用程序設(shè)計(jì)高效的復(fù)制與粘貼功能,請(qǐng)記住以下幾點(diǎn):

·       任何時(shí)候,剪貼板中都只有一個(gè)clip。系統(tǒng)中任何應(yīng)用程序執(zhí)行了新的復(fù)制操作,都會(huì)覆蓋之前的clip 。由于用戶可能會(huì)跳離應(yīng)用程序,并在返回前執(zhí)行了復(fù)制,因此不能假定剪貼板中包含了前一次在此程序中復(fù)制的內(nèi)容。

·       設(shè)計(jì)clip< span="">ClipData.Item對(duì)象的初衷,是為了支持一次復(fù)制和粘貼多個(gè)選項(xiàng),而不是為了單個(gè)選項(xiàng)能包含多種不同的格式。通常一個(gè)clip中的所有ClipData.Item對(duì)象都應(yīng)該具有相同的格式,也就是說,它們應(yīng)該全都是簡單文本、或者或者content URI、或者Intent,而不能混在一起使用。

·       提供數(shù)據(jù)時(shí),可以提交各種不同的MIME描述。把所支持的MIME< span="">ClipDescription,然后在content provider中實(shí)現(xiàn)這些MIME類型。

·       從剪貼板讀取數(shù)據(jù)時(shí),應(yīng)用程序有責(zé)任對(duì)可用的MIME類型進(jìn)行檢查,然后決定要使用哪些類型。即使剪貼板中存在clip,而用戶也請(qǐng)求了粘貼,應(yīng)用程序也不一定要執(zhí)行粘貼。應(yīng)該MIME類型能夠兼容時(shí)才執(zhí)行粘貼。可以選用coerceToText()把剪貼板數(shù)據(jù)強(qiáng)制轉(zhuǎn)換成文本。如果應(yīng)用程序能支持更多可用的用的MIME類型,可以讓用戶先選擇其中一個(gè)再使用。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    欧美午夜一级特黄大片| 国产日产欧美精品视频| 激情三级在线观看视频| 国内真实露脸偷拍视频| 日本丁香婷婷欧美激情| 99国产高清不卡视频| 东京热加勒比一区二区| 国产三级视频不卡在线观看| 国产一区二区三区不卡| 日本免费熟女一区二区三区| 国产欧美日韩综合精品二区| 久久这里只有精品中文字幕| 亚洲夫妻性生活免费视频| 久久大香蕉精品在线观看| 在线免费不卡亚洲国产| 国产欧美一区二区久久| 欧美一级片日韩一级片| 男人和女人草逼免费视频| 国产中文另类天堂二区| 免费大片黄在线观看国语| 日本和亚洲的香蕉视频| 天堂网中文字幕在线观看| 人人妻在人人看人人澡| 人妻熟女欲求不满一区二区| 好骚国产99在线中文| 男人和女人黄 色大片| 蜜桃臀欧美日韩国产精品| 富婆又大又白又丰满又紧又硬| 日韩中文字幕有码午夜美女| 国产视频在线一区二区| 日本久久中文字幕免费| 大香蕉精品视频一区二区| 国产精品久久熟女吞精| 中文字幕在线区中文色| 中日韩美一级特黄大片| 午夜视频成人在线免费| 日韩欧美高清国内精品| 午夜福利在线观看免费| 91日韩欧美国产视频| 国产内射一级二级三级| 亚洲欧洲一区二区综合精品|