本文對應(yīng)的Git項目
本文主要介紹以下功能:
- 分享(純文本|圖片|文件)給QQ好友
- QZone(QQ空間)-分享到“QQ空間”應(yīng)用-目前QQ不支持分享到QQ中自帶空間
- 新浪微博分享-分兩種(1)分享給好友仅偎;(2)分享到微博內(nèi)容
- 直接分享(純文本|圖片|文件)給微信好友
- 直接分享圖片到微信朋友圈
注意-更新于19年5月23日:
1.微信在6.6.7版本以后跨蟹,已經(jīng)不支持往朋友圈分享標(biāo)題了,具體請點(diǎn)擊查看
2.微信在6.7.3版本以后橘沥,已經(jīng)不支持往朋友圈分享多圖了窗轩,具體請點(diǎn)擊查看 - android7.0以上系統(tǒng)獲取url的方法
- 保存圖片
- 直接添加進(jìn)入QQ群
簡單說明-也是我當(dāng)時需要要做出來的效果:
1.QQ:分享到QQ好友時,直接以發(fā)文本的方式分享出去座咆,字?jǐn)?shù)不受限制
2.WechatMoment : 分享到微信朋友圈時痢艺,需要將圖片帶到發(fā)送朋友圈圖文發(fā)送界面直接發(fā)送分享(新版微信不支持同時帶文本)
3.直接分享圖片給微信好友
說到分享許多人都會使用一些第三方sdk來實現(xiàn),比如“友盟分享”介陶,“Mob分享(ShareSdk)”堤舒。
這兩種分享方式需要配置許多文件和代碼,雖說省去了我們一個個集成各大網(wǎng)站分享的sdk哺呜,但常常也會自帶許多坑植酥,具體的大家在使用的時候就會發(fā)現(xiàn),我就不評價了弦牡。
QQ分享:無論是友盟或sharesdk友驮,都無法實現(xiàn)直接將長文本分享到QQ好友,原因是什么驾锰?我找過他們客服卸留,這是tencent(騰訊)公司分享sdk規(guī)定的。具體可查看:鏈接中的 1.13 分享消息到QQ(無需QQ登錄)的參數(shù)椭豫,以QQapi上的代碼進(jìn)行分享以后除了文本字?jǐn)?shù)有限制以外耻瑟,而且其分享的樣式是以鏈接的形式分享出去的,所以不符合我的要求赏酥。
WechatMoment微信朋友圈分享:以官方文檔或以第三方通道分享時喳整,在分享到朋友圈的時候,分享文本是設(shè)置不到文本區(qū)域的裸扶,無論你用啥方法框都。因為ShareSdk官方文檔也說了:查看第4點(diǎn)(微信(好友、朋友圈呵晨、收藏))當(dāng)你需要同時設(shè)置分享圖片和文本時你設(shè)置的text是不顯示的魏保。
我的解決方案:(使用Intent分享)但有個缺點(diǎn)是熬尺,分享到平臺后卻不能返回到原應(yīng)用,只能留在QQ或微信(除在微信分享文件-分享文件給好友可以返回到原應(yīng)用)
先給大家提供個判斷QQ向微信客戶端是否存在的兩個方法:
調(diào)用方式如:Platformutil.isInstallApp(context,PlatformUtil.PACKAGE_WECHAT);// 判斷微信是否安裝
public class PlatformUtil {
public static final String PACKAGE_WECHAT = "com.tencent.mm";
public static final String PACKAGE_MOBILE_QQ = "com.tencent.mobileqq";
public static final String PACKAGE_QZONE = "com.qzone";
public static final String PACKAGE_SINA = "com.sina.weibo";
// 判斷是否安裝指定app
public static boolean isInstallApp(Context context, String app_package){
final PackageManager packageManager = context.getPackageManager();
List<PackageInfo> pInfo = packageManager.getInstalledPackages(0);
if (pInfo != null) {
for (int i = 0; i < pInfo.size(); i++) {
String pn = pInfo.get(i).packageName;
if (app_package.equals(pn))) {
return true;
}
}
}
return false;
}
}
QQ分享(分享至QQ好友或群組):
/**
* 直接分享純文本內(nèi)容至QQ好友
* @param mContext
* @param content
*/
public static void shareQQ(Context mContext, String content) {
if (Platformutil.isInstallApp(mContext,PlatformUtil.PACKAGE_MOBILE_QQ)) {
Intent intent = new Intent("android.intent.action.SEND");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "分享");
intent.putExtra(Intent.EXTRA_TEXT, content);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(new ComponentName("com.tencent.mobileqq", "com.tencent.mobileqq.activity.JumpActivity"));
mContext.startActivity(intent);
} else {
Toast.makeText(mContext, "您需要安裝QQ客戶端", Toast.LENGTH_LONG).show();
}
}
/**
* 分享圖片給QQ好友
*
* @param bitmap
*/
public void shareImageToQQ(Bitmap bitmap) {
if (Platformutil.isInstallApp(mContext,PlatformUtil.PACKAGE_MOBILE_QQ)) {
try {
Uri uriToImage = Uri.parse(MediaStore.Images.Media.insertImage(
mContext.getContentResolver(), bitmap, null, null));
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.setType("image/*");
// 遍歷所有支持發(fā)送圖片的應(yīng)用谓罗。找到需要的應(yīng)用
ComponentName componentName = new ComponentName("com.tencent.mobileqq", "com.tencent.mobileqq.activity.JumpActivity");
shareIntent.setComponent(componentName);
// mContext.startActivity(shareIntent);
mContext.startActivity(Intent.createChooser(shareIntent, "Share"));
} catch (Exception e) {
// ContextUtil.getInstance().showToastMsg("分享圖片到**失敗");
}
}
}
之前有同學(xué)說在分享QQ和微信的時候粱哼,發(fā)現(xiàn)只要QQ或微信在打開的情況下,再調(diào)用分享只是打開了QQ和微信檩咱,卻沒有調(diào)用選擇分享聯(lián)系人的情況揭措,這里,我要感覺一下@[努力搬磚]同學(xué)刻蚯,他找出了原因绊含。
解決辦法如下:
mActivity.startActivity(intent);//如果微信或者QQ已經(jīng)喚醒或者打開,這樣只能喚醒微信芦倒,不能分享
請使用 mActivity.startActivity(Intent.createChooser(intent, "Share"));
QZone(QQ空間)
經(jīng)過我反復(fù)試驗艺挪,通過adb(方法:adb shell “dumpsys window | grep mCurrentFocus”)查找QQ中的空間發(fā)布說說界面是:cooperation.qzone.QzonePublishMoodProxyActivity,但始終歪能成功兵扬,在網(wǎng)上看到有人說是該界面沒有對外開放麻裳,所以這里只能通過調(diào)用qq空間app打開發(fā)布界面進(jìn)行分享內(nèi)容!(強(qiáng)調(diào):不是QQ內(nèi)自帶發(fā)布界面器钟,是QQ空間單獨(dú)的APP)津坑。后期再研究下能否直接使用QQ內(nèi)直接的界面。
/**
* description : 分享到QQ空間
* created at 2018/7/9 17:04
*
* @param photoPath 照片路徑
*/
public void shareImageToQQZone(String photoPath) {
try {
if (PlatformUtil.isInstalledSpecifiedApp(mActivity, PlatformUtil.PACKAGE_QZONG)) {
File file = new File(photoPath);
if (!file.exists()) {
String tip = "文件不存在";
Toast.makeText(mActivity, tip + " path = " + photoPath, Toast.LENGTH_LONG).show();
return;
}
Intent intent = new Intent();
ComponentName componentName = new ComponentName(PlatformUtil.PACKAGE_QZONG, PlatformUtil.ACTIVITY_SHARE_QQ_ZONE);
intent.setComponent(componentName);
intent.setAction("android.intent.action.SEND");
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_TEXT, "I'm so tired!!");
if (file.isFile() && file.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(mContext, ShareToolUtil.AUTHORITY, file);
} else {
uri = Uri.fromFile(file);
}
intent.putExtra(Intent.EXTRA_STREAM, uri);
}
mActivity.startActivity(intent);
} else {
Toast.makeText(mActivity, "您需要安裝QQ空間客戶端", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Wechat(微信好友)
/**
* 直接分享圖片到微信好友
* @param context
* @param picFile
*/
public static void shareWechatFriend(Context context,String content ,File picFile){
if (Platformutil.isInstallApp(mContext,PlatformUtil.PACKAGE_WE_CHAT)){
Intent intent = new Intent();
ComponentName cop = new ComponentName("com.tencent.mm","com.tencent.mm.ui.tools.ShareImgUI");
intent.setComponent(cop);
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
if (picFile != null) {
if (picFile.isFile() && picFile.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, ShareToolUtil.AUTHORITY, picFile);
} else {
uri = Uri.fromFile(picFile);
}
intent.putExtra(Intent.EXTRA_STREAM, uri);
// intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri);
}
}
// intent.putExtra("Kdescription", !TextUtils.isEmpty(content) ? content : "");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// context.startActivity(intent);
context.startActivity(Intent.createChooser(intent, "Share"));
}else{
Toast.makeText(context, "您需要安裝微信客戶端", Toast.LENGTH_LONG).show();
}
}
/**
* 直接分享文本到微信好友
*
* @param context 上下文
*/
public void shareWechatFriend(Context context, String content) {
if (Platformutil.isInstallApp(mContext,PlatformUtil.PACKAGE_WE_CHAT)) {
Intent intent = new Intent();
ComponentName cop = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI");
intent.setComponent(cop);
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("android.intent.extra.TEXT", content);
// intent.putExtra("sms_body", content);
intent.putExtra("Kdescription", !TextUtils.isEmpty(content) ? content : "");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
Toast.makeText(context, "您需要安裝微信客戶端", Toast.LENGTH_LONG).show();
}
}
WechatMoment(微信朋友圈)分享:
(這段更新時間:19-05-23)可查看文章開頭更新內(nèi)容傲霸,這里說一下解決方法:在不能分享標(biāo)題到朋友圈的時候疆瑰,可以在點(diǎn)擊分享按鈕時,將需要分享的內(nèi)容復(fù)制到剪貼板昙啄,并toast給用戶到微信朋友圈發(fā)布界面粘帖穆役。
/**
* 直接分享文本和圖片到微信朋友圈
* @param context
* @param content
*/
public static void shareWechatMoment(Context context, String content, File picFile) {
if (PlatformUtil. isInstallApp(context,PlatformUtil.PACKAGE_WECHAT)) {
Intent intent = new Intent();
//分享精確到微信的頁面,朋友圈頁面梳凛,或者選擇好友分享頁面
ComponentName comp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareToTimeLineUI");
intent.setComponent(comp);
// intent.setAction(Intent.ACTION_SEND_MULTIPLE);// 分享多張圖片時使用
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
//添加Uri圖片地址--用于添加多張圖片
//ArrayList<Uri> imageUris = new ArrayList<>();
//intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
if (picFile != null) {
if (picFile.isFile() && picFile.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, ShareToolUtil.AUTHORITY, picFile);
} else {
uri = Uri.fromFile(picFile);
}
intent.putExtra(Intent.EXTRA_STREAM, uri);
}
}
// 微信現(xiàn)不能進(jìn)行標(biāo)題同時分享
// intent.putExtra("Kdescription", !TextUtils.isEmpty(content) ? content : "");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
Toast.makeText(context, "您需要安裝微信客戶端", Toast.LENGTH_LONG).show();
}
}
在上面微信好友和朋友圈分享的過程中遇到了這樣一串代碼:
if (picFile.isFile() && picFile.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, ShareToolUtil.AUTHORITY, picFile);
} else {
uri = Uri.fromFile(picFile);
}
intent.putExtra(Intent.EXTRA_STREAM, uri);
// intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri);
}
上面這部分代碼主要功能是判斷了下文件是否存在耿币,在android版本高過7.0(包括7.0版本)當(dāng)前APP是不能直接向外部應(yīng)用提供file開頭的的文件路徑,需要通過FileProvider轉(zhuǎn)換一下韧拒。否則在7.0及以上版本手機(jī)將直接crash淹接。
這里再提供下我這里具體的邏輯:
常量:ShareToolUtil.AUTHORITY --寫在哪兒無所謂,只要能調(diào)用到
public static final String AUTHORITY = "com.gudd.demo.fileprovider";
// AndroidManifest需要加一個provider的標(biāo)簽叛溢,里面的authorities就是我們上面需要調(diào)用的一個常量
// 如果你有多個module的話也沒關(guān)系塑悼,所有的module只要有一個地方寫了這個就行,因為app打包以后所有的AndroidManifest文件將會合并到一起
<provider
android:name="android.support.v4.content.FileProvider"
// 再說一遍哦:這里的"com.gudd.demo"是自定義的楷掉,需要改成你們自己的名字厢蒜,其實可以隨便寫啦。這里很重要,不能兩個app使用相同的名字郭怪,否則~~嘿嘿支示,兩個app是不能同時安裝的?佟鄙才!
android:authorities="com.gudd.demo.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths_screencapture" />
</provider>
上面還有個資源文件:resource="@xml/file_paths_screencapture"
// 上圖是寫這個文件要放的位置,隨便哪個Module都沒關(guān)系
// 只要AndroidManifest里面能直接調(diào)用到就可以促绵。但要記得寫在xml里面攒庵。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path
name="ext_sd_files"
path="" />
<files-path
name="int_files"
path="." />
<external-path
name="ext_files"
path="" />
<cache-path
name="cache_files"
path="" />
<external-files-path
name="ext_int_files"
path="" />
</paths>
// 可能上面這串代碼放到文件中會有些紅色的波浪線,呵呵败晴,但又有啥關(guān)系呢浓冒,能運(yùn)行起來不就行了,哈哈
這里再提供一下我保存圖片的一個方法:
public class ShareToolUtil {
private static String sharePicName = "share_pic.jpg";
private static String sharePicPath = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+"UmeBrowser"+File.separator+"sharepic"+File.separator;
/**
* 保存圖片尖坤,并返回一個File類型的文件
* 如今Android版本已經(jīng)高達(dá)28了稳懒,但在使用該方法時,涉及到權(quán)限問題慢味,本人在創(chuàng)建文件夾時遇到文件夾創(chuàng)建失敗問題场梆,遂將原因及解決方法記錄如下:
問題:Android6.0以后,文件夾創(chuàng)建失敗纯路。也就是使用file.mkdirs方法.
解決方法:1.讀寫sdcard需要權(quán)限或油,但僅在manifest.xml里面添加是不夠的,需要動態(tài)申請權(quán)限驰唬。2.可以將targetSdkVersion改為21或22或以下顶岸。
否則在分享過程中獲取不到圖片就會彈出“獲取資源失敗”這樣的提示。
*/
public static File saveSharePic(Context context, Bitmap bitmap){
if (FileUtil.isSDcardExist()){
File file = new File(sharePicPath);
if (!file.exists()){
file.mkdirs();
}
File filePic = new File(sharePicPath,sharePicName);
if (filePic.exists()){
filePic.delete();
}
try {
FileOutputStream out = new FileOutputStream(filePic);
if (bitmap == null) {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.share_homepage);
}
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return filePic;
}
return null;
}
}
這就是我的方法叫编,在分享微信朋友圈的時候需要注意一點(diǎn)辖佣,分享的圖片要保存在微信可獲取到的目錄下,一定不能保存在/data/data/****這個內(nèi)置目錄中搓逾,否則將獲取不到圖片報“獲取不到圖片資源卷谈,.....”導(dǎo)致分享失敗。
后面如果有時間我會再將新浪的分享給寫進(jìn)來恃逻。
今天是7月10日雏搂,距離這篇文章已經(jīng)有段時間了,為了說到做到寇损,我把新浪的也給分享出來凸郑,還是在回頭看這篇文章的時候想到,原來忘記我說的新浪這回事兒了矛市,哈哈芙沥。。。
新浪微博分享
新浪分享分為兩部分而昨,一部分指分享給好友救氯,一部分分享到內(nèi)容「韬看下面吧着憨。
/**
* description : 微博分享
* created at 2018/7/10 13:58
*/
public void shareToSinaFriends(Context context,boolean isFriends, String photoPath) {
if (PlatformUtil.isInstalledSpecifiedApp(context, PlatformUtil.PACKAGE_SINA)) {
File file = new File(photoPath);
if (!file.exists()) {
String tip = "文件不存在";
Toast.makeText(context, tip + " path = " + photoPath, Toast.LENGTH_LONG).show();
return;
}
Intent intent = new Intent(Intent.ACTION_SEND);
// 使用以下兩種type有一定的區(qū)別,"text/plain"分享給指定的粉絲或好友 务嫡;"image/*"分享到微博內(nèi)容
if (isFriends) {
intent.setType("text/plain");
}else {
intent.setType("image/*");// 分享文本|文本+圖片|圖片 到微博內(nèi)容時使用
}
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> matchs = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
ResolveInfo resolveInfo = null;
for (ResolveInfo each : matchs) {
String pkgName = each.activityInfo.applicationInfo.packageName;
if (PlatformUtil.PACKAGE_SINA.equals(pkgName)) {
resolveInfo = each;
break;
}
}
// type = "image/*"--->com.sina.weibo.composerinde.ComposerDispatchActivity
// type = "text/plain"--->com.sina.weibo.weiyou.share.WeiyouShareDispatcher
intent.setClassName(PlatformUtil.PACKAGE_SINA, resolveInfo.activityInfo.name);// 這里在使用resolveInfo的時候需要做判空處理防止crash
intent.putExtra(Intent.EXTRA_TEXT, "Test Text String !!");
if (file.isFile() && file.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(mContext, ShareToolUtil.AUTHORITY, file);
} else {
uri = Uri.fromFile(file);
}
intent.putExtra(Intent.EXTRA_STREAM, uri);
}
context.startActivity(intent);
}else{
Toast.makeText(mContext, "您需要安裝sina客戶端", Toast.LENGTH_LONG).show();
}
}
直接添加進(jìn)入QQ群
之前有小伙伴問我如何實現(xiàn)QQ群直接加入功能甲抖,這里我簡單給大家介紹一下,其實很簡單心铃,登錄騰訊https://qun.qq.com/join.html就明白了准谚。下面我貼下代碼:
/**
* 該群目前為我個人新建測試群,無聊的小盆友也可以加入進(jìn)來壯大我的號去扣,哈哈
* 發(fā)起添加群流程柱衔。群號:Android學(xué)習(xí)交流(610194891) 的 key 為: CXaQmSGNixYtgpaRuUlxd0CwyMhQYkd_
* 調(diào)用 joinQQGroup(CXaQmSGNixYtgpaRuUlxd0CwyMhQYkd_) 即可發(fā)起手Q客戶端申請加群 Android學(xué)習(xí)交流(610194891)
*
* @param key 由官網(wǎng)生成的key
* @return 返回true表示呼起手Q成功,返回fals表示呼起失敗
*/
public boolean joinQQGroup(String key) {
Intent intent = new Intent();
intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key));
// 此Flag可根據(jù)具體產(chǎn)品需要自定義愉棱,如設(shè)置唆铐,則在加群界面按返回,返回手Q主界面羽氮,不設(shè)置或链,按返回會返回到呼起產(chǎn)品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
startActivity(intent);
return true;
} catch (Exception e) {
// 未安裝手Q或安裝的版本不支持
return false;
}
}
以上僅是個人工作中遇到的一些問題,記錄下來方便以后查閱档押,如有優(yōu)化方法請留言澳盐。
QQ、WECHAT在打開情況下分享時只能喚醒應(yīng)用卻不能調(diào)用分享聯(lián)系人列表情況令宿。解決辦法如下:
調(diào)用開啟分享界面 mActivity.startActivity(intent);//如果微信或者QQ已經(jīng)喚醒或者打開叼耙,這樣只能喚醒微信,不能分享
請使用:mActivity.startActivity(Intent.createChooser(intent, "Share"));