天天看點

Android Develop Training——資料共享(Sharing Content)

資料共享

         能夠互相交流和整合是Android應用非常重要的一個功能,是以才會有當已經有一個應用存在這個功能時,在你的應用中這個功能就不算是一個核心功能的說法。

         本課将向你講述通過Intent和ActionProvider在應用中接收和發送内容的一些方法。

發送内容到其它程式

         當你執行個體化一個Intent對象時,你必須要為其指定你想要做什麼事的意圖。Android定義了一系列的動作屬性,其中就包括ACTION_SEND,看它的名字你可能就已經猜到它的意思了,就是在同一程序或者不同程序中,從一個視窗往另一個視窗發送資料。為了能夠在視窗之間傳遞資料,你需要指定資料和資料類型,這樣系統才能夠識别哪些視窗可以接收這些資訊,然後将這些應用以一個對話框的形式顯示出來(如果有多于一個應用可以執行這些操作的話)或者直接啟動符合要求的視窗(如果隻有一個應用滿足條件)。同樣的,你可以在你的清單檔案Manifest.xml中為你的視窗設定資料類型,其它應用就可以在設定好對應類型的情況下跳轉到你的視窗了。

         在不同應用之間發送和接收資料在社交分享應用中使用得尤為地多,使用者可以通過intent可以快捷友善的分享資訊到他們喜歡的應用上去。

注意:分享功能實作的最好方式是使用ShareActionProvider在ActionBar上添加一個分享操作項,但前提是你的API版本是14及以上版本。

發送文本内容

         使用ACTION_SEND最直接和最多的是在視窗間傳送文本内容,比如系統内置的浏覽器應用可以将目前顯示的網頁對應的URL位址以文本的方式分享給其它任何應用。可見以文本的形式通過郵件或者社交網絡分享文章和網址是非常有用的,下面是視窗間傳遞文本内容的一個具體實作:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

           

         如果目前裝置中同時存在一個filter為”ACTION_SEND”,MIME類型為”text/plain”的視窗,android系統将會啟動它,如果多于一個應用滿足比對條件,系統将顯示一個列出所有能夠啟動應用的對話框供使用者選擇。當然了,如果你在執行個體化Intent的時候使用了語句”Intent.createChooser()”,android系統會直接顯示你所選擇的應用,這樣做的好處在于:

1、  即使是使用者之前從對話框中選擇了一個預設的應用,經過上面的設定後,再次啟動應用時會直接跳轉到在代碼中設定的應用;

2、  如果目前裝置中沒有符合條件的應用,android會顯示一條系統提示資訊;

3、  你可以為選擇對話框設定标題。

下面是更新後的代碼:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));

           
Android Develop Training——資料共享(Sharing Content)

具體效果如上圖所示。

         或者,你可以為intent設定一些标準的extra:EXTRA_EMAIL,EXTRA_CC,EXTRA_BCC,EXTRA_SUBJECT。然而,如果接受這些消息的應用沒有打算用這些extra,即使你這樣設定了但什麼事情也不會發生。别擔心,即使應用沒有處理這些資訊,但程式還是會正常運作的。從技術的角度來講,你最好是使用接收消息的應用自定義的extra。

注意:一些郵件應用,比如Gmail,你可以通過intent的putExtra(String,String[])方法來傳遞一些額外的EXTRA_EMAIL和EXTRA_CC資訊給它們。

發送二進制内容

         應用間傳遞二進制資訊時,要ACTION_SEND結合設定MIME類型來使用,并且通過EXTRA_STREAM以URI的方式來傳遞這些資料,這種方式通常用于分享圖檔,但也可以分享其它任何是二進制的資料。

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));

           

在使用的過程中你需要注意以下幾點:

1、  你可以将MIME的類型設定為”**”。正如前面所描述的那樣,這些都是由接收intent的應用解析和處理你的資料而定的,請看下面的例子:

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));

           

         請確定接收intent的應用可以通路傳遞的uri所指向的資料。

接收從其它應用傳遞過來的資料

         既然你的應用可以發送資料給其它應用,那同樣也可以接收從其它應用傳遞過來的資料。想象一下使用者是怎樣和你的程式進行互動的,哪種資料類型是你希望從其它應用中接收的。比如,一個社交網絡應用會傾向于接收純文字内容,比如從其它應用傳遞過來的一個網頁連結。比如Google+安卓用戶端能夠接收純文字或者單個和多個圖像。通過它,使用者可以輕松地将畫廊應用中的圖檔發送到Google+。

更新你的清單檔案

         通過清單檔案中的Intent過濾器就可以讓系統知道,你的應用希望接收那種類型的資料。就像之前的課程所講,你可以在清單檔案中定義一個intent過濾器來接收ACTION_SEND所發送的action。比如,如果你的應用可以操作接收的文本内容、可以是不同格式的一張圖檔,或者是多張不同格式的圖檔,你的清單檔案看起來是這個樣子的。

<activity android:name=".ui.MyActivity" >
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

           

         在清單檔案中設定後這些資訊後,當其它應用通過startActivity()傳遞符合過濾條件的資料類型的時候,你的應用将被系統作為可接受這些資料的應用而加入intent選擇清單,如果使用者選擇了通過你的應用來啟動,你應用的主視窗将被啟動,然後就是該你操作這些資料了。

處理接收到的内容

         為了能夠處理通過Intent傳遞過來的内容,你需要通過getIntent()方法來擷取Intent執行個體,一旦你擷取到了Intent執行個體,你就可以做你想做的事情了。記住,如果這個視窗可以被系統的某個應用啟動,比如桌面,你需要考慮intent為空的情況。比如:

void onCreate (Bundle savedInstanceState) {
    ...
    // Get intent, action and MIME type
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();

    if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent); // Handle text being sent
        } else if (type.startsWith("image/")) {
            handleSendImage(intent); // Handle single image being sent
        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/")) {
            handleSendMultipleImages(intent); // Handle multiple images being sent
        }
    } else {
        // Handle other intents, such as being started from the home screen
    }
    ...
}

void handleSendText(Intent intent) {
    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    if (sharedText != null) {
        // Update UI to reflect text being shared
    }
}

void handleSendImage(Intent intent) {
    Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
    if (imageUri != null) {
        // Update UI to reflect image being shared
    }
}

void handleSendMultipleImages(Intent intent) {
    ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    if (imageUris != null) {
        // Update UI to reflect multiple images being shared
    }
}

           

注意:切記檢查你接收到的資訊,因為你不可能控制其它程式給你發送的内容,比如,其它應用傳遞過來的MIME類型可能是錯的,或者傳了一張非常大的圖檔。還有,如果你需要處理接收的二進制資料,記得開一個線程,不要直接在UI線程裡面整。

         更新的UI可能是一個簡簡單單的EditText,也可能是一個圖像過濾視窗。

添加一個簡單的分享操作

         從Android 4.0開始,通過ActionProvider在操作欄上實作一個有良好使用者體驗的分享操作是非常簡單的一個事情,一個ActionProvider,一旦與操作欄的某一個菜單項綁定,就可以接管這個菜單項的所有行為了,如果你使用的是ShareActionProvider,你隻需要提供一個分享intent,其它的事情你就不用管了。

注意:隻有在Android 4.0及以上的版本才支援ShareActionProvider。

更新菜單的定義

         在使用ShareActionProviders時,你需要在菜單的資源檔案中item标簽下定義android:ctionProviderClass屬性。

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_item_share"
        android:showAsAction="ifRoom"
        android:title="Share"
        android:actionProviderClass="android.widget.ShareActionProvider" />
    ...
</menu>

           

         這樣,ShareActionProvider就可以接管該菜單項的所有行為了,但要記住,你需要告訴這個provider你希望分享什麼。

設定分享Intent

         為了讓ShareActionProvider生效,你必須為其提供分享意圖,分享意圖可以是ACTION_SEND和EXTRA_TEXT、EXTRA_STREAM,具體執行個體如下:

private ShareActionProvider mShareActionProvider;
...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate menu resource file.
    getMenuInflater().inflate(R.menu.share_menu, menu);

    // Locate MenuItem with ShareActionProvider
    MenuItem item = menu.findItem(R.id.menu_item_share);

    // Fetch and store ShareActionProvider
    mShareActionProvider = (ShareActionProvider) item.getActionProvider();

    // Return true to display menu
    return true;
}

// Call to update the share intent
private void setShareIntent(Intent shareIntent) {
    if (mShareActionProvider != null) {
        mShareActionProvider.setShareIntent(shareIntent);
    }
}

           

         一旦你建立你的菜單時你就需要設定分享意圖,有可能在程式運作的過程中這個設定内容會更改,比如當你在畫廊應用中全屏浏覽圖檔的時候,分享的intent會在你圖檔切換時改變。

原文連結:Sharing Content