Unity 2022 + Android 接入微信登录

实现Unity接入安卓端的微信登录

分为五个大步骤

  1. 生成keystore安卓应用开发者签名
  2. 微信开放平台申请移动应用接入
  3. 编写Java Android部分代码, 生成arr文件
  4. 编写 Unity C# 代码
  5. Unity打apk包, 安装到手机中进行测试

建议按照顺序逐步进行, 1, 2 步如果已经完成, 可直接跳过. 虽然步骤有些多, 但这些步骤只要做一次就好, 往后点击两个按钮就可以完成代码更新.

生成keystore安卓应用开发者签名

  1. 打开 IDEA , 新建项目
    Unity 2022 + Android 接入微信登录_第1张图片
  2. 选择上方工具栏, Generate Signed Bundle/ APK生成密钥
    Unity 2022 + Android 接入微信登录_第2张图片
  3. 点击 Create new
    Unity 2022 + Android 接入微信登录_第3张图片
  4. 分别填入

    • Password
    • Confirm (再填一次密码)
    • Alias
    • Alias Password
    • Alias Confirm
    • Certificate 中填一个就好

    Unity 2022 + Android 接入微信登录_第4张图片

    keystore签名包含一个密钥与多个子签名. 密钥用于开启 keystore 文件, 而一个子签名Key Alias 可用于对一个 Android 应用加密.
  5. 这时可在 key store path 中看见文件
    Unity 2022 + Android 接入微信登录_第5张图片
  6. 需要将该文件转为 .keystore 文件
    我的testKey文件路径为 /Users/chenyuanzhen/Desktop/testKey
    执行以下命令

    keytool -importkeystore -srckeystore /Users/chenyuanzhen/Desktop/testKey -srcstoretype JKS -deststoretype PKCS12 -destkeystore /Users/chenyuanzhen/Desktop/testKey.p12
    
    keytool -v -importkeystore -srckeystore /Users/chenyuanzhen/Desktop/testKey.p12 -srcstoretype PKCS12 -destkeystore /Users/chenyuanzhen/Desktop/testKey.keystore -deststoretype JKS

    完成后会得到 keystore 文件
    Unity 2022 + Android 接入微信登录_第6张图片
    只需要保留 .keystore 文件就好.
    到此第一步结束

微信开放平台申请移动应用接入

  1. 申请接入移动应用后会到这个界面
    Unity 2022 + Android 接入微信登录_第7张图片

    需要注意的是, 接入的移动应用必须要有官网介绍这个应用或者已经上线....
  2. 到这个界面后, 需要填写应用签名与应用包名
    Unity 2022 + Android 接入微信登录_第8张图片

    • 应用签名需要填写 MD5 值, 而且只能有数字和字母, 其余需要去掉.
      这个应用签名是从 keystore 文件中获取的. 获取方法需要执行以下指令.

      keytool -exportcert -rfc -keystore  /Users/chenyuanzhen/Desktop/testKey.keystore  -alias myKey | openssl x509 -inform pem -outform der -out testKey.der
      
      openssl md5 /Users/chenyuanzhen/Desktop/testKey.der 

      会得到如下输出

    image.png
    其中的 85fd... 为应用签名

    • 应用包名建议与刚在 IDEA 新建项目的包名一致

    申请通过后, 到此第二步已经完成.

编写Java Android部分代码, 生成arr文件

  1. 从 Unity 中搬移文件到 Android 项目中.
    Unity 2022 + Android 接入微信登录_第9张图片
    点击任一一个 Copy Path 按钮, 目的是找到 Unity 的安卓环境路径.

    这个需要在 Unity Hub 中安装
    • 将目录中的classes.jar文件复制到安卓项目下的 lib 目录下
    /Applications/Unity/Hub/Editor/2021.3.23f1/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Classes
    • 将位于下方目录的文件复制到安卓项目包内, 并将 package com.unity3d.player; 包名修改为你自己的包名
    /Applications/Unity/Hub/Editor/2021.3.23f1/PlaybackEngines/AndroidPlayer/Source/com/unity3d/player/UnityPlayerActivity.java 
  2. 编写模块内的 build.gradle 文件.

    注意不是项目根目录的 build.gradle 文件
    plugins {
     id 'com.android.library'
    }
    
    android {
     compileSdkVersion 33
     buildToolsVersion "33.0.1"
    
     defaultConfig {
         minSdk 24
         targetSdkVersion 33
    
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         consumerProguardFiles "consumer-rules.pro"
     }
    
     buildTypes {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
    }
    
    dependencies {
    
     implementation 'androidx.appcompat:appcompat:1.6.1'
     implementation 'com.google.android.material:material:1.9.0'
     compileOnly files('tempLibs/classes.jar')
    
     api 'com.tencent.mm.opensdk:wechat-sdk-android:+'
     testImplementation 'junit:junit:'
     androidTestImplementation 'androidx.test.ext:junit:1.1.5'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    }
    
    task copyPlugin(type: Copy) {
     dependsOn assemble
     from('build/outputs/aar')
     into('/Users/chenyuanzhen/UnityProject/projectname/Assets/Plugins/Android')
     include(project.name + '-release.aar')
    
    }
    
    其中 copyPlugin 中的 into 里的文件目录为 Unity 项目目录
  3. 同步 gradle 文件
    使用 IDEA 的话点击
    Unity 2022 + Android 接入微信登录_第10张图片
    按钮
  4. 新建两个包 (假设你的包名为 com.company.project, 在微信平台上登记的也是该包名)

    • com.company.project.wechatplugin

      wechatplugin 可以随意取
    • com.company.project.wxapi

      这个包名必须是 微信平台登记的包名 + wxapi
      否则会出现微信没有回调信息的问题
  5. 将 UnityPlayerActivity.java 文件放置到 com.company.project.wechatplugin 下
  6. 在 com.company.project.wechatplugin 中创建 MainActivity 文件.

    package com.company.project.wechatplugin;
    
    import android.os.Bundle;
    
    import android.util.Log;
    import com.tencent.mm.opensdk.modelmsg.SendAuth;
    import com.tencent.mm.opensdk.openapi.IWXAPI;
    import com.tencent.mm.opensdk.openapi.WXAPIFactory;
    import com.lingdong.drone.wechat.playerActivity.UnityPlayerActivity;
    
    
    public class MainActivity extends UnityPlayerActivity {
    
     public IWXAPI wxapi = null;
     // 这个 APPID 由 Unity 传入
     public static String APPID;
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
     }
    
     private void regWx(String appid){
         APPID = appid;
         if (wxapi==null){
             wxapi = WXAPIFactory.createWXAPI(this,APPID);
             // 将该app注册到微信
             wxapi.registerApp(APPID);
             Log.e("myTencent", "监听注册到微信");
         }
         Log.e("myTencent", "onCreate finished ! ");
     }
    
     public void Login(){
         Log.e("myTencent", "Login!! ");
         SendAuth.Req req = new SendAuth.Req();
         req.scope = "snsapi_userinfo";
         req.state = "wechat_sdk_demo_test";
         wxapi.sendReq(req);
         Log.e("myTencent", "SendReq Finish");
     }
    }
  7. 在 com.company.project.wxapi 下创建 WXEntryActivity.java 文件.

    必须是这个名字
    package com.company.project.wxapi;
    //com.lingdong.drone
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.lingdong.drone.wechat.MainActivity;
    import com.tencent.mm.opensdk.modelbase.BaseReq;
    import com.tencent.mm.opensdk.modelbase.BaseResp;
    import com.tencent.mm.opensdk.modelmsg.SendAuth;
    import com.tencent.mm.opensdk.openapi.IWXAPI;
    import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
    import com.tencent.mm.opensdk.openapi.WXAPIFactory;
    import com.unity3d.player.UnityPlayer;
    
    public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    
     public IWXAPI wxapi = null;
    
    
     public static String gameObjectName = "";
    
     // WXLoginCallBack
     public static String callBackFunctionName = "";
    
     public static void setGameObjectName(String gameObjectName) {
         WXEntryActivity.gameObjectName = gameObjectName;
     }
    
     public static void setCallBackFunctionName(String callBackFunctionName) {
         WXEntryActivity.callBackFunctionName = callBackFunctionName;
     }
    
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
    
         // WXLoginObject
         Log.e("myTencent", "WxEntryActivity onCreate");
         //初始化wxapi
         if (wxapi == null) {
             wxapi = WXAPIFactory.createWXAPI(this, MainActivity.APPID);
         }
         wxapi.registerApp(MainActivity.APPID);
    
         wxapi.handleIntent(getIntent(), this);
     }
    
     @Override
     public void onReq(BaseReq baseReq) {
    
     }
    
    
     @Override
     public void onResp(BaseResp baseResp) {
         Log.e("myTencent", "收到 resp ");
         if (baseResp.getType() == 1) {//微信登录
             if (baseResp.errCode == BaseResp.ErrCode.ERR_OK) {//用户同意
                 UnityPlayer.UnitySendMessage(gameObjectName, callBackFunctionName, ((SendAuth.Resp) baseResp).code);
             } else if (baseResp.errCode == BaseResp.ErrCode.ERR_USER_CANCEL) {//用户取消
                 UnityPlayer.UnitySendMessage(gameObjectName, callBackFunctionName, "用户取消");
             } else if (baseResp.errCode == BaseResp.ErrCode.ERR_AUTH_DENIED) {//用户拒绝
                 UnityPlayer.UnitySendMessage(gameObjectName, callBackFunctionName, "用户拒绝");
             } else {
                 UnityPlayer.UnitySendMessage(gameObjectName, callBackFunctionName, "其他错误");
             }
         } else if (baseResp.getType() == 2) {
    
         }
    
         finish();
     }
    }
  8. 修改项目内的 AndroidManifest.xml 文件

    
    
    
     
         
     
     
    
         
             
                 
                 
             
             
    
         
    
         
         
     
    
    
    

    到此第三步完成.

编写 Unity C# 代码

  1. 在 Unity 项目中创建文件夹

    • /Assets/Plugins/Android

      该文件夹路径必须是这样, Unity官方规定
    • 打开安卓项目, 找到模块内build.gradle, 执行 copyPlugin 任务.

      这时 /Assets/Plugins/Android 目录会出现一个 arr 文件
      建议以后每次运行 copyPlugin 前, 先将旧的 arr 文件删除. 否则 Unity 可能会因缓存使用旧的 arr 文件.
  2. 将微信 sdk 的 jar 包移到 /Assets/Plugins/Android 目录中. 该 jar 包可在 idea 里的 External Libraries 中找到.
    Unity 2022 + Android 接入微信登录_第11张图片
  3. 配置 Unity 设置

    • 覆写 Unity 打包的包名
      Unity 2022 + Android 接入微信登录_第12张图片

      该包名必须与开放平台上登记的一致, 另外必须跟 Android 项目里的包名有所不同. 否则会出现冲突
    • 配置 Unity 打包密钥并勾选 Custom Main Manifest
      Unity 2022 + Android 接入微信登录_第13张图片
  4. 将安卓项目里的 AndroidManifest.xml 复制到 /Assets/Plugins/Android 目录中
  5. 对其进行修改

    
    
    
     
         
     
     
    
         
             
                 
                 
             
             
    
         
    
         
         
     
    
  6. 编写 C# 脚本

    using UnityEngine;
    using UnityEngine.UI;
    
    public class WXLogin : MonoBehaviour
    {
     // public Button button_login, button_quit;
     // public Image image_head;
     public Text text_username, text_code;
    
     // public GameObject go_lobby;
    
     private AndroidJavaClass mainActivityClass = null;
     private AndroidJavaObject mainActivity = null;
    
     private AndroidJavaClass WXEntryActivityClass = null;
    
    
     private string APPID = "你的 APPID";
     private string SECRET = "你的 APP 密钥";
    
    
     // Start is called before the first frame update
     void Start()
     {
         // 配置 APPID
         mainActivityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
         mainActivity = mainActivityClass.GetStatic("currentActivity");
         mainActivity.Call("regWx", APPID);
    
         // 配置 WXEntryActivity
         WXEntryActivityClass = new AndroidJavaClass("com.company.project.wxapi.WXEntryActivity");
         WXEntryActivityClass.CallStatic("setGameObjectName", this.gameObject.name);
         WXEntryActivityClass.CallStatic("setCallBackFunctionName", "WXLoginCallBack");
    
    
     }
    
     public void Onbutton_login()
     {
         mainActivity.Call("Login");
     }
     
    
     public void WXLoginCallBack(string str)
     {
         if (str != "用户取消" && str != "用户拒绝" && str != "其他错误")
         {
    
             Debug.Log("微信登录成功,code是:" + str);
             text_code.text += "微信登录成功,code是:" + str + "\r\n";
         }
         else
         {
             Debug.Log("微信登录失败,code是:" + str);
             text_code.text += "微信登录成功,code是:" + str + "\r\n";
         }
     }
    
    }
  7. 将WXLogin挂在一个 gameObject 下, 并将一个按钮 Onclick 事件触发 Onbutton_login 函数

到此第四步完成.

Unity打apk包, 安装到手机中进行测试

  1. 找到一台安装有微信, 且微信已经登录的手机并与电脑连接

    若用户没有登录微信, 那有可能会不弹窗
  2. 在 Unity 界面中按 command + B 构建 (或者点击按钮)
    Unity 2022 + Android 接入微信登录_第14张图片

构建完成后会自动安装到手机中. 可从手机的日志查看是否登录成功.

执行流程

整个程序执行流程

  1. 用户在 Unity 中点击微信登录按钮
  2. Unity 中的 C# 代码, 使用 AndroidJavaClass 与 AndroidJavaObject 类调用 Android 代码
  3. Android 代码中调用微信 sdk, 并将应用向微信注册
  4. 跳转到微信程序
  5. 用户点击登录确认
  6. 微信程序跳转回 Android 代码, WXEntryActivity
  7. Android 代码使用 UnityPlayer.UnitySendMessage 函数, 调用 Unity C#代码的函数, 并返回微信 code

    UnityPlayer.UnitySendMessage(挂载的 gameObject 名字, 需要调用的函数名, 函数参数)

注意点

  • 若出现问题, 先核查自己的 APPID 与 密钥 是否配置正确. 如果这两个东西不正确, 会报一些意想不到的错误. 例如

    Uninitialized ActivityThread, likely app-created Instrumentation, disabling AppComponentFactory

    很多问题都会报这个错, 例如 AndroidManifest.xml 配置错误也会报这个错.

  • 若出现这个问题
    Unity 2022 + Android 接入微信登录_第15张图片
    那大概率是 arr 包里的文件与 Unity 里的配置冲突.
  • Unity 的 AndroidManifest.xml 配置与 arr 包里的AndroidManifest.xml 配置冲突
  • arr 包名与 Unity 覆写的包名相同

具体可看构建时的报错 console

参考

你可能感兴趣的:(Unity 2022 + Android 接入微信登录)