本文对应的Git项目
本文主要介绍以下功能:
- 分享(纯文本|图片|文件)给QQ好友
- QZone(QQ空间)-分享到“QQ空间”应用-目前QQ不支持分享到QQ中自带空间
- 新浪微博分享-分两种(1)分享给好友;(2)分享到微博内容
- 直接分享(纯文本|图片|文件)给微信好友
- 直接分享图片到微信朋友圈
注意-更新于19年5月23日:
1.微信在6.6.7版本以后,已经不支持往朋友圈分享标题了,具体请点击查看
2.微信在6.7.3版本以后,已经不支持往朋友圈分享多图了,具体请点击查看 - android7.0以上系统获取url的方法
- 保存图片
- 直接添加进入QQ群
简单说明-也是我当时需要要做出来的效果:
1.QQ:分享到QQ好友时,直接以发文本的方式分享出去,字数不受限制
2.WechatMoment : 分享到微信朋友圈时,需要将图片带到发送朋友圈图文发送界面直接发送分享(新版微信不支持同时带文本)
3.直接分享图片给微信好友
说到分享许多人都会使用一些第三方sdk来实现,比如“友盟分享”,“Mob分享(ShareSdk)”。
这两种分享方式需要配置许多文件和代码,虽说省去了我们一个个集成各大网站分享的sdk,但常常也会自带许多坑,具体的大家在使用的时候就会发现,我就不评价了。
QQ分享:无论是友盟或sharesdk,都无法实现直接将长文本分享到QQ好友,原因是什么?我找过他们客服,这是tencent(腾讯)公司分享sdk规定的。具体可查看:链接中的 1.13 分享消息到QQ(无需QQ登录)的参数,以QQapi上的代码进行分享以后除了文本字数有限制以外,而且其分享的样式是以链接的形式分享出去的,所以不符合我的要求。
WechatMoment微信朋友圈分享:以官方文档或以第三方通道分享时,在分享到朋友圈的时候,分享文本是设置不到文本区域的,无论你用啥方法。因为ShareSdk官方文档也说了:查看第4点(微信(好友、朋友圈、收藏))当你需要同时设置分享图片和文本时你设置的text是不显示的。
我的解决方案:(使用Intent分享)但有个缺点是,分享到平台后却不能返回到原应用,只能留在QQ或微信(除在微信分享文件-分享文件给好友可以返回到原应用)
先给大家提供个判断QQ向微信客户端是否存在的两个方法:
调用方式如: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 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好友或群组):
/**
* 直接分享纯文本内容至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/*");
// 遍历所有支持发送图片的应用。找到需要的应用
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("分享图片到**失败");
}
}
}
之前有同学说在分享QQ和微信的时候,发现只要QQ或微信在打开的情况下,再调用分享只是打开了QQ和微信,却没有调用选择分享联系人的情况,这里,我要感觉一下@[努力搬砖]同学,他找出了原因。
解决办法如下:
mActivity.startActivity(intent);//如果微信或者QQ已经唤醒或者打开,这样只能唤醒微信,不能分享
请使用 mActivity.startActivity(Intent.createChooser(intent, "Share"));
QZone(QQ空间)
经过我反复试验,通过adb(方法:adb shell “dumpsys window | grep mCurrentFocus”)查找QQ中的空间发布说说界面是:cooperation.qzone.QzonePublishMoodProxyActivity,但始终歪能成功,在网上看到有人说是该界面没有对外开放,所以这里只能通过调用qq空间app打开发布界面进行分享内容!(强调:不是QQ内自带发布界面,是QQ空间单独的APP)。后期再研究下能否直接使用QQ内直接的界面。
/**
* 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)可查看文章开头更新内容,这里说一下解决方法:在不能分享标题到朋友圈的时候,可以在点击分享按钮时,将需要分享的内容复制到剪贴板,并toast给用户到微信朋友圈发布界面粘帖。
/**
* 直接分享文本和图片到微信朋友圈
* @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 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);
}
}
// 微信现不能进行标题同时分享
// 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版本)当前APP是不能直接向外部应用提供file开头的的文件路径,需要通过FileProvider转换一下。否则在7.0及以上版本手机将直接crash。
这里再提供下我这里具体的逻辑:
常量:ShareToolUtil.AUTHORITY --写在哪儿无所谓,只要能调用到
public static final String AUTHORITY = "com.gudd.demo.fileprovider";
// AndroidManifest需要加一个provider的标签,里面的authorities就是我们上面需要调用的一个常量
// 如果你有多个module的话也没关系,所有的module只要有一个地方写了这个就行,因为app打包以后所有的AndroidManifest文件将会合并到一起
上面还有个资源文件:resource="@xml/file_paths_screencapture"
// 上图是写这个文件要放的位置,随便哪个Module都没关系
// 只要AndroidManifest里面能直接调用到就可以。但要记得写在xml里面。
// 可能上面这串代码放到文件中会有些红色的波浪线,呵呵,但又有啥关系呢,能运行起来不就行了,哈哈
这里再提供一下我保存图片的一个方法:
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版本已经高达28了,但在使用该方法时,涉及到权限问题,本人在创建文件夹时遇到文件夹创建失败问题,遂将原因及解决方法记录如下:
问题:Android6.0以后,文件夹创建失败。也就是使用file.mkdirs方法.
解决方法:1.读写sdcard需要权限,但仅在manifest.xml里面添加是不够的,需要动态申请权限。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;
}
}
这就是我的方法,在分享微信朋友圈的时候需要注意一点,分享的图片要保存在微信可获取到的目录下,一定不能保存在/data/data/****这个内置目录中,否则将获取不到图片报“获取不到图片资源,.....”导致分享失败。
后面如果有时间我会再将新浪的分享给写进来。
今天是7月10日,距离这篇文章已经有段时间了,为了说到做到,我把新浪的也给分享出来,还是在回头看这篇文章的时候想到,原来忘记我说的新浪这回事儿了,哈哈。。。
新浪微博分享
新浪分享分为两部分,一部分指分享给好友,一部分分享到内容。看下面吧。
/**
* 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有一定的区别,"text/plain"分享给指定的粉丝或好友 ;"image/*"分享到微博内容
if (isFriends) {
intent.setType("text/plain");
}else {
intent.setType("image/*");// 分享文本|文本+图片|图片 到微博内容时使用
}
PackageManager packageManager = context.getPackageManager();
List 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();
}
}
直接添加进入QQ群
之前有小伙伴问我如何实现QQ群直接加入功能,这里我简单给大家介绍一下,其实很简单,登录腾讯https://qun.qq.com/join.html就明白了。下面我贴下代码:
/**
* 该群目前为我个人新建测试群,无聊的小盆友也可以加入进来壮大我的号,哈哈
* 发起添加群流程。群号:Android学习交流(610194891) 的 key 为: CXaQmSGNixYtgpaRuUlxd0CwyMhQYkd_
* 调用 joinQQGroup(CXaQmSGNixYtgpaRuUlxd0CwyMhQYkd_) 即可发起手Q客户端申请加群 Android学习交流(610194891)
*
* @param key 由官网生成的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可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
startActivity(intent);
return true;
} catch (Exception e) {
// 未安装手Q或安装的版本不支持
return false;
}
}
以上仅是个人工作中遇到的一些问题,记录下来方便以后查阅,如有优化方法请留言。
QQ、WECHAT在打开情况下分享时只能唤醒应用却不能调用分享联系人列表情况。解决办法如下:
调用开启分享界面 mActivity.startActivity(intent);//如果微信或者QQ已经唤醒或者打开,这样只能唤醒微信,不能分享
请使用:mActivity.startActivity(Intent.createChooser(intent, "Share"));