• 【Unity】ShareSDK、SMSSDK的基本使用与常见问题


    概要

    测试使用ShareSDK的一些常用功能。包括:

    • 用微博帐号做第三方登录
    • 获取用户的帐号详细信息
    • 获取好友列表
    • 分享功能

    测试使用SMSSDK插件,包括:

    • 导入插件,解决包冲突
    • 短信登录功能:发验证码,收验证码,比对验证码

    学习资料:


    用微博帐号做第三方登录

    1、在mob.com上注册帐号,添加一个应用,给该应用添加ShareSDK。
    2、登录微博开放平台,填写开发者信息。添加一个应用,确定安卓包名,下载微博提供的签名生成工具(md5签名生成器apk),安装到安卓手机上。打开工具输入安卓包名,得到签名字符串。把包名和签名填上。在OAuth2.0授权设置中输入回调页url。
    3、打开Unity新建一个项目,Player Settings中填上上面的包名,自己的密钥库和密钥。
    4、下载ShareSDK for Unity,把包里的ShareSDK.unitypackage导入到项目中。
    5、新建一个场景取名Init,一个空物体(可取名ShareSDKManager),专门用于存放全游戏中通用的(可跨场景长的、生命周期的)数据,开始游戏时先进入该场景,执行ShareSDK初始化,然后再跳转到其他游戏场景。该场景只会进入一次。
    6、给ShareSDKManager物体挂上Share SDK脚本,填上在微博开放平台中给的App Key,App Secret和回调页路径Redirect Url(默认填的是官方给的Debug帐号的信息)。
    7、在脚本的Dev Info中打开本次测试id新浪微博Sinaweibo进行修改。其他不用管,默认都填的官方给的Debug帐号信息。

     

    8、新建一个ShareSDKManager脚本,挂载到ShareSDKManager物体上。
    using cn.sharesdk.unity3d;
    using UnityEngine;
    
    public class ShareSDKManager : MonoBehaviour {
        private static ShareSDKManager _instance;
        public static ShareSDKManager Instance {
            get {
                return _instance;
            }
        }
    
      [HideInInspector]
        public PlatformType userPlatform = PlatformType.Unknown; // 用户登录的平台(是微博登录还是短信登录)
        [HideInInspector]
        public string userID = ""; [HideInInspector]
    public ShareSDK ssdk; void Start () { _instance = this; DontDestroyOnLoad(gameObject); ssdk= gameObject.GetComponent<ShareSDK>(); // ShareSDK.Awake()中已经执行了shareSDKUtils.InitSDK(appKey,appSecret)初始化操作,这里是否写初始化可随意 // 初始化完成后,跳转场景 UnityEngine.SceneManagement.SceneManager.LoadScene(1); } }
    9、新建一个场景取名Login,这是在Init场景之后进入的登录页面场景。新建脚本Login,挂到新建的LoginManager物体上。场景中的【用新浪微博登录】按钮触发该物体中Login脚本对应的方法。登录方法的流程参考下图。这里以应用没有用户系统的体系为例。
    using cn.sharesdk.unity3d;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class Login : MonoBehaviour {
    
        ShareSDK ssdk;
        void Start () {
            ssdk= ShareSDKManager.Instance.shareSDK;
            ssdk.authHandler = OnAuthResultHandler; // 授权结果的回调函数
        }
        
        // 用新浪微博登录
        public void OnSinaLoginButtonClick()
        {
            if (ssdk.IsAuthorized(PlatformType.SinaWeibo)) // 检测指定的平台是否已经授权过了
            {
             // 写入授权信息
                Utility.WriteFile(Application.persistentDataPath, "AuthInfo.txt", ssdk.GetAuthInfo(PlatformType.SinaWeibo).toJson());
                Utility.MakeToast("微博用户:" + ssdk.GetAuthInfo(PlatformType.SinaWeibo)["userName"] + " 登录成功!"); // 信息详情查看输入的文件
                ShareSDKManager.Instance.userPlatform = PlatformType.SinaWeibo;
                SceneManager.LoadScene(2); }
    else // 指定的平台尚未授权,给它授权 { ssdk.Authorize(PlatformType.SinaWeibo); } } /// <summary> /// 授权结果的回调函数 /// </summary> /// <param name="reqID"></param> /// <param name="state">授权状态:成功,失败,取消</param> /// <param name="type">授权平台类型</param> /// <param name="data">返回的数据</param> void OnAuthResultHandler(int reqID, ResponseState state, PlatformType type, Hashtable data) { if (state == ResponseState.Success) {
            // 授权结果写入文件
                Utility.WriteFile(Application.persistentDataPath, "AuthData.txt", data.toJson());
                Utility.WriteFile(Application.persistentDataPath, "AuthInfo.txt", ssdk.GetAuthInfo(PlatformType.SinaWeibo).toJson());
                Utility.MakeToast("微博用户:" + ssdk.GetAuthInfo(PlatformType.SinaWeibo)["userName"] + " 登录成功!"); // 信息详情查看输入的文件
                ShareSDKManager.Instance.userPlatform = PlatformType.SinaWeibo;
                SceneManager.LoadScene(2); }
    else if (state == ResponseState.Fail) { // 失败或取消要清除指定平台的授权信息 ssdk.CancelAuthorize(type); Utility.MakeToast("登录失败!"); } else if (state == ResponseState.Cancel) { // 失败或取消要清除指定平台的授权信息 ssdk.CancelAuthorize(type); Utility.MakeToast("登录被取消!"); } } }
    写一个文件读写的工具类。
    using System.IO;
    
    /// <summary>
    /// 读写文件的工具类。
    /// 用于查看ShareSDK授权时返回的data中有哪些数据。
    /// </summary>
    public static class Utility
    {
        public static void WriteFile(string path, string name, string info)
        {
            StreamWriter writer;
            FileInfo fi = new FileInfo(path + "/" + name);
            writer = fi.CreateText();
            writer.WriteLine(info);
            writer.Close();
            writer.Dispose();
        }
        
        public static string ReadFile(string path, string name)
        {
            StreamReader reader;
            FileInfo fi = new FileInfo(path + "/" + name);
            reader = fi.OpenText();
            string info = reader.ReadToEnd();
            reader.Close();
            reader.Dispose();
            return info;
        }
    }
    9、打包APK后在安卓模拟器上运行。点击【用新浪微博登录】按钮后即可看到效果:首次登录时要填微博账号和密码,输入正确后会跳转到微博授权页面,点击确定授权完成后,游戏进入下一个场景,完成操作。再次登录时直接完成操作,进入下一场景。
    打开输出的两个dat文件,查看返回的详细数据。其中用户ID,用户名,用户头像等是常用的数据。这里为便于自己查看,后缀改成了txt(我用的逍遥游安卓模拟器不让选择.dat打开方式)
    坑点
    • 如果点击按钮没反应,到微博开放平台测试信息—添加测试帐号,关联到自己的微博,因为开发者身份认证未通过审核时不能拿到数据。
    • 如果点击按钮后页面回退,是Unity中ShareSDK脚本的微博App Key和App Secret没填对。(有默认的Debug帐号的数据,注意检查)。
    • 报错“你所访问的站点在微博认证失败 错误号21322 重定向地址不匹配”。是因为在Unity脚本中没有填写回调url,要跟微博开放平台中输入的回调页地址一致才行!
    • 报错 21323 : 请求不合法。该方法登录如果碰到这个问题,过一段时间后再试试就没问题了,非常诡异,也许是新浪服务端那边的问题???怀疑是请求过于频繁导致。没搞懂这个错误。

    获取用户的帐号详细信息

    接着上面的工程,在用户详情页中写一个脚本,在已登录的状态下获取微博账号的详情。

    using cn.sharesdk.unity3d;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.SceneManagement;
    
    public class Info : MonoBehaviour
    {
        public Image userIcon;
        public Text userName;
        public Text userID;
        ShareSDK ssdk;
    
        void Start ()
        {
            ssdk = ShareSDKManager.Instance.ssdk;
            ssdk.showUserHandler = OnGetUserInfoResultHandler;
    
            // 在前一个场景中已把授权返回的数据写入到了本地
            Hashtable authInfo = Utility.ReadFile(Application.persistentDataPath, "AuthInfo.dat").hashtableFromJson();
            StartCoroutine(LoadUserIcon(authInfo["userIcon"].ToString()));
            userName.text = authInfo["userName"].ToString();
            userID.text = "ID:" + authInfo["userID"].ToString();
        }
    
        // 协程下载用户头像Icon
        IEnumerator LoadUserIcon(string url)
        {
            WWW www = new WWW(url);
            yield return www; // 等待下载完才执行下面的代码
            if (www.isDone && www.error == null)
            {
                Texture2D texture2D = www.texture;
                userIcon.sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), Vector2.zero);
            }
        }
    
        // 进入游戏主场景
        public void OnEnterButtonClick()
        {
        }
    
        // 查看用户详细信息
        public void OnDetailButtonClick()
        {
            ssdk.GetUserInfo(PlatformType.SinaWeibo);
        }
    
        // 获取用户详情的回调
        void OnGetUserInfoResultHandler(int reqID, ResponseState state, PlatformType type, Hashtable data)
        {
            if (state == ResponseState.Success)
            {
                // 将用户详情写入文件中,之后随意使用。
                Utility.WriteFile(Application.persistentDataPath, "UserInfo.dat", data.toJson());
                // 如获取用户位置
                Utility.MakeToast("所在地:" + Utility.Unicode2String(data["location"].ToString()));
            }
            else if (state == ResponseState.Fail)
            {
                Utility.MakeToast("获取用户详情失败!");
            }
            else if (state == ResponseState.Cancel)
            {
                Utility.MakeToast("获取用户详情被取消!");
            }
        }
    
        // 注销,退出登录
        public void OnSignOutButtonClick()
        {
            // 取消指定平台的授权
            ssdk.CancelAuthorize(PlatformType.SinaWeibo);
            // 回调登录场景
            SceneManager.LoadScene(1);
        }
    }

    打开UserInfo.dat查看能获取到哪些帐号详情。

    获取好友列表

    using cn.sharesdk.unity3d;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class Play : MonoBehaviour
    {
        public Text resultText;
        ShareSDK ssdk;
    
        void Start ()
        {
            ssdk = ShareSDKManager.Instance.ssdk;
            ssdk.getFriendsHandler = OnGetFriendsResultHandler;
        }
    
        // 点击获取好友列表
        public void OnFriendsButtonClick()
        {
            // 分页获取当前登录用户平台的好友列表,每页容量,第几页(从0开始)
            // 但此接口已被弃用,目前只能准确获得好友总数,且一次请求只能返回2个好友(第三参数填0返回第1和2位好友),后两个参数已失效
            // 如果想靠该接口分页获取所有好友,需要自行多次获取,自行分页
            ssdk.GetFriendList(PlatformType.SinaWeibo, 20, 0);
        }
        
        void OnGetFriendsResultHandler(int reqID, ResponseState state, PlatformType type, Hashtable data)
        {
            if (state == ResponseState.Success)
            {
                // 将好友列表写入文件中,之后随意使用。
                Utility.WriteFile(Application.persistentDataPath, "FriendsList.dat", data.toJson());
            }
            else if (state == ResponseState.Fail)
            {
                Utility.MakeToast("获取好友列表失败!");
            }
            else if (state == ResponseState.Cancel)
            {
                Utility.MakeToast("获取好友列表被取消!");
            }
        }
    }

    查看FriendsList.dat,每个好友的信息有很多数据,同样中文是Unicode需要转成String显示。该接口谨慎使用。

    分享功能

    void Start ()
    {
        ssdk = ShareSDKManager.Instance.ssdk;
        ssdk.shareHandler = OnShareResultHandler;
    }
    
    // 点击分享:截图,配文字,分享
    public void OnShareButtonClick()
    {
        // 屏幕截图,默认存放路径Application.persistentDataPath,多次调用会同名替换图片。
        ScreenCapture.CaptureScreenshot("Screenshot.png");
        // 分享的内容
        ShareContent content = new ShareContent();
    
        // ★通用分享内容的设置
        // 设置分享的文字(正文)
        content.SetText("测试ShareSDK分享功能");
    
        // 设置分享的图片
        // SetImagePath:用于本地图片,参数为图片路径
        // SetImageUrl:用于网络图片,参数为图片网址
        // SetImageArray:用于多图分享,参数为图片网址string数组。仅支持网络图片,仅支持Android。
        content.SetImagePath(Application.persistentDataPath + "/Screenshot.png");
    
        // 其他可设置的额外参数
        content.SetTitle("ShareSDKDemo");           // 标题
        content.SetTitleUrl("http://www.guxin.me"); // 标题的Url
        content.SetSite("guxin.me");                // 分享来源的站点
        content.SetTitle("http://www.guxin.me");    // 站点的Url
        content.SetUrl("http://www.guxin.me");      // 分享的网站
        content.SetUrlDescription("个人学习ShareSDK的Demo");
        // ...
        // 设定分享内容的主要类型,放在最后一步
        content.SetShareType(ContentType.Image);
    
        // ★其他平台特异性分享内容的设置
        ShareContent sinaWeiboContent = new ShareContent();
        sinaWeiboContent.SetText(resultText.text + "
     via 新浪微博");
        // 在指定平台上,使用第二个参数中的内容覆盖主内容里的值
        content.SetShareContentCustomize(PlatformType.SinaWeibo, sinaWeiboContent);
    
        // ★显示分享框
        // PlatformType[] platforms = { PlatformType.SinaWeibo, PlatformType.QQ, PlatformType.WeChat };
        // ssdk.ShowPlatformList(platforms, content, 100, 100);
        // 指定显示平台的方法已弃用,第一个参数穿null即可。
        // string[] platforms = { "5" }; // 查看PlatformType枚举值,如豆瓣是“5”
        // string[] platforms = { ((int)PlatformType.DouBan).ToString() };
        // 可以设置哪些平台不显示。
        string[] platforms = { "5", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "20", "25", "26", "27", "28", "29", "30", "34", "35", "36", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "50", "51", "52", "53", "54" };
        content.SetHidePlatforms(platforms);
    
        ssdk.ShowPlatformList(null, content, 100, 100);
    }
    
    // 分享结果的回调
    void OnShareResultHandler(int reqID, ResponseState state, PlatformType type, Hashtable data)
    {
        // 注意:并非所有平台都会报告正确的状态,如短信、邮件平台,只要界面跳转成功了都算成功(不管玩家接下来是否真的有点发送)。
        if (state == ResponseState.Success)
        {
            Utility.MakeToast("分享成功!");
            // 游戏中分享成功可能会获得一些道具,在这里处理。注意不能正确报告的平台,防止玩家未分享也能获得道具。
            // ......
        }
        else if (state == ResponseState.Fail)
        {
            Utility.MakeToast("分享失败!");
        }
        else if (state == ResponseState.Cancel)
        {
            Utility.MakeToast("分享被取消!");
        }
    }

    Bug:指定了分享界面的显示的可选平台,但还是显示了所有的平台。即设置指定的分享平台无效。

    解决办法有三种:
    一、设置setHidePlatforms,填上所有隐藏的平台,只保留想要的平台。
    二、在ShareSDK脚本上把不需要的平台的Enable取消勾选,直接关闭与该平台的所有交互。
    三、在Plugins-Android-lib里删除不需要的平台的包(ShareSDK开头的lib文件)
    建议使用方法一,可适应如不同界面要显示不同的分享平台等需求。

    导入SMSSDK报错,包冲突问题

    1、登录mob.com后台,给应用添加SMSSDK功能。并从官网下载短信验证码SDK(https://github.com/MobClub/SMSSDK-for-Unity3D),内含详细文档。
    2、将SMSSDK.unitypackage导入项目中。会报错MiniJSON已存在,这是因为已同时存在Assets/Plugins/SMSSDK/MiniJSON.cs和Assets/Plugins/ShareSDK/MiniJSON.cs文件(名称空间相同),删掉一个即可,如删掉SMSSDK文件夹下的。
    3、打包运行,发现报错,AndroidManifest清单文件无法合并等问题。这是因为Assets/Plugins/Android/ShareSDK/lib和Assets/Plugins/Android/SMSSDK/lib文件夹下有相同的MobCommons.lib和MobTools.lib,包冲突了(虽然后边版本号不同)。任意删除一边的两个包即可,如删除SMSSDK文件夹下的。把两个清单的都设置 android:minSdkVersion="16" , android:targetSdkVersion="26"
    AndroidManifest清单合并报错。
    F:workspaceUnity LearningShareSDKDemoTempStagingAreaAndroidManifest-main.xml:28:13-74 Error:
        Attribute activity#com.mob.tools.MobUIShell@configChanges value=(keyboardHidden|orientation|screenSize) from AndroidManifest.xml:28:13-74
        is also present at AndroidManifest.xml:15:13-97 value=(keyboardHidden|orientation|screenSize|locale|layoutDirection).
        Suggestion: add 'tools:replace="android:configChanges"' to <activity> element at AndroidManifest-main.xml:26:9-44:20 to override.
    F:workspaceUnity LearningShareSDKDemoTempStagingAreaAndroidManifest-main.xml:29:13-72 Error:
        Attribute activity#com.mob.tools.MobUIShell@theme value=(@android:style/Theme.Translucent.NoTitleBar) from AndroidManifest.xml:29:13-72
        is also present at AndroidManifest.xml:16:13-60 value=(@android:style/Theme.NoTitleBar).
        Suggestion: add 'tools:replace="android:theme"' to <activity> element at AndroidManifest-main.xml:26:9-44:20 to override.
    
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
    这是因为在Assets/Plugins/Android/ShareSDK/AndroidManifest.xml与Assets/Plugins/Android/SMSSDKGUI/AndroidManifest.xml中有重复设置android:configChanges和android:theme属性。去掉SMSSDKGUI/AndroidManifest.xml中的该属性即可。

    短信登录

    SMSSDK主要使用发验证码、收验证码、比对验证码功能,其他功能已多年未维护,不推荐使用。
    在Init场景中给物体挂上SMSSDK脚本,该脚本已默认填有App Key和App Secret。虽然已在mob后台添加了SMSSDK功能,但测试时依然可以继续用该Debug帐号,因为不受每天20条短信限制。(发布时再改用自己的Key和Secret,上线后不受数量限制,且可定制短信)
    在自定义的管理类中初始化smssdk。
    // SMSSDK初始化
    smssdk = gameObject.GetComponent<SMSSDK>();
    smssdk.init("moba6b6c6d6", "b89d2427a3bc7ad1aea1e1e8c1d36bf3", true); // 用默认的Debug帐号的App Key和App Secret测试。上线时改用在mob后台给的值。

    主逻辑脚本继承SMSSDKHandler接口,实现onComplete()和onError()这两个回调函数,smssdk.setHandler()注册。注意枚举ActionType.SubmitUserInfo和ActionType.GetFriends已很久未维护,不推荐使用。

    最终整合了微博登录与短信登录的脚本如下。

    using cn.sharesdk.unity3d;
    using cn.SMSSDK.Unity;
    using System.Collections;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class Login : MonoBehaviour, SMSSDKHandler
    {
        ShareSDK ssdk;
        SMSSDK smssdk;
    
        void Start () {
            ssdk = ShareSDKManager.Instance.ssdk;
            ssdk.authHandler = OnAuthResultHandler; // 授权结果的回调函数
    
            smssdk = ShareSDKManager.Instance.smssdk;
            smssdk.setHandler(this); // 短信操作的回调
        }
        
        // 用新浪微博登录
        public void OnSinaLoginButtonClick()
        {
            if (ssdk.IsAuthorized(PlatformType.SinaWeibo)) // 检测指定的平台是否已经授权过了
            {
                // 写入授权信息
                Utility.WriteFile(Application.persistentDataPath, "AuthInfo.txt", ssdk.GetAuthInfo(PlatformType.SinaWeibo).toJson());
                Utility.MakeToast("微博用户:" + ssdk.GetAuthInfo(PlatformType.SinaWeibo)["userName"] + "
    登录成功!"); // 信息详情查看输入的文件
                ShareSDKManager.Instance.userPlatform = PlatformType.SinaWeibo;
                SceneManager.LoadScene(2);
            }
            else // 指定的平台尚未授权,给它授权
            {
                ssdk.Authorize(PlatformType.SinaWeibo);
            }
        }
    
        /// <summary>
        /// 授权结果的回调函数
        /// </summary>
        /// <param name="reqID"></param>
        /// <param name="state">授权状态:成功,失败,取消</param>
        /// <param name="type">授权平台类型</param>
        /// <param name="data">返回的数据</param>
        void OnAuthResultHandler(int reqID, ResponseState state, PlatformType type, Hashtable data)
        {
            if (state == ResponseState.Success)
            {
                // 授权结果写入文件
                Utility.WriteFile(Application.persistentDataPath, "AuthData.txt", data.toJson());
                Utility.WriteFile(Application.persistentDataPath, "AuthInfo.txt", ssdk.GetAuthInfo(PlatformType.SinaWeibo).toJson());
                Utility.MakeToast("微博用户:" + ssdk.GetAuthInfo(PlatformType.SinaWeibo)["userName"] + "
    登录成功!"); // 信息详情查看输入的文件
                ShareSDKManager.Instance.userPlatform = PlatformType.SinaWeibo;
                SceneManager.LoadScene(2);
            }
            else if (state == ResponseState.Fail)
            {
                // 失败或取消要清除指定平台的授权信息
                ssdk.CancelAuthorize(type);
                Utility.MakeToast("登录失败!");
            }
            else if (state == ResponseState.Cancel)
            {
                // 失败或取消要清除指定平台的授权信息
                ssdk.CancelAuthorize(type);
                Utility.MakeToast("登录被取消!");
            }
        }
    
        // 用短信登录,有两种方式
        public void OnSmsButtonClick()
        {
            // 方式一:非UI方式,需要搭配Unity里自己制作的UI
            /*
             * 通过getCode()获得验证码,参数是:验证码类型(短信/语音),手机号,国际区域号(大陆为86,非国内电话的区号),模板号
             * smssdk.getCode(CodeType, phone, zone, tempCode);
             * 通过commitCode()方式提交验证码,参数:手机号,国际区域号(大陆为86,非国内电话的区号),验证码
             * smssdk.commitCode(phone, zone, code);
             */
    
            // 方式二:UI方式,直接使用SMSSDK自带的UI(Android下的界面)
            smssdk.showRegisterPage(CodeType.TextCode, null); //tempcode是模板编号,如还未申请传null即可。申请新模板要等审核通过。
        }
    
    
        // 短信操作,完成
        public void onComplete(int action, object resp)
        {
            ActionType act = (ActionType)action;
            //Debug.Log(act);
            if (act == ActionType.CommitCode)
            {
                ShareSDKManager.Instance.userPlatform = PlatformType.SMS;
                ShareSDKManager.Instance.userID = ((string)resp).hashtableFromJson()["phone"].ToString();
                Utility.MakeToast("手机用户:" + ShareSDKManager.Instance.userID + "
    登录成功!");
                SceneManager.LoadScene(2);
            }
        }
    
        // 短信操作,失败
        public void onError(int action, object resp)
        {
            Utility.MakeToast("短信验证失败!");
        }
    }

    自用Demo:https://gitee.com/guxin233/Unity_ShareSDK_Demo

     

     
  • 相关阅读:
    归并排序的java实现
    Hanoi问题java解法
    j2ee之Filter使用实例(页面跳转)
    java工具类之Graphics
    java程序设计之循环链表
    Java程序设计求出岁数
    Java程序设计之链表结构
    CENTOS 6 通过YUM升级GCC到4.7/4.8
    Object c的NSString的使用,创建,拼接和分隔,子string,substring
    Let’s Encrypt 最近很火的免费SSL 使用教程
  • 原文地址:https://www.cnblogs.com/guxin/p/unity-sharesdk-login-demo.html
Copyright © 2020-2023  润新知