草庐IT

Android开发 对接微信分享SDK总结

Stars-one 2023-03-28 原文

原文:Android开发 对接微信分享SDK总结 - Stars-One的杂货小窝

公司项目需要对接微信分享,本来之前准备对接友盟分享的,但友盟的分享实际参数太多,而我又只需要对接一个微信分享,于是便是选择总结对接官方的

顺便把微信SDK的APPID申请的流程也一起记录了

步骤

1.注册获得APPID

前往微信公众平台,使用企业认证的开发者账号进行登录,提交应用包名和签名指纹文件,可以生成一个appId,有了此appId账号才能有侯勋的操作

通过输入命令可查看签名文件的md5等信息:

keytool -list -v -keystore qj_test.keystore

注意:上述输完命令后需要输入密码,密码不会显示出来,密码正确则会出现下面的相关md5等信息了

微信平台比较坑的就是,它要求输入不要带:号,且还要小写的md5数值,我们稍微处理一下:我比较懒,就写了几行代码处理了,代码如下:

//改为你的md5即可
String md5 = "73:95:50:FB:F9:A9:A6:A3:F2:74:E0:25:64:EB:E7:48";
String result = md5.replaceAll(":", "").toLowerCase();
System.out.println(result);

输出结果复制一下,就得到了符合规范的md5了

2.添加依赖

implementation 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.0'

官方文档提供的写法是不固定版本号的,我这里觉得还是固定版本号比较好,需要依赖中央仓库即可

3.初始化启动分享

// APP_ID 替换为你的应用从官方网站申请到的合法appID
private static final String APP_ID = "wx88888888";

// IWXAPI 是第三方 app 和微信通信的 openApi 接口
private IWXAPI api;

private void regToWx(Context context) {
    // 通过 WXAPIFactory 工厂,获取 IWXAPI 的实例
    api = WXAPIFactory.createWXAPI(context, APP_ID, true);

    // 将应用的 appId 注册到微信
    api.registerApp(APP_ID);

    //建议动态监听微信启动广播进行注册到微信
    context.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            // 将该 app 注册到微信
            api.registerApp(APP_ID);
        }
    }, new IntentFilter(ConstantsAPI.ACTION_REFRESH_WXAPP));

}

之后在分享的Activity或Application中进行初始化,调用regToWx(),如

regToWx(MainActivity.this)

PS: 这里可以看下下面提到的工具类封装

4.使用微信分享

经过上面的步骤,我们已经能够使用微信分享了,使用IWXAPI那个对象即可,具体可以查看文档WXMediaMessage (微信媒体消息内容)说明 | 微信开放文档

api.sendReq(req);

不过需要注意一下Android11的适配,需要在AndroidManifest.xml声明

<queries>
    <!-- 指定微信包名-->
    <package android:name="com.tencent.mm" />
</queries>

这里我是封装了一个工具类,源码在下一章节,主要封装了分享文本,图片,视频和网页链接,至于分享小程序和分享音乐文件没有需求,就暂时没有对接,各位可以参考的完善即可

这里顺便补充一下,由于我自己个人没法成功申请到微信应用平台的APPID,于是我就是使用了另外项目的的APPID来进行测试

测试的发现,只要你使用同个签名文件,同时,把build.gradle里面的applicationId改成填写的包名,微信分享就是能够正常的使用

举个例子,我们有一个应用包名为com.starsone.test的应用已经申请到了APPID

这个时候,我们另外个项目,包名与其不同,但我们想要测试一下分享功能,可以进行以下的操作:

修改app模块里的build.gradle,将applicationId改为com.starsone.test包名,并使用相同的签名文件打包即可使用同个APPID测试分享功能了,如下图所示:

这里如果使用分享视频或分享网页链接,在微信中会以消息卡片的形式展示,如下图所示:

5.添加回调

如果项目中需要对分享成功或失败进行监听,来进行进一步的逻辑处理,可以按照微信官方的文档添加一个WxEntryActivity实现

由于我开发的项目暂时无需,所以没怎么研究,这里稍微简单的补充一下:

我们需要创建一个WXEntryActivity作为回调的接收,WXEntryActivity没有页面,主要实现微信的回调接口IWXAPIEventHandler即可,代码如下:


public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

    @Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {

    }
}
<activity
    android:name=".wxapi.WXEntryActivity"
    android:exported="true"
    android:launchMode="singleTask"
    android:taskAffinity="com.tyky.share"
    android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

这里,注意,Activity是要处于你当前包名下的wxapi文件夹,如我自己的例子,当前包名是com.tyky.share,也是我在新建一层wxapi包名,并将Activity放在里面,如下图所示

这里由于我没有用到,所以就没有在方法里补充对应的逻辑了

逻辑解释如下:

通过api.sendReq(req)分享内容,发送的请求会将回调一次 onReq() 方法,之后微信分享完成(成功或取消)之后,会将响应结果将回调到 onResp() 方法

工具类封装

工具类用到了以下两个依赖,记得先导入

implementation 'org.apache.commons:commons-lang3:3.9'
// Android的工具类   https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/README-CN.md
implementation 'com.blankj:utilcodex:1.30.6'

PS:微信SDK依赖也不要忘记哦!

点击查看工具类源码
package com.tyky.share.utils;

import android.graphics.Bitmap;

import com.blankj.utilcode.util.EncodeUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.MetaDataUtils;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
import com.tencent.mm.opensdk.modelmsg.WXImageObject;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.modelmsg.WXTextObject;
import com.tencent.mm.opensdk.modelmsg.WXVideoObject;
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
import com.tencent.mm.opensdk.openapi.IWXAPI;

import org.apache.commons.lang3.StringUtils;

import java.io.File;

import static com.tencent.mm.opensdk.modelmsg.SendMessageToWX.Req.WXSceneSession;
import static com.tencent.mm.opensdk.modelmsg.SendMessageToWX.Req.WXSceneTimeline;

/**
 * 参考文档 [WXMediaMessage (微信媒体消息内容)说明 | 微信开放文档](https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Share_and_Favorites/Android.html)
 * 微信分享工具类(没有对接小程序和音乐)
 *
 * @author stars-one
 */
public class WxUtils {

    //从meta里读取微信平台的appId
    public static String appId = MetaDataUtils.getMetaDataInApp("wechat_app_id");

    // IWXAPI 是第三方 app 和微信通信的 openApi 接口 初始化在ShareInitializer类中
    public static IWXAPI api;

    /**
     * 分享文本
     *
     * @param text        文本内容(长度需大于 0 且不超过 10KB)
     * @param flag        0:好友 1:朋友圈
     * @param title       分享标题(限制长度不超过 512Bytes)
     * @param description 分享描述(限制长度不超过 1KB)
     */
    public static void shareText(String text, int flag, String title, String description) {
        //初始化一个 WXTextObject 对象,填写分享的文本内容
        WXTextObject textObj = new WXTextObject();
        textObj.text = text;

        //用 WXTextObject 对象初始化一个 WXMediaMessage 对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = textObj;
        msg.title = title;
        msg.description = description;
        sendMessage(msg, flag);
    }

    /**
     * 分享图片
     *
     * @param imgBase64   图片base64数据
     * @param flag        0:好友 1:朋友圈
     * @param title       分享标题(限制长度不超过 512Bytes)
     * @param description 分享描述(限制长度不超过 1KB)
     */
    public static void sharePicture(String imgBase64, int flag, String title, String description) {
        //base64数据处理
        String data = imgBase64;
        if (data.contains("base64,")) {
            data = org.apache.commons.lang3.StringUtils.substringAfter(data, "base64,");
        }
        byte[] bytes = EncodeUtils.base64Decode(data);
        Bitmap bitmap = ImageUtils.bytes2Bitmap(bytes);

        //使用file存放,突破微信分享的限制
        File file = ImageUtils.save2Album(bitmap, Bitmap.CompressFormat.PNG);
        sharePictureByImgFilePath(file.getPath(), flag, title, description);
    }

    /**
     * 分享图片
     *
     * @param imgFilePath 图片本地路径
     * @param flag        0:好友 1:朋友圈
     * @param title       分享标题(限制长度不超过 512Bytes)
     * @param description 分享描述(限制长度不超过 1KB)
     */
    public static void sharePictureByImgFilePath(String imgFilePath, int flag, String title, String description) {
        //初始化一个 WXImageObject 对象,填写分享图片
        WXImageObject wxImageObject = new WXImageObject();
        wxImageObject.imagePath = imgFilePath;

        //用 WXTextObject 对象初始化一个 WXMediaMessage 对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = wxImageObject;
        msg.title = title;
        msg.description = description;
        sendMessage(msg, flag);
    }

    /**
     * 分享视频(分享给好友会以消息卡片展示)
     *
     * @param videoUrl    视频链接(文本长度不能超过10KB)
     * @param flag        0:好友 1:朋友圈
     * @param title       分享标题(限制长度不超过 512Bytes)
     * @param description 分享描述(限制长度不超过 1KB)
     * @param thumbData   缩略图base64(不能超过32KB)
     */
    public static void shareVideo(String videoUrl, int flag, String title, String description, String thumbData) {
        //初始化一个 WXImageObject 对象,填写分享图片
        WXVideoObject wxImageObject = new WXVideoObject();
        wxImageObject.videoUrl = videoUrl;

        //用 WXTextObject 对象初始化一个 WXMediaMessage 对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = wxImageObject;
        msg.title = title;
        msg.description = description;
        if (StringUtils.isNotBlank(thumbData)) {
            String data = thumbData;
            if (data.contains("base64,")) {
                data = org.apache.commons.lang3.StringUtils.substringAfter(data, "base64,");
            }
            byte[] bytes = EncodeUtils.base64Decode(data);
            Bitmap bitmap = ImageUtils.bytes2Bitmap(bytes);
            msg.setThumbImage(bitmap);
        }
        sendMessage(msg, flag);
    }

    /**
     * 分享网页(分享给好友会以消息卡片展示)
     *
     * @param webUrl      网页链接(文本长度不能超过10KB)
     * @param flag        0:好友 1:朋友圈
     * @param title       分享标题(限制长度不超过 512Bytes)
     * @param description 分享描述(限制长度不超过 1KB)
     * @param thumbData   缩略图base64(不能超过32KB)
     */
    public static void shareWeb(String webUrl, int flag, String title, String description, String thumbData) {
        //初始化一个 WXImageObject 对象,填写分享图片
        WXWebpageObject wxImageObject = new WXWebpageObject();
        wxImageObject.webpageUrl = webUrl;

        //用 WXTextObject 对象初始化一个 WXMediaMessage 对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = wxImageObject;
        msg.title = title;
        msg.description = description;

        if (StringUtils.isNotBlank(thumbData)) {
            String data = thumbData;
            if (data.contains("base64,")) {
                data = org.apache.commons.lang3.StringUtils.substringAfter(data, "base64,");
            }
            byte[] bytes = EncodeUtils.base64Decode(data);
            Bitmap bitmap = ImageUtils.bytes2Bitmap(bytes);
            msg.setThumbImage(bitmap);
        }
        sendMessage(msg, flag);
    }


    /**
     * @param msg  分享内容实体数据
     * @param flag 0:好友 1:朋友圈
     */
    private static void sendMessage(WXMediaMessage msg, int flag) {
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = String.valueOf(System.currentTimeMillis());  //transaction字段用与唯一标示一个请求
        req.message = msg;

        //朋友圈:WXSceneTimeline
        //会话:WXSceneSession
        if (flag == 1) {
            req.scene = WXSceneTimeline;
        } else {
            req.scene = WXSceneSession;
        }

        //调用 api 接口,发送数据到微信
        api.sendReq(req);
    }
}

工具类使用的时候,记得在注册的时候一起进行初始化,把上述第三步的初始化方法代码改为如下面:

private void regToWx(Context context) {
    String APP_ID = WxUtils.appId;

    // 通过 WXAPIFactory 工厂,获取 IWXAPI 的实例
    WxUtils.api = WXAPIFactory.createWXAPI(context, APP_ID, true);

    // 将应用的 appId 注册到微信
    WxUtils.api.registerApp(APP_ID);

    //建议动态监听微信启动广播进行注册到微信
    context.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            // 将该 app 注册到微信
            WxUtils.api.registerApp(APP_ID);
        }
    }, new IntentFilter(ConstantsAPI.ACTION_REFRESH_WXAPP));
}

之后在Application或Activity进行初始化,其他步骤不变

踩坑总结

1、配置签名的坑

解决:一定要MD5、小写、不要带冒号,最好用官方给的签名获取工具。

2、没有注册API

解决:API是运行重复注册的,并且也不是耗时任务,所以不妨放在Activity的onCreate下面,记得写这个。

3、分享的图标

解决:分享的图标大小不能超过32K,要是jpg格式。

3、分享图标自己能看到,好友看不到

解决:修改分享的标题和内容,不要触及微信的敏感词检测系统,多试几下。

4、没有回调

解决:一定要注意WXEntryActivity的包名路径是否正确,已经配置export=true

5、确定了问题4后还是调不起来

你确定有在WXEntryActivity的onCreate里面注册API并且调用 api.handleIntent(getIntent(), this);? 估计你没有吧?

6、回调到其他页面

解决:没办法直接回调到其他页面,但可以通过广播、EventBus等通知的实现来通知其他页面刷新,同时结束WXEntryActivity的页面。

参考

有关Android开发 对接微信分享SDK总结的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  3. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  4. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  6. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  10. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

随机推荐