Android分享集成系列之微信分享

项目中单独集成微信分享,集成起来还算顺利,但是还是有一些坑需要注意。下面我来说说这个具体的过程:

集成流程

1.申请你的AppID
2.下载SDK及API文档
3.搭建开发环境
4.在代码中使用开发工具包
总之,具体参考微信开放平台的接入流程,严格按照流程进行集成。点击查看集成地址

代码实现

在具体讲解代码实现前,保证你已经做到以下几点,测试才能通过:

  • 应用已经通过审核
  • 创建的应用包名与项目包名一致

开始实现

(1)添加依赖:
dependencies {
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
}

dependencies {
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
}

(其中,前者包含统计功能)

(2)清单文件权限申明:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
(3)将应用注册到微信:

要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的APP_ID。(可以在程序入口Activity的onCreate回调函数处,或其他合适的地方将你的应用id注册到微信)

public void regToWeiXin() {
        wxapi = WXAPIFactory.createWXAPI(WRKApplication.getContext(), appID, true);
        wxapi.registerApp(appID);
    }
(4)分享到微信:
  1. 判断当前设备是否安装微信:
/**
     * 判断是否安装微信
     */
    public boolean isWeiXinAppInstall() {
        if (wxapi == null)
            wxapi = WXAPIFactory.createWXAPI(WRKApplication.getContext(), appID);
        if (wxapi.isWXAppInstalled()) {
            return true;
        } else {
            Toast.makeText(WRKApplication.getContext(), R.string.no_install_wx, Toast.LENGTH_SHORT).show();
            return false;
        }
    }
  1. 如果已安装,判断当前版本号对分享的支持情况:
不同微信版本对开放平台接口的支持(New)

发送信息:4.0及以上版本微信iPhone、Android客户端;
接收/查看信息:4.0及以上版本微信iPhone、Android、Sybiam客户端;
发送到朋友圈:4.2及以上版本微信iPhone、Android客户端;
收藏到我的收藏:5.0及以上版本微信iPhone、Android客户端。

判断版本:(这个方法只判断是否支持分享到朋友圈,其他判断类似)

/**
     * 是否支持分享到朋友圈
     */
    public boolean isWXAppSupportAPI() {
        if (isWeiXinAppInstall()) {
            int wxSdkVersion = wxapi.getWXAppSupportAPI();
            if (wxSdkVersion >= TIMELINE_SUPPORTED_VERSION) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
  1. 分享数据:(支持文本、图片、表情、音频、视频、url链接、小程序)
  • 分享文本:
/**
     * 分享文本类型
     *
     * @param text 文本内容
     * @param type 微信会话或者朋友圈等
     */
    public void shareTextToWx(String text, int type) {
        if (text == null || text.length() == 0) {
            return;
        }

        WXTextObject textObj = new WXTextObject();
        textObj.text = text;

        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = textObj;
        msg.description = text;

        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("text");
        req.message = msg;
        req.scene = type;

        getWxApi().sendReq(req);
    }
  • 分享图片(代码中开启一个线程用来加载网络图片,显示缩略图)
/**
     * 分享图片到微信
     */

    public void shareImageToWx(final String imgUrl, String title, String desc, final int wxSceneSession) {
        Bitmap bmp = BitmapFactory.decodeResource(WRKApplication.getContext().getResources(), R.mipmap.ic_launcher);
        WXImageObject imgObj = new WXImageObject(bmp);

        final WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = imgObj;
        msg.title = title;
        msg.description = desc;
        final Bitmap[] thumbBmp = {Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true)};
        bmp.recycle();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream imageStream = getImageStream(imgUrl);
                    Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
                    msg.mediaObject = new WXImageObject(bitmap);
                    thumbBmp[0] = Bitmap.createScaledBitmap(bitmap, THUMB_SIZE, THUMB_SIZE, true);
                    bitmap.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                msg.thumbData = WRKFileUtil.bmpToByteArray(thumbBmp[0], true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("img");
                req.message = msg;
                req.scene = wxSceneSession;
                getWxApi().sendReq(req);
            }
        }).start();
    }
  • 分享音频:
/**
     * 分享音乐
     *
     * @param musicUrl       音乐资源地址
     * @param title          标题
     * @param desc           描述
     * @param wxSceneSession
     */
    public void shareMusicToWx(final String musicUrl, final String title, final String desc, final String iconUrl, final int wxSceneSession) {
        WXMusicObject music = new WXMusicObject();
        music.musicUrl = musicUrl;

        final WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = music;
        msg.title = title;
        msg.description = desc;

        Bitmap bmp = BitmapFactory.decodeResource(WRKApplication.getContext().getResources(), R.mipmap.ic_launcher);
        final Bitmap[] thumbBmp = {Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true)};
        bmp.recycle();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream imageStream = getImageStream(iconUrl);
                    Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
                    thumbBmp[0] = Bitmap.createScaledBitmap(bitmap, THUMB_SIZE, THUMB_SIZE, true);
                    bitmap.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                msg.thumbData = WRKFileUtil.bmpToByteArray(thumbBmp[0], true);
                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("music");
                req.message = msg;
                req.scene = wxSceneSession;
                getWxApi().sendReq(req);
            }
        }).start();
    }
  • 分享视频:
/**
     * 分享视频
     *
     * @param videoUrl       视频地址
     * @param title          标题
     * @param desc           描述
     * @param wxSceneSession
     */

    public void shareVideoToWx(String videoUrl, String title, String desc, final String iconUrl, final int wxSceneSession) {
        WXVideoObject video = new WXVideoObject();
        video.videoUrl = videoUrl;

        final WXMediaMessage msg = new WXMediaMessage(video);
        msg.title = title;
        msg.description = desc;
        Bitmap bmp = BitmapFactory.decodeResource(WRKApplication.getContext().getResources(), R.mipmap.ic_launcher);
        final Bitmap[] thumbBmp = {Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true)};
        bmp.recycle();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream imageStream = getImageStream(iconUrl);
                    Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
                    thumbBmp[0] = Bitmap.createScaledBitmap(bitmap, THUMB_SIZE, THUMB_SIZE, true);
                    bitmap.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                msg.thumbData = WRKFileUtil.bmpToByteArray(thumbBmp[0], true);

                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("video");
                req.message = msg;
                req.scene = wxSceneSession;
                getWxApi().sendReq(req);
            }
        }).start();
    }
  • 分享链接:
/**
     * 分享url地址
     *
     * @param url            地址
     * @param title          标题
     * @param desc           描述
     * @param wxSceneSession 类型
     */
    public void shareUrlToWx(String url, String title, String desc, final String iconUrl, final int wxSceneSession) {

        WXWebpageObject webpage = new WXWebpageObject();
        webpage.webpageUrl = url;
        final WXMediaMessage msg = new WXMediaMessage(webpage);
        msg.title = title;

        msg.description = desc;
        Bitmap bmp = BitmapFactory.decodeResource(WRKApplication.getContext().getResources(), R.mipmap.ic_launcher);
        final Bitmap[] thumbBmp = {Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true)};
        bmp.recycle();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream imageStream = getImageStream(iconUrl);
                    Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
                    thumbBmp[0] = Bitmap.createScaledBitmap(bitmap, THUMB_SIZE, THUMB_SIZE, true);
                    bitmap.recycle();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                msg.thumbData = WRKFileUtil.bmpToByteArray(thumbBmp[0], true);
                SendMessageToWX.Req req = new SendMessageToWX.Req();
                req.transaction = buildTransaction("webpage");
                req.message = msg;
                req.scene = wxSceneSession;
                getWxApi().sendReq(req);
            }
        }).start();
    }

这几种分享已经满足项目需求,所以没有做小程序分享。如果有需要直接参看开发平台Demo即可。

(5)分享后接受微信的回调:WXEntryActivity类实现
  • 在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity(必须确保申请时的包名下,否则接收不到信息)
  • 在manifest文件里面加上exported属性,设置为true
<activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:theme="@style/AppTheme.Fullscreen.Translucent" />

回调接受处理:

public class WRKWxEntryActivity extends Activity implements IWXAPIEventHandler {
    private IWXAPI api;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 通过WXAPIFactory工厂,获取IWXAPI的实例
        api = WRKShareUtil.getInstance().getWxApi();
        //注意:
        //第三方开发者如果使用透明界面来实现WXEntryActivity,需要判断handleIntent的返回值,如果返回值为false,则说明入参不合法未被SDK处理,应finish当前透明界面,避免外部通过传递非法参数的Intent导致停留在透明界面,引起用户的疑惑
        try {
            api.handleIntent(getIntent(), this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        setIntent(intent);
        api.handleIntent(intent, this);
    }

    @Override
    public void onReq(BaseReq baseReq) {
//        System.out.println(baseReq);
    }

    @Override
    public void onResp(BaseResp baseResp) {
        int result;
        switch (baseResp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                result = R.string.errcode_success;
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                result = R.string.errcode_cancel;
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                result = R.string.errcode_deny;
                break;
            case BaseResp.ErrCode.ERR_UNSUPPORT:
                result = R.string.errcode_unsupported;
                break;
            default:
                result = R.string.errcode_unknown;
                break;
        }
        Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
        finish();
    }
}

到这基本上就实现分享功能了,如果这样,那你就厉害了。这里我再说一下在集成时遇到的问题:

集成问题与解决:

  1. 点击分享后,出现 “ 不合法的参数,无法分享到微信。返回到没有审核的应用 ” ,出现这个问题是因为我把APP_ID写错了。APP_ID一般为一个以wx开头的18个字符的字符串。
  2. 分享了多条数据,发现有几条数据点击分享,不能把微信调起来。这个时候你就需要查看你分享的数据是否符合微信规定的限制条件。要对应限制条件,进行处理。来看一下源码:(检查发送时的缩略图大小是否超过32k)
final boolean checkArgs() {
        if(this.getType() == 8 && (this.thumbData == null || this.thumbData.length == 0)) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, thumbData should not be null when send emoji");
            return false;
        } else if(this.thumbData != null && this.thumbData.length > '耀') {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, thumbData is invalid");
            return false;
        } else if(this.title != null && this.title.length() > 512) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, title is invalid");
            return false;
        } else if(this.description != null && this.description.length() > 1024) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, description is invalid");
            return false;
        } else if(this.mediaObject == null) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, mediaObject is null");
            return false;
        } else if(this.mediaTagName != null && this.mediaTagName.length() > 64) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, mediaTagName is too long");
            return false;
        } else if(this.messageAction != null && this.messageAction.length() > 2048) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, messageAction is too long");
            return false;
        } else if(this.messageExt != null && this.messageExt.length() > 2048) {
            Log.e("MicroMsg.SDK.WXMediaMessage", "checkArgs fail, messageExt is too long");
            return false;
        } else {
            return this.mediaObject.checkArgs();
        }
    }

看看你没有分享成功的原因有没有这些,要是仔细看日志的伙伴应该也能发现这个问题。所以我在代码中做出了处理:

 String title = mShareData.getTitle();
 if (title != null && title.length() > 512)
        title = title.substring(0, 511);
 String desc = mShareData.getDesc();
 if (desc != null && desc.length() > 1024)
       desc = desc.substring(0, 1023);

总结:

最终集成成功了,遇到的问题也基本解决了。微信的集成与其他的集成大致看一下,套路都是一样的。想一想要是集成其他的,遇到的这些坑,其他分享应该也会有。比如说限制条件。

由于项目有多个端(APP_ID有多个),都需要分享功能。所以把分享功能放到了公共库,但是这样公共库不能访问到各个端的APP_ID,所以我将APP_ID放到各个端的清单文件中,以mete_data的形式在运行时动态获取。如果不懂这一流程,可以看我的一篇文章:运行时动态获取清单数据

微信分享工具类,下载地址

希望这个分享能对你有帮助,收尾!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,563评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,609评论 4 59
  • 在mybatis 3.4.0版本中新增了一个功能,查询可以返回Cusror<T>类型的数据,类似于JDBC里的Re...
    Draft灬h阅读 32,883评论 1 4
  • 去年四月经不住同事的“忽悠”,学校的流浪小奶猫太过可怜,故而收留。也开始了自己成家后的第一次在城市养猫。从不足一个...
    艾冰台阅读 461评论 3 1
  • by橘生淮北 乌蒙小镇的天永远是灰蒙蒙的,时时刻刻都酝酿着大暴雨。奇怪的是下雨的时候从来只...
    年更摇阅读 365评论 0 1