天天看點

【Android】分享功能

安卓系統本身可以很簡便的實作分享功能,因為我們隻需向startActivity傳遞一個ACTION_SEND的Intent,系統就為我們彈出一個應用程式清單。其實在系統的檔案管理器中,這應該是我們常用的功能(包括檔案的打開Intent.ACTION_VIEW)。

下面列出一個簡單的分享方式

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

前兩行代碼不用說了,就是一個簡單的Action Intent,第三行的Intent.EXTRA_TEXT,是文本類型,還有EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT等等,這些看字面意思就可以了解。 

重點說一下Intent.EXTRA_STREAM。 

設定合适的MIME類型,并且在附件資料中的EXTRA_STREAM中放一個指向資料的URI,就可以來分享二進制資料。這個通常用來分享圖檔,但是也可以用來分享任何類型的二進制内容,比如視訊,檔案等等。

Intent shareIntent = newIntent();
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)));      

下面說一下Intent.setType這個方法: 

參數有很多種,簡單列出幾個,”text/plain”、”image/jpeg”、”audio/mp4a-latm”、”audio/x-mpeg”、 “video/mp4”還有很多很多… 

這裡給出一個擷取類型的方法

/**
     * 根據檔案字尾名獲得對應的MIME類型。
     * @param filePath
     */
    public static String getMimeType(String filePath) {
        MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        String mime = "text/plain";
        if (filePath != null) {
            try {
                mmr.setDataSource(filePath);
                mime = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE);
            } catch (IllegalStateException e) {
                return mime;
            } catch (IllegalArgumentException e) {
                return mime;
            } catch (RuntimeException e) {
                return mime;
            }
        }
        return mime;
    }      
我們可以**同時發送多條内容**,要發送多條資料,使用ACTION_SNED_MULTIPLE和一個指向資料的URI list。MIME類型根據分享的内容不同而不同。例如,如果分享3張JPEG圖檔,那麼類型為"image/jpeg"。如果有不同的圖檔類型,那麼就應該用"image/*"來比對處理不同類型圖檔的activity。如果要處理各種不同的類型就應該用"*/*"了。正如前面提到的,分析和處理分享是資料是接收程式的事情了。
但是需要明确的一點是,**要確定URI指向的資料要可以被接收程式通路到**。

另外一個知識點就是,我們可以對分享的App進行篩選,比如我隻想分享到QQ和微信平台,不關心人人網,迅雷這樣的App
可通過Intent.createChooser方法實作,
首先我們定義一個Action Intent      
String type = getMimeType(path);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
            shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            shareIntent.setType(getMimeType(path));      
然後擷取可以用來發送該類型檔案的ResolveInfo清單,也就是可以發送這種檔案的應用清單資訊      
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(shareIntent, 0);      

通過包名篩選出我們想要的應用

ArrayList<Intent> targetIntents = new ArrayList<Intent>();
                for (ResolveInfo info : resInfo) {
                    ActivityInfo activityInfo = info.activityInfo;
                    if (activityInfo.packageName.contains("com.tencent.mobileqq")
                            ||activityInfo.packageName.contains("com.tencent.mm")) {
                        Intent intent = new Intent(Intent.ACTION_SEND);
                        intent.setPackage(activityInfo.packageName);
                        intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
                        intent.setClassName(activityInfo.packageName, activityInfo.name);
                        targetIntents.add(intent);
                    }


                }      

最後用Intent.createChooser打開

Intent chooser = Intent.createChooser(targetIntents.remove(0), "Send mail...");
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
                context.startActivity(chooser);      

到此,利用Intent.ACTION_SEND進行分享就差不多介紹完了,是不是比申請友盟以及各個平台要友善的多…

/**
     * 發送檔案
     * @param context
     * @param path
     */
    public static void sendFileByOtherApp(Context context, String path) {
        File file = new File(path);
        if (file.exists()) {
            String type = getMimeType(path);
            Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
            shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            shareIntent.setType(getMimeType(path));
            List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(shareIntent, 0);
            if (!resInfo.isEmpty()) {
                ArrayList<Intent> targetIntents = new ArrayList<Intent>();
                for (ResolveInfo info : resInfo) {
                    ActivityInfo activityInfo = info.activityInfo;
                    if (activityInfo.packageName.contains("com.tencent.mobileqq")
                            ||activityInfo.packageName.contains("com.tencent.mm")) {
                        Intent intent = new Intent(Intent.ACTION_SEND);
                        intent.setPackage(activityInfo.packageName);
                        intent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
                        intent.setClassName(activityInfo.packageName, activityInfo.name);
                        targetIntents.add(intent);
                    }


                }
                Intent chooser = Intent.createChooser(targetIntents.remove(0), "Send mail...");
                chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
                context.startActivity(chooser);

            }
        }

    }      
當然,我們也可以做一個Activity,像QQ微信一樣,來接收檔案或者wen z,隻要會使用intentfilter就可以了      
<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>      
if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
            handleSendText(intent); // 處理發送來的文字
        } else if (type.startsWith("image/")) {
            handleSendImage(intent); // 處理發送來的圖檔
        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/")) {
            handleSendMultipleImages(intent); // 處理發送來的多張圖檔
        }
    } else {
        // 處理其他intents,比如由主屏啟動
    }