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

2022-11-01 21:00:51

原文: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 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 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的頁面。

參考