android适配收录的大神文章

Android系统分享使用Intent分享文本到QQ和文本+图片

2018-02-09  本文已影响7885人  NewNiu

本文主要介绍以下功能:(后续可能会继续添加)

1.直接分享纯文本内容至QQ好友
2.分享图片给QQ好友
3.QZone(QQ空间)-分享到“QQ空间”应用-目前QQ不支持分享到QQ中自带空间
4.新浪微博分享-分两种(1)分享给好友;(2)分享到微博内容
5.直接分享图片到微信好友
6.直接分享文本和图片到微信朋友圈
7.android7.0以上系统获取url的方法
8.保存图片

简单说明-也是我当时需要要做出来的效果:

1.QQ:分享到QQ好友时,直接以发文本的方式分享出去,字数不受限制
2.WechatMoment : 分享到微信朋友圈时,需要将图片和文本带到发送朋友圈图文发送界面直接发送分享
3.直接分享图片给微信好友

说到分享许多人都会使用一些第三方sdk来实现,比如“友盟分享”,“Mob分享(ShareSdk)”。

这两种分享方式需要配置许多文件和代码,虽说省去了我们一个个集成各大网站分享的sdk,但常常也会自带许多坑,具体的大家在使用的时候就会发现,我就不评价了。

介绍

今天正好把公司任务做完了,也正好是公司项目中用到了些平常分享组件无法完成的效果,目前我只做到了两种效果:1.分享长文本到QQ;2.分享图文到wechat朋友圈

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<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好友或群组):

   /**
     * 直接分享纯文本内容至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内直接的界面。

public static void shareImageToQQZone(Context mContext, String photoPath) {
        if (Platformutil.isInstallApp(mContext,PlatformUtil.PACKAGE_QZONE)) {
//            photoPath = Environment.getExternalStorageDirectory() + "/UmeWeb/Bitmap/1.png";
            File file = new File(photoPath);
            if (!file.exists()) {
                String tip = "文件不存在";
                Toast.makeText(mContext, tip + " path = " + photoPath, Toast.LENGTH_LONG).show();
                return;
            }
            Intent intent = new Intent();
//            ComponentName componentName = new ComponentName("com.tencent.mobileqq","cooperation.qzone.QzonePublishMoodProxyActivity");// 无用代码
            ComponentName componentName = new ComponentName("com.qzone","com.qzonex.module.operation.ui.QZonePublishMoodActivity");
            intent.setComponent(componentName);
            intent.setAction("android.intent.action.SEND");
            intent.setType("image/*");
            intent.putExtra(Intent.EXTRA_TEXT, "I'm so tired!!");//  分享文本
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));// 分享图片
            mContext.startActivity(intent);
        }
    }

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.isWeChatAvailable(context)) {
            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(微信朋友圈)分享:

   /**
     * 直接分享文本和图片到微信朋友圈
     * @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);
                }
            }
            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.ume.browser.fileprovider";
// AndroidManifest需要加一个provider的标签,里面的authorities就是我们上面需要调用的一个常量
// 如果你有多个module的话也没关系,所有的module只要有一个地方写了这个就行,因为app打包以后所有的AndroidManifest文件将会合并到一起
<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.ume.browser.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"


file_paths_screencapture.xml 该文件需要在AndroidManifest.xml中引用
//  上图是写这个文件要放的位置,随便哪个Module都没关系 
//  只要AndroidManifest里面能直接调用到就可以。但要记得写在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>
// 可能上面这串代码放到文件中会有些红色的波浪线,呵呵,但又有啥关系呢,能运行起来不就行了,哈哈
这里再提供一下我保存图片的一个方法:
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类型的文件
     */
    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日,距离这篇文章已经有段时间了,为了说到做到,我把新浪的也给分享出来,还是在回头看这篇文章的时候想到,原来忘记我说的新浪这回事儿了,哈哈。。。

新浪微博分享

新浪分享分为两部分,一部分指分享给好友,一部分分享到内容。看下面吧。

public static void shareToSinaFriends(Context context, String photoPath) {
        if (! isInstallApp(context, PlatformUtil.PACKAGE_SINA)) {
            Toast.makeText(context, "新浪微博没有安装!", Toast.LENGTH_SHORT).show();
            return;
        }
        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/*"分享到微博内容,下面这两个设置type的代码必须写在查询语句前面,否则找不到带有分享功能的应用。
//        intent.setType("text/plain");
        intent.setType("image/*");// 分享文本|文本+图片|图片 到微博内容时使用
        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 ("com.sina.weibo".equals(pkgName)) {
                resolveInfo = each;
                break;
            }
        }
        intent.setClassName(PACKAGE_SINA, resolveInfo.activityInfo.name);// 这里在使用resolveInfo的时候需要做判空处理防止crash
        intent.putExtra(Intent.EXTRA_TEXT, "Test Text String !!");
        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
        context.startActivity(intent);
    }

以上仅是个人工作中遇到的一些问题,记录下来方便以后查阅,如有优化方法请留言。不喜勿喷。

感谢

@努力搬砖

提供QQ、WECHAT在打开情况下分享时只能唤醒应用却不能调用分享联系人列表情况。解决办法如下:

调用开启分享界面 mActivity.startActivity(intent);//如果微信或者QQ已经唤醒或者打开,这样只能唤醒微信,不能分享 
请使用:mActivity.startActivity(Intent.createChooser(intent, "Share"));
上一篇下一篇

猜你喜欢

热点阅读