Android利用intent實現分享功能
一、 概述
現在的社會化分享大多使用了第三方的分享,例如友盟,ShareSDK等等,當然也有使用微信,QQ等官方的SDK進行分享。不過這些方法比較繁瑣,如果沒有特別要求,只希望將資訊分享出去,我們可以利用安卓的intent來做這個事情。
二、 簡單Intent的構建
在構建一個intent時,必須指定這個intent需要觸發的action。Android定義了一些actions,比如ACTION_SEND,該action表明該intent用於從一個activity傳送資料到另外一個activity的,甚至可以是跨程序的資料傳送。
為了傳送資料到另一個Activity,我們只需要指定資料和資料的型別,系統就會自動識出能夠接收這些資料型別的Activity。如果選擇有多個,就會把這些Activity顯示給使用者進行選擇;如果只有一個,則立即啟動該Activity。
下面列出一個簡單的分享方式
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT,"文字分享"); intent.setType("text/plain"); startActivity(intent);
putExtra()方法中放入的是分享的內容;
setType()設定分享的型別;
利用這樣的分享方式進行分享時,會出現一個設定預設的選擇,選定後,系統預設此型別的分享內容一直使用選定的程式進行,這樣顯然不符合我們的分享需求。我們可以使用下面的方法:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT,"文字分享"); intent.setType("text/plain"); startActivity(Intent.createChooser(intent,"選擇分享應用"));
呼叫Intent.createChooser()這個方法,此時即使使用者之前為這個intent設定了預設,選擇介面還是會顯示,並且我們可以指定選擇介面的標題。
此外,我們不僅可以分享文字,還可以分享圖片、視訊、檔案等。需要改變的就是putExtra()方法和setType()方法。Intent.EXTRA_TEXT,是文字型別,除此之外還有一個重要Intent.EXTRA_STREAM,在附件資料中的EXTRA_STREAM中放一個指向資料的URI,就可以來分享二進位制資料。這個通常用來分享圖片,也可以用來分享任何型別的二進位制內容。如下所示:
Uri uri = Uri.parse("file://" + image.getImagePath()); Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType("image/*"); startActivity(Intent.createChooser(intent, "選擇分享應用"));
setType()方法根據要分享的內容的型別,還可以有“audio/mp4a-latm”、“audio/x-mpeg”、 “video/mp4”…很多型別。
三、 分享應用的過濾
通過上面的設定,我們會發現,系統彈出了很多方式,包括郵件、簡訊、藍芽之類的,有些應用我們不希望顯示出來,我們就可以使用以下方法:
1、首先,我們定義一個圖片的分享,繼續沿用上面的方式:
Uri uri = Uri.parse("file://" + image.getImagePath()); Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType("image/*"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
2、然後獲取匹配圖片型別的應用資訊列表:
PackageManagerpm = getPackageManager(); List<ResolveInfo> resInfo = pm.queryIntentActivities(intent,0); if(resInfo.isEmpty()){ Toaster.showShort(this,"沒有可以分享的應用"); return; }
3、接下來遍歷這個集合,通過包名篩選出我們想要顯示的應用(微信和QQ):
在進行篩選時,需要注意的一點是setType()方法是必須設定的,不然的話不能跳轉到選擇的應用。
List<Intent> targetIntents = new ArrayList<>(); for (ResolveInfo resolveInfo : resInfo) { ActivityInfo activityInfo = resolveInfo.activityInfo; if (activityInfo.packageName.contains("com.tencent.mm") || activityInfo.packageName.contains("com.tencent.mobileqq")){ //過濾掉qq收藏 if (resolveInfo.loadLabel(pm).toString().contains("QQ收藏")){ continue; } Intent target = new Intent(); target.setAction(Intent.ACTION_SEND); target.setComponent(new ComponentName(activityInfo.packageName,activityInfo.name)); target.putExtra(Intent.EXTRA_STREAM, uri); target.setType("image/*");//必須設定,否則選定分享型別後不能跳轉介面 targetIntents.add(new LabeledIntent(target,activityInfo.packageName,resolveInfo.loadLabel(pm),resolveInfo.icon)); } } if (targetIntents.size()<= 0){ Toaster.showShort(this,"沒有可以分享的應用"); return; }
4、最後呼叫createChooser方法,顯示分享dialog
Intent chooser = Intent.createChooser(targetIntents.remove(targetIntents.size() - 1), "選擇分享"); if (chooser == null) return; LabeledIntent[] labeledIntents = targetIntents.toArray(new LabeledIntent[targetIntents.size()]); chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,labeledIntents); startActivity(chooser);
createChooser()方法最終展示給使用者的選擇包括,符合createChooser第一個引數的應用以及由EXTRA_INTENT_INTENTS指定的應用。
效果圖如下:

1.效果圖
四、 多張圖片的分享
上述方法都是對單個圖片的分享,如果我們想要一次分享多張圖片,要怎麼做呢?其實很簡單,只需要把多張圖片的uri裝進一個集合裡,並將action設定為ACTION_SEND_MULTIPLE多個檔案傳送模式,並把uri集合傳入即可,程式碼如下所示:
ArrayList<Uri> myList = new ArrayList<>(); Intent target = new Intent(); target.setAction(Intent.ACTION_SEND_MULTIPLE); target.putParcelableArrayListExtra(Intent.EXTRA_STREAM, myList); target.setType("image/*"); startActivity(Intent.createChooser(target,"選擇分享"));
上述程式碼中沒有對分享應用進行過濾,如果需要進行過濾,可以參考第三小節進行。
五、 總結
最後呢,總結一下利用Android原生實現分享和利用第三方SDK實現的優缺點,如下表中所示:
分享型別 | 優勢 | 劣勢 |
---|---|---|
原生分享 | 1.簡單粗暴,輕鬆實現分享功能;2沒有多餘的架包和依賴庫3.無需去申請繁瑣AppKey | 1.系統會調出手機中所有具有分享的功能的App;2.介面風格不統一跟隨系統的版本; 3.如果沒有安裝需要分享的指定APP,則無法分享 |
第三方SDK | 1.可以統一分享的介面風格;2.支援網頁分享和App直接分享; 3.分享型別比較多,封裝了分享內容的樣式 | 1.需要新增大量依賴庫和架包;2.需要去申請繁瑣的AppKey;3.經常更新版本,相容性和穩定性不好 |
六、 補充
在Android 7.0及以上系統,限制了file域的訪問,導致進行intent分享的時候,會報錯甚至崩潰。我們需要在App啟動的時候在Application的onCreate方法中新增如下程式碼,解除對file域訪問的限制:
if(VERSION.SDK_INT >= 24) { Builder builder = new Builder(); StrictMode.setVmPolicy(builder.build()); }