Android開發 對接微信分享SDK總結

原文: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的工具類   //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 java.io.File;

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

/**
 * 參考文檔 [WXMediaMessage (微信媒體消息內容)說明 | 微信開放文檔](//developers.weixin.qq.com/doc/oplatform/Mobile_App/Share_and_Favorites/Android.html)
 * 微信分享工具類(沒有對接小程序和音樂)
 *
 * @author starsone
 */
public class WxUtils {

    //從meta里讀取微信平台的appId
    public static String appId = "";

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

    /**
     * 分享文本
     *
     * @param text        文本內容(長度需大於 0 且不超過 10KB)
     * @param flag        0:好友 1:朋友圈
     * @param title       分享標題
     * @param description 分享描述
     */
    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       分享標題
     * @param description 分享描述
     */
    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       分享標題
     * @param description 分享描述
     */
    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    視頻鏈接
     * @param flag        0:好友 1:朋友圈
     * @param title       分享標題
     * @param description 分享描述
     */
    public static void shareVideo(String videoUrl, int flag, String title, String description) {
        //初始化一個 WXImageObject 對象,填寫分享圖片
        WXVideoObject wxImageObject = new WXVideoObject();
        wxImageObject.videoUrl = videoUrl;

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

    /**
     * 分享網頁
     *
     * @param webUrl      網頁鏈接
     * @param flag        0:好友 1:朋友圈
     * @param title       分享標題
     * @param description 分享描述
     */
    public static void shareWeb(String webUrl, int flag, String title, String description) {
        //初始化一個 WXImageObject 對象,填寫分享圖片
        WXWebpageObject wxImageObject = new WXWebpageObject();
        wxImageObject.webpageUrl = webUrl;

        //用 WXTextObject 對象初始化一個 WXMediaMessage 對象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = wxImageObject;
        msg.title = title;
        msg.description = description;
        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的頁面。

參考