Unity iOS接入微信登录--cocoapods集成

诗林  金牌会员 | 2024-6-22 12:59:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 492|帖子 492|积分 1476

官方教程:iOS接入指南 | 微信开放文档
我是用cocoapods集成的,因为手动集成老有下面这个问题,一时解决不了
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[WXApi genExtraUrlByReq:withAppData:]: unrecognized selector sent to class
  1. Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[WXApi genExtraUrlByReq:withAppData:]: unrecognized selector sent to class
复制代码
一、安装cocoapods

1、安装Homebrew

国内源:HomebrewCN: Homebrew 国内安装脚本,快速部署 brew ,国内镜像
这个源真的很棒,安装很快。
安装Homebrew
  1. /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
复制代码
2、安装cocoapods

  1. brew install cocoapods
复制代码
二、接入微信登录

1、下载微信sdk

前往下载基本信息 | 微信开放文档,打开压缩文件

我把三个文件放在Plugins/iOS/文件夹下的同一个文件夹内了

2、编写ObjectiveC代码调用微信api

创建WeChatUnity.mm、WXApiManager.h、WXApiManager.mm这三个文件,文件也放在Plugins/iOS/文件夹下

代码内容如下,参考网上大佬的:
WeChatUnity.mm
  1. // WeChatUnity.mm
  2. #import <Foundation/Foundation.h>
  3. #import "WXApiManager.h"
  4. #import <UIKit/UIKit.h>
  5. #import <WXApi.h>
  6. #define UNITY_CS_API extern "C"
  7. static NSString *mWXAppid = nil;
  8. // 将c字符串const char* 转为 oc字符串NSString
  9. static inline NSString * str_c2ns(const char*s)
  10. {
  11.     if (s)
  12.         return [NSString stringWithUTF8String: s];
  13.     else
  14.         return [NSString stringWithUTF8String: ""];
  15. }
  16. // 初始化
  17. UNITY_CS_API void WeChatInit(const char* appId, const char* universalLink)
  18. {
  19.     NSLog(@"WeChatInit");
  20.     //在register之前打开log, 后续可以根据log排查问题,第一次测试sdk时可以取消注释
  21.     // [WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) {
  22.     //     NSLog(@"WeChatSDK: %@", log);
  23.     // }];
  24.     // 向微信注册
  25.         mWXAppid = str_c2ns(appId);
  26.     NSString *link = str_c2ns(universalLink);
  27.     NSLog(@"init: %@   %@", mWXAppid, link);
  28.         [WXApi registerApp:mWXAppid universalLink:link];
  29.     // 调用自检函数,第一次测试sdk时可以取消注释
  30.     // [WXApi checkUniversalLinkReady:^(WXULCheckStep step, WXCheckULStepResult* result) {
  31.     //     NSLog(@"%@, %u, %@, %@", @(step), result.success, result.errorInfo, result.suggestion);
  32.     // }];
  33. }
  34. // WeChatUnity.mm
  35. UNITY_CS_API void WeChatLogin(const char* state)
  36. {
  37.     NSLog(@"WeChatLogin");
  38.     SendAuthReq* req = [[SendAuthReq alloc] init];
  39.     req.scope = @"snsapi_userinfo";;
  40.     req.state = str_c2ns(state);
  41.     [WXApi sendReq:req completion:nil];
  42.     // 此时会拉起微信,授权后会回调WXApiManager的onResp方法
  43. }
复制代码
WXApiManager.h
  1. // WXApiManager.h
  2. #import <Foundation/Foundation.h>
  3. #import <UIKit/UIKit.h>
  4. #import "WXApi.h"
  5. // @end
  6. @interface WXApiManager : UIResponder<UIApplicationDelegate, WXApiDelegate>
  7. @property (strong, nonatomic) UIWindow *window;
  8. + (instancetype)sharedManager;
  9. @end
复制代码
WXApiManager.mm
  1. #import "WXApiManager.h"
  2. @implementation WXApiManager
  3. // 单例
  4. +(instancetype)sharedManager {
  5.     static dispatch_once_t onceToken;
  6.     static WXApiManager *instance;
  7.     dispatch_once(&onceToken, ^{
  8.         instance = [[WXApiManager alloc] init];
  9.     });
  10.     return instance;
  11. }
  12. // WXApiManager.mm
  13. - (void)onResp:(BaseResp *)resp {
  14.         if ([resp isKindOfClass:[SendAuthResp class]]) {
  15.                 NSLog(@"微信授权回调");
  16.                 if (resp.errCode == 0) {
  17.             UnitySendMessage("UnityAndroidConnector", "WeChatLoginSuccess", ((SendAuthResp *)resp).code.UTF8String);
  18.                 }
  19.                 else
  20.                 {
  21.                         // 失败,回调给Unity
  22.             NSString *stringNumber = [NSString stringWithFormat:@"%d", resp.errCode];
  23.                         UnitySendMessage("UnityAndroidConnector", "WeChatLoginFail", stringNumber.UTF8String);
  24.                 }
  25.         }
  26. }
  27. - (void)onReq:(BaseReq *)req {
  28.         // TODO 微信回调,从微信端主动发送过来的请求
  29. }
  30. @end
复制代码
创建xxxAppController.mm文件,我这里叫CustomAppController,也放在Plugins/iOS/文件夹下

CustomAppController.mm,内容如下
  1. // CustomAppController.mm
  2. #import "WXApiManager.h"
  3. #import  "UnityAppController.h"
  4. @interface CustomAppController : UnityAppController
  5. @end
  6. IMPL_APP_CONTROLLER_SUBCLASS (CustomAppController)
  7. @implementation CustomAppController
  8. - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  9. {
  10.     [super application:application didFinishLaunchingWithOptions:launchOptions];
  11.        
  12.     // 可以在这里自动注册微信,也可以在手动调用WeChatUnity.mm的WeChatInit进行注册
  13.     // [WXApi registerApp:@"wx123123123" universalLink:@"https://xxx.com/app/"];
  14.    
  15.     return YES;
  16. }
  17. - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
  18.     return  [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
  19. }
  20. - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
  21.     return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
  22. }
  23. - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler
  24. {
  25.     return [WXApi handleOpenUniversalLink:userActivity delegate:[WXApiManager sharedManager]];
  26. }
  27. @end
复制代码
3、编写Unity代码调用和处理回调

调用方法如下:
  1.         void iOSInit()
  2.         {
  3.             WeChatInit("wx12312312", "https://www.xxx.com/app/");
  4.         }
  5.         void iOSLogin()
  6.         {
  7.             WeChatLogin("app_wechat");
  8.         }
  9.         [DllImport("__Internal")]
  10.         static extern void WeChatInit(string appId, string universalLink);
  11.         [DllImport("__Internal")]
  12.         static extern void WeChatLogin(string state);
复制代码
回调处理:UnityAndroidConnector.cs
  1. public class UnityAndroidConnector : MonoSingleton<UnityAndroidConnector>
  2.     {
  3.         
  4.         public void WeChatLoginSuccess(string code)
  5.         {
  6.             // 传给服务器
  7.         }
  8.         public void WeChatLoginFail(string codestr)
  9.         {
  10.             int code = int.Parse(codestr);
  11.             // 错误码处理
  12.         }
  13.     }
复制代码
WXApiManager.mm中的UnitySendMessage方法里的参数就对应UnityAndroidConnector.cs里的方法。
记得:UnityAndroidConnector.cs必要挂载在名为UnityAndroidConnector的组件上,即组件名和脚本名保持一致,这个名字你也可以取你喜欢的
  1. UnitySendMessage("UnityAndroidConnector", "WeChatLoginSuccess", ((SendAuthResp *)resp).code.UTF8String);
  2. UnitySendMessage("UnityAndroidConnector", "WeChatLoginFail", stringNumber.UTF8String);
复制代码
三、打包

1、引入External Dependency Manager for Unity

 ​​​​​​​GitHub - googlesamples/unity-jar-resolver: Unity plugin which resolves Android & iOS dependencies and performs version management

打开设置,Assets--External Dependency Manager--iOS Resolver--Settings,设置我这边用的是默认的,然后 Always add the main target to Podfile 这个设置取消勾选(否则会在Build Phases--Link Binary With Libraries里添加上一个Pod_xxxx_framework,打包时会报错,必要手动删除)


2、创建xxxDependencies.xml

在任意Editor文件夹下创建一个xxxDependencies.xml,用于cocoapods打包用,我这里是WechatDependencies.xml

WechatDependencies.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <dependencies>
  3.     <iosPods>
  4.         <iosPod name="WechatOpenSDK-XCFramework"  bitcodeEnabled="true" >  </iosPod>
  5.     </iosPods>
  6. </dependencies>
复制代码
3、xcode配置

直接用脚本配置xcode配置项,该脚本也必要放在任意Editor文件夹下
  1. using UnityEditor;
  2. using UnityEditor.Build;
  3. using UnityEditor.Build.Reporting;
  4. using UnityEngine;
  5. #if UNITY_IOS
  6. using UnityEditor.iOS.Xcode;
  7. class iOSBuildTool : IPostprocessBuildWithReport
  8. {
  9.     public int callbackOrder { get { return 0; } }
  10.     public void OnPostprocessBuild(BuildReport report)
  11.     {
  12.         if (report.summary.platform == BuildTarget.iOS)
  13.         {
  14.             string projectPath = report.summary.outputPath + "/Unity-iPhone.xcodeproj/project.pbxproj";
  15.             PBXProject pbxProject = new PBXProject();
  16.             pbxProject.ReadFromFile(projectPath);
  17.             //Disabling Bitcode on all targets
  18.             //Main
  19.             string target = pbxProject.GetUnityMainTargetGuid();
  20.             pbxProject.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
  21.             pbxProject.SetBuildProperty(target, "CONFIGURATION", "Release");
  22.             pbxProject.SetBuildProperty(target, "CONFIGURATION_BUILD_DIR", "$(BUILD_DIR)/$(CONFIGURATION)");
  23.             pbxProject.SetBuildProperty(target, "OTHER_LDFLAGS", "-ObjC -all_load -lstdc++ -lsqlite3");
  24.             // 添加framework
  25.             pbxProject.AddFrameworkToProject(target, "Security.framework", false);
  26.             pbxProject.AddFrameworkToProject(target, "CoreGraphics.framework", false);
  27.             pbxProject.AddFrameworkToProject(target, "WebKit.framework", false);
  28.             //Unity Tests
  29.             string targetGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTestTargetName());
  30.             pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
  31.             //Unity Framework
  32.             string frameworkTarget = pbxProject.GetUnityFrameworkTargetGuid();
  33.             pbxProject.SetBuildProperty(frameworkTarget, "ENABLE_BITCODE", "NO");
  34.             pbxProject.SetBuildProperty(frameworkTarget, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "NO");
  35.             // 写入
  36.             pbxProject.WriteToFile(projectPath);
  37.             // 修改Info.plist文件
  38.             var plistPath = report.summary.outputPath + "/Info.plist";
  39.             var plist = new PlistDocument();
  40.             plist.ReadFromFile(plistPath);
  41.             PlistElementDict rootDict = plist.root;
  42.             // example of adding a boolean key...
  43.             //设置LSApplicationQueriesSchemes(数组)
  44.             PlistElementArray loginChannelsArr;
  45.             loginChannelsArr = rootDict.CreateArray("LSApplicationQueriesSchemes");
  46.             loginChannelsArr.AddString("weixin");
  47.             loginChannelsArr.AddString("weixinULAPI");
  48.             loginChannelsArr.AddString("weixinURLParamsAPI");
  49.             // 添加 url scheme
  50.             PlistElementArray urlTypes = rootDict.CreateArray("CFBundleURLTypes");
  51.             PlistElementDict wxUrl = urlTypes.AddDict();
  52.             wxUrl.SetString("CFBundleTypeRole", "Editor");
  53.             wxUrl.SetString("CFBundleURLName", "weixin");
  54.             PlistElementArray wxUrlScheme = wxUrl.CreateArray("CFBundleURLSchemes");
  55.             wxUrlScheme.AddString("wx12312312");
  56.             // 是否加密
  57.             rootDict.SetBoolean("ITSAppUsesNonExemptEncryption", false);
  58.             // 麦克风权限
  59.             rootDict.SetString("NSMicrophoneUsageDescription", "允许访问您的麦克风,以便您能够在xxxx中使用语音功能");
  60.             // 应用修改
  61.             plist.WriteToFile(plistPath);
  62.             //xxx是项目得名称,一定要修改成对应的项目名称
  63.             ProjectCapabilityManager projectCapabilityManager = new ProjectCapabilityManager(projectPath, "Entitlements.entitlements", "Unity-iPhone");
  64.             // 添加关联域名
  65.             projectCapabilityManager.AddAssociatedDomains(new string[] {
  66.                 "applinks:www.xxx.com",
  67.                
  68.             });
  69.             // 添加通知
  70.             // projectCapabilityManager.AddPushNotifications(true);
  71.             projectCapabilityManager.WriteToFile();
  72.         }
  73.     }
  74. }
  75. #endif
复制代码
4、Unity--Build Settings--Build

打包后运行.xcworkspace这个工程,别运行xcodeproj那个工程,然后真机测试。

大致流程应该就这些,有问题就参考一下官方辣鸡教程或者其他大佬的方法。

关于Universal Link的阐明

微信开发者后台必要配置Universal Link,一般格式为https://xxx.com/yyy/,xxx.com就是你的域名,yyy就是path

同时必要在你的域名根目次下或者.well-known目次下有一个apple-app-site-association文件,大致内容如下,内容格式为json格式,但文件不带任何后缀名(即你可以先创建一个json文件,保存好后删除文件名里的'.json'后缀)。
  1. {
  2.     "applinks": {
  3.         "apps": [],
  4.         "details": [
  5.                 {
  6.                     "appID": "teamid.bundle_id",
  7.                     "paths": ["/app/*"]
  8.             }
  9.         ]
  10.     }
  11. }
复制代码
teamid可在apple开发者后台拿到,网上搜一下就知道了;bundle_id就是你Unity项目的包名com.xxx.xxxx;paths里的app就对应上面说的app,后面记得加一个‘*’号。
还和Universal Link有关的就是上面提到的WeChatUnity.mm和CustomAppController.mm里的微信注册,那个universalLink的值就是Universal Link,即https://xxx.com/app/,而xcode配置脚本里的applink则是域名,即www.xxx.com,别搞错了。
在安装了你的app的手机safari欣赏器地址输入你的Universal Link加随机码(如https://xxx.com/app/abc),转到这个链接时,顶部应该是能出现打开你的app的下拉窗口的,这就表现你的Universal Link配置正确了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

诗林

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表