Unity接入第三方iOS SDK——之微信開放平臺

廢言

這算是Unity接入微信開放平臺的第二篇了,第一篇在這:Unity接入第三方Android SDK——之微信開放平臺 作爲一個既沒有接觸過Android開發、有沒有接觸過iOS開發的人員 ,完成Android和iOS的微信SDK接入,攏共花費了一週的工作時間,效率有點低。

在完成微信SDK接入的過程中,查看過網絡上不少的文章,不過似乎沒有哪一篇是能文章能夠一氣呵成解決問題的,因此自己有了斗膽一試的想法,所以纔有了這兩篇文章的誕生,希望能夠後面接觸的小夥伴節約一些時間。

本文的亮點

最後的完成品,不需要在Xcode中修改、添加任何內容,直接Unity編譯到Xcode然後安裝到真機

一、開始 Universal Links的配置

這部分的內容我就不細講了,相對比較簡單,主要是蘋果開發者和微信開發者後臺的設置,然後把apple-app-site-association這個文件放到域名根目錄即可(域名必須支持HTTPS) apple-app-site-association 這個文件的內容類似下面這樣:

{
    "applinks": {
        "apps": [],
        "details": [{
            "appID": "TeamID.com.yourapp.bundleID",
            "paths": ["*"]
            }
            ]
    }
}
複製代碼

 

二、微信SDK的導入

  1. 前往微信開放平臺下載SDK:developers.weixin.qq.com/doc/oplatfo…
  2. SDK包含4個文件: libWeChatSDK.a,WXApi.h,WXApiObject.h, WechatAuthSDK.h
  3. 將這四個文件放入Unity項目的 Assets/Plugins/iOS 目錄下,這個目錄下的文件會自動打包至Xcode項目的Libraries目錄下。
  4. 在Unity的Inspector中設置libWeChatSDK.a,勾選 Framework dependencies/Security 和 Rarely used frameworks/Webkit,如下圖:

image.pngimage.png 設置完之後記得點 Apply 。

三、擴展UnityAppController

擴展UnityAppController的目的很簡單,這樣就不需要每次導出Xcode項目之後,都去修改UnityAppController.mm中的代碼。 這個我主要參考了這篇博文:blog.mutoo.im/2015/09/mak… 但是最終我用的代碼版本 ,是在他的基礎上去掉了一部分。 創建MyAppController.m文件 ,代碼如下:

//
//  MyAppController.m
//  Unity-iPhone
//
//  Created by Jooki Tsui on 2020/11/13.
//

#import "WXApi.h"
#import "UnityAppController.h"

@interface MyAppController : UnityAppController<WXApiDelegate>
@end

IMPL_APP_CONTROLLER_SUBCLASS (MyAppController)

@implementation MyAppController

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
#if defined(__IPHONE_12_0) || defined(__TVOS_12_0)
    restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring> > * _Nullable restorableObjects))restorationHandler
#else
    restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
#endif
{
    return [WXApi handleOpenUniversalLink:userActivity delegate:self];
}

- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation
{
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [WXApi handleOpenURL:url delegate:self];
}

- (void)onResp:(BaseResp *)resp
{
    // do something
}

- (void)onReq:(BaseReq *)req
{
    // do something
}

@end

複製代碼

具體代碼我就不一句句解釋了,主要是重寫了continueUserActivity、openURL、handleOpenURL這三個方法。 同樣將這個文件放入 Assets/Plugins/iOS 目錄下。

四、編寫Unity和Objective-C的橋接文件

創建NativeBridge.m文件,寫入供Unity調用的方法,代碼如下:

//
//  NativeBridge.m
//  Unity-iPhone
//

#import <Foundation/Foundation.h>
#import "WXApi.h"

//這是向微信終端註冊你的appid
void RegisterApp(const char* appid)
{
    NSString *weichatId = [NSString stringWithFormat:@"%s", appid];
    
    BOOL installed = [WXApi isWXAppInstalled];
    NSLog(@"installed result: %@", installed?@"true":@"false");

    BOOL result = [WXApi registerApp:weichatId universalLink:(@"https://www.mylittleenglish.com/app/hanzi/")];
    
    NSLog(@"result: %@", result?@"true":@"false");
}


// 分享鏈接至微信
void ShareUrlToWX(int scene, const char* url, const char* title, const char* description){
    WXWebpageObject *webpageObject = [WXWebpageObject object];
    webpageObject.webpageUrl = [NSString stringWithUTF8String:url];
    WXMediaMessage *message = [WXMediaMessage message];
    message.title = [NSString stringWithUTF8String:title];
    message.description = [NSString stringWithUTF8String:description];
    // 用APP的Icon做縮略圖
    NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary];
    NSString *icon = [[infoPlist valueForKeyPath:@"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles"] lastObject];
    [message setThumbImage:[UIImage imageNamed:icon]];
    message.mediaObject = webpageObject;
    SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
    req.bText = NO;
    req.message = message;
    req.scene = scene;
    [WXApi sendReq:req completion:nil];
}


//判斷是否安裝微信
bool IsWechatInstalled_iOS()
{
    return [WXApi isWXAppInstalled];
}
複製代碼

我這裏實現了向微信註冊APP、判斷是否安裝了微信App、分享鏈接至微信三個方法。要實現分享更多的媒體消息,比如圖片、小程序等,請查看微信官方文檔:developers.weixin.qq.com/doc/oplatfo… 寫好之後同樣將這個文件放入 Assets/Plugins/iOS 目錄下。

五、在Unity中調用NativeBridge.m中的方法

public class WeChatController
{
    private string _APP_ID = "";

    #region iOS微信SDK
#if !UNITY_EDITOR && UNITY_IOS
    [DllImport("__Internal")]
    private static extern void RegisterApp(string appid);

    [DllImport("__Internal")]
    private static extern bool IsWechatInstalled_iOS();

    [DllImport("__Internal")]
    private static extern void ShareUrlToWX(int scene, string url, string title, string description);
#endif
    #endregion

    private static WeChatController _instance;
    public static WeChatController Instance {
        get {
            if (_instance == null) {
                _instance = new WeChatController();
            }
            return _instance;
        }
    }

    /// <summary>
	/// 初始化微信SDK, APPID是用戶在微信開放平臺註冊是所分配的應用唯一標識, 可在微信開放平臺找到
	/// </summary>
	/// <param name="APPID"></param>
	public void Init(string APPID) {
        _APP_ID = APPID;
#if !UNITY_EDITOR && UNITY_IOS
        RegisterApp(_APP_ID);
#endif
    }

    /// <summary>
	/// 判斷是否是否安裝了微信
	/// </summary>
	/// <returns></returns>
    public bool IsWeChatAppInstalled() {
#if !UNITY_EDITOR && UNITY_IOS
        return IsWechatInstalled_iOS();
#endif
    }

    /// <summary>
	/// 分享鏈接至微信,縮略圖用的是APP Icon
	/// </summary>
	/// <param name="scene">分享至什麼場景, 0-對話、1-朋友圈、2-收藏</param>
	/// <param name="url">網頁鏈接</param>
	/// <param name="title">標題</param>
	/// <param name="description">描述</param>
    public void ShareWebpageToWX(int scene, string url, string title, string description) {
#if !UNITY_EDITOR && UNITY_IOS
        ShareUrlToWX(scene, url, title, description);
#endif
    }
}  
複製代碼

之後就可以再Unity任意腳本中在合適的時機調用WeChatController.Instance.Init()、WeChatController.Instance.IsWeChatAppInstalled()、WeChatController.Instance.ShareWebpageToWX()這些方法。

至此所有的邏輯部分都完成了,接下來就剩下在Xcode中對相關項進行設置了,但是我們不打算手動設置,而是通過代碼自動設置,實現打包全程自動化,不需要人工參與設置參數或者修改代碼。

六、自動完成Xcode項目的各項設置

主要是通過PostProcessBuild來實現。 在Unity項目的 Assets/Editor 目錄下新建一個文件,比如XCodePostProcessBuild.cs 這個文件的目的就是自動設置Xcode項目的相關選項,具體每句代碼設置的是什麼內容,代碼都有註釋:

using UnityEditor;
using System.IO;
using UnityEngine;

#if UNITY_IOS && UNITY_EDITOR
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
#endif

public static class XCodePostProcessBuild
{
#if UNITY_IOS && UNITY_EDITOR
    private static readonly string[] csAddFrameworks = new string[]{
        "Security.framework","WebKit.framework", "CoreGraphics.framework"
    };

    [PostProcessBuild(1)]
    public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)
    {
        if(BuildTarget.iOS != buildTarget)
        {
            return;
        }
        string projectPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";
        SetFrameworksAndBuildSettings(projectPath);
        SetInfoList(pathToBuiltProject, "com.yourapp.bundleApp", "wx_APP_ID");
        SetAssociatedDomains(projectPath, "www.yourdomain.com");
    }

    private static void SetFrameworksAndBuildSettings(string path)
    {
        PBXProject proj = new PBXProject();
        proj.ReadFromString(File.ReadAllText(path));
        string target = proj.GetUnityMainTargetGuid();
        Debug.Log("Target Name is " + target);
        // 設置 BuildSettings
        proj.AddBuildProperty(target, "Other Linker Flags", "-Objc -all_load");
        proj.SetBuildProperty(target, "ENABLE_BITCODE", "NO");

        //根據微信SDK文檔的要求,加入相關的Frameworks
        for (int i = 0; i < csAddFrameworks.Length; ++i)
        {
            if (!proj.ContainsFramework(target, csAddFrameworks[i]))
                proj.AddFrameworkToProject(target, csAddFrameworks[i], false);
        }

        File.WriteAllText(path, proj.WriteToString());        
    }

    public static void SetInfoList(string buildPath, string wxUrlName, string wxScheme)
    {
        string listPath = buildPath + "/Info.plist";
        PlistDocument plist = new PlistDocument();
        plist.ReadFromString(File.ReadAllText(listPath));

        // 在“info”標籤欄的“URL type“添加“URL scheme”,值爲你在微信後臺註冊的應用程序的 AppID
        PlistElementArray urlArray = plist.root.CreateArray("CFBundleURLTypes");
        PlistElementDict dict = urlArray.AddDict();
        dict.SetString("CFBundleTypeRole", "Editor");
        dict.SetString("CFBundleURLName", wxUrlName);
        PlistElementArray urlSchemes = dict.CreateArray("CFBundleURLSchemes");
        urlSchemes.AddString(wxScheme);

        // 在 “info”標籤欄的“LSApplicationQueriesSchemes“添加weixin wechat和weixinULAPI
        PlistElementArray wxArray = plist.root.CreateArray("LSApplicationQueriesSchemes");
        wxArray.AddString("weixin");
        wxArray.AddString("wechat");
        wxArray.AddString("weixinULAPI");


        File.WriteAllText(listPath, plist.WriteToString());
    }

    // 設置Associated Domains
    public static void SetAssociatedDomains(string pbxProjectPath, string domainUrl)
    {
        //默認 Target Name, 你自己的可能不一樣
        string targetName = "Unity-iPhone";
        //Set the entitlements file name to what you want but make sure it has this extension
        string entitlementsFileName = "my_app.entitlements";

        var entitlements = new ProjectCapabilityManager(pbxProjectPath, entitlementsFileName, targetName);
        entitlements.AddAssociatedDomains(new string[] { "applinks:" + domainUrl });
        
        entitlements.WriteToFile();
    }

#endif
}
複製代碼

注意,這個文件是放在Assets/Editor目錄下。

七、小結

以上就是所有流程了,應該還是比較完整的,可能代碼貼的多了點,不過這篇文章對照微信開發文檔來看的話,應該還是很清晰易懂的:developers.weixin.qq.com/doc/oplatfo…

最後,覺得不錯的話記得點個贊呀! 原文鏈接:www.yuque.com/jooki/hcm4i…


作者:JookiTsui
鏈接:https://juejin.cn/post/6894537490510807054
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章