[Unity]腾讯SDK踩坑之路(2)--配置Xcode工程(MSDK和米大师配置代码冲突)

        前不久接完MSDK,又花了几天时间改之前的打包工具和MSDK的一些代码,主要是这边有骚操作,需要不带SDK的包和带SDK的包,还有很多杂七杂八的包。然后顺带着打了个iOS测试包,检测SDK有没有接好。大厂给的插件中有对XCode工程进行配置,不需要手动去拖frameworks和添加代码啥的,简单方便。稍微改下,就能快速打iOS包。确认没问题后,就马不停蹄的开始接入米大师充值SDK。

        米大师SDK也有Unity版的插件,就直接用这个,安卓上的接入相对简单。XCode这边就有点麻烦了,因为米大师也在OnPostProcessBuild这个回调方法里进行了处理,就对代码进行了合并,发现各种问题,然后一个个解决过来。主要是MSDK和米大师都对XUPorter进行了修改,虽然后面全部解决了,但如果再有个第3方SDK,也用到了XUPorter,也进行了魔改,后面的维护不要太大啊。想了想,决定用Unity自带的API来,不用大厂的代码来自动配置,而且项目中Unity版本比较高,是2017版本的,也不需要配置其他插件,简单方便。

        参考了一些大佬文章,用Unity的自带API也挺累的,很多都靠试,然后打包验证,花了一两天的时间结束,测试也没问题,也说下遇到的问题,google有搜到说建议用ProjectCapabilityManager这个类,用过发现不好用,不知道是不是XCode版本太高导致的,还是怎么了。PBXProject.AddCapability能开启InAppPurchase,但ProjectCapabilityManager就不能开启,后面就没有用上,这是官方的Bug吗?

        代码:逻辑应该还算比较清晰,就懒得一一注释了。也测试过,MSDK和米大师都没有问题。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;
using System;

public class ZPXCodePostProcess
{
#if UNITY_EDITOR
    [PostProcessBuild(1000)]
    public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
    {
        if (target != BuildTarget.iOS) return;

        string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
        PBXProject project = new PBXProject();
        project.ReadFromString(File.ReadAllText(projPath));

        GenerateProjectFile(project, pathToBuiltProject);

        string plistPath = pathToBuiltProject + "/Info.plist";
        PlistDocument plist = new PlistDocument();
        plist.ReadFromString(File.ReadAllText(plistPath));

        GeneratePlistFile(plist.root, plistPath);

        File.WriteAllText(projPath, project.WriteToString());
        File.WriteAllText(plistPath, plist.WriteToString());

        DeployIOS.EditorCode(pathToBuiltProject);
    }

    /// <summary>
    /// 处理XCode工程
    /// </summary>
    /// <param name="project"></param>
    /// <param name="pathToBuiltProject"></param>
    private static void GenerateProjectFile(PBXProject project, string pathToBuiltProject)
    {
        string target = project.TargetGuidByName(PBXProject.GetUnityTargetName());

        project.SetBuildProperty(target, "CODE_SIGN_IDENTITY", "********");
        project.SetBuildProperty(target, "PROVISIONING_PROFILE_SPECIFIER", "******");
        project.SetBuildProperty(target, "DEVELOPMENT_TEAM", "******");
        project.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
        project.SetBuildProperty(target, "CODE_SIGNING_STYLE", "MANUAL");

        // 添加flag
        project.AddBuildProperty(target, "OTHER_LDFLAGS", "-ObjC");

        // 添加系统库
        AddSystemFramework(project, target);

        // 添加第3方
        AddOther(project, target, pathToBuiltProject);

        //project.AddCapability(target, PBXCapabilityType.PushNotifications);
        project.AddCapability(target, PBXCapabilityType.InAppPurchase);
        project.AddCapability(target, PBXCapabilityType.BackgroundModes);
        
    }

    private static void AddSystemFramework(PBXProject project, string target)
    {
        string[] frameworks =
        {
            "libz.dylib",
            "libz.1.1.3.dylib",
            "libsqlite3.dylib",
            "libxml2.dylib",
            "libc++.dylib",
            "libstdc++.dylib",

            "CoreTelephony.framework",
            "SystemConfiguration.framework",
            "UIKit.framework",
            "Foundation.framework",
            "CoreGraphics.framework",
            "MobileCoreServices.framework",
            "StoreKit.framework",
            "CFNetwork.framework",
            "CoreData.framework",
            "Security.framework",
            "CoreLocation.framework",
            "ImageIO.framework",
            "CoreText.framework",
            "QuartzCore.framework",
            "AdSupport.framework",
            "Accelerate.framework",
            "CoreImage.framework",
            "SafariServices.framework",
            "Social.framework",
            "JavaScriptCore.framework",
            "AssetsLibrary.framework",
            "MediaPlayer.framework",
            "AddressBook.framework",
            "CoreMotion.framework",
            "AVFoundation.framework",
            "MessageUI.framework",
            "EventKit.framework",
            "EventKitUI.framework",
            "CoreAudio.framework",
        };

        foreach (var framework in frameworks)
        {
            project.AddFrameworkToProject(target, framework, false);
        }
    }

    private static void AddOther(PBXProject project, string target, string pathToBuiltProject)
    {
        UpdateiOSPlugin(pathToBuiltProject);

        // 添加MSDK相关
        project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Third/MSDK");
        AddFile(project, target, "Third/MSDK/MSDK.framework");
        AddFile(project, target, "Third/MSDK/MSDKResources.bundle");
        AddFile(project, target, "Third/MSDK/WGPlatformResources.bundle");
        AddFile(project, target, "Third/MSDK/MSDKAdapter.framework");

         // Bugly
        project.AddBuildProperty(target, "LIBRARY_SEARCH_PATHS", "$(PROJECT_DIR)/Third/Bugly");
        AddFile(project, target, "Third/Bugly/BuglyBridge.h");
        AddFile(project, target, "Third/Bugly/libBuglyBridge.a");

        // 添加米大师相关
        project.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Third/Midas/local");
        AddFile(project, target, "Third/Midas/local/MidasIAPSDK.bundle");
        AddFile(project, target, "Third/Midas/local/MidasIAPSDK.framework");
        AddFile(project, target, "Third/Midas/Script/MidasLocalIAPSDKAdapter.h");
        AddFile(project, target, "Third/Midas/Script/MidasSdkConnector.h");
        AddFile(project, target, "Third/Midas/Script/MidasLocalIAPSDKAdapter.m");
        AddFile(project, target, "Third/Midas/Script/MidasSdkConnector.m");
    }

    private static bool UpdateiOSPlugin(string pathToBuiltProject)
    {
        bool bIsFinish = false;

        try
        {
            int lastIndex = Application.dataPath.LastIndexOf("/");
            string sdkPluginPath = Application.dataPath.Substring(0, lastIndex) + "/PlatformSDKPlugin/iOS/Third";

            // C++11 版本
            if(ConfigSettings.Instance.UseC11)
                sdkPluginPath += "_C11";

            if (Directory.Exists(sdkPluginPath))
            {
                int length = sdkPluginPath.Length;
                if ('/' == sdkPluginPath[length - 1] || '\\' == sdkPluginPath[length - 1])
                    --length;

                string[] files = Directory.GetFiles(sdkPluginPath, "*.*", SearchOption.AllDirectories);
                for (int i = 0; i < files.Length; ++i)
                {
                    string tempStr = files[i].Remove(0, length);
                    string tempDestPath = pathToBuiltProject + "/Third/" + tempStr;
                    string tempDir = Path.GetDirectoryName(tempDestPath);
                    if (!Directory.Exists(tempDir))
                        Directory.CreateDirectory(tempDir);
                    File.Copy(files[i], tempDestPath, true);
                }
            }

            bIsFinish = true;
        }
        catch (Exception e)
        {
            Debug.LogException(e);
        }

        return bIsFinish;
    }

    private static void AddFile(PBXProject project, string target, string destPath)
    {
        project.AddFileToBuild(target, project.AddFile(destPath, destPath, PBXSourceTree.Source));
    }

    /// <summary>
    /// 处理Plist工程
    /// </summary>
    /// <param name="project"></param>
    /// <param name="plistPath"></param>
    private static void GeneratePlistFile(PlistElementDict rootDict, string plistPath)
    {
        PlistElementArray urlArray = null;
        if (!rootDict.values.ContainsKey("CFBundleURLTypes"))
            urlArray = rootDict.CreateArray("CFBundleURLTypes");
        else
            urlArray = rootDict.values["CFBundleURLTypes"].AsArray();
        var urlTypeDict = urlArray.AddDict();
        urlTypeDict.SetString("CFBundleTypeRole", "Editor");
        urlTypeDict.SetString("CFBundleURLName", "weixin");
        var urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
        urlScheme.AddString(DeploySettings.Instance.WxAppId);

        urlTypeDict = urlArray.AddDict();
        urlTypeDict.SetString("CFBundleTypeRole", "Editor");
        urlTypeDict.SetString("CFBundleURLName", "tencentopenapi");
        urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
        urlScheme.AddString("tencent" + DeploySettings.Instance.QqAppId);

        urlTypeDict = urlArray.AddDict();
        urlTypeDict.SetString("CFBundleTypeRole", "Editor");
        urlTypeDict.SetString("CFBundleURLName", "tencentvideo");
        urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
        urlScheme.AddString("tencentvideo" + DeploySettings.Instance.QqAppId);

        urlTypeDict = urlArray.AddDict();
        urlTypeDict.SetString("CFBundleTypeRole", "Editor");
        urlTypeDict.SetString("CFBundleURLName", "QQ");
        urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
        urlScheme.AddString(DeploySettings.Instance.QqScheme);

        urlTypeDict = urlArray.AddDict();
        urlTypeDict.SetString("CFBundleTypeRole", "Editor");
        urlTypeDict.SetString("CFBundleURLName", "QQLaunch");
        urlScheme = urlTypeDict.CreateArray("CFBundleURLSchemes");
        urlScheme.AddString("tencentlaunch" + DeploySettings.Instance.QqAppId);

        rootDict.SetString("CHANNEL_DENGTA", "***");
        rootDict.SetString("MSDK_OfferId", DeploySettings.Instance.IOSOfferId);
        rootDict.SetString("MSDK_ENV", ConfigSettings.Instance.MsdkUrlEnv);
        rootDict.SetString("QQAppID", DeploySettings.Instance.QqAppId);
        rootDict.SetString("WXAppID", DeploySettings.Instance.WxAppId);
        rootDict.SetString("MSDKKey", DeploySettings.Instance.MsdkKey);
        rootDict.SetBoolean("MSDK_PUSH_SWITCH", true);
        rootDict.SetBoolean("AutoRefreshToken", true);
        rootDict.SetBoolean("NeedNotice", true);
        rootDict.SetInteger("NoticeTime", 900);
        rootDict.SetInteger("MSDK_REAL_NAME_AUTH_SWITCH", 1);
        rootDict.SetBoolean("MSDK_Webview_Landscape_NavBar_Hideable", false);
        rootDict.SetBoolean("MSDK_Webview_Portrait_NavBar_Hideable", false);

        if (!rootDict.values.ContainsKey("LSApplicationQueriesSchemes"))
            urlArray = rootDict.CreateArray("LSApplicationQueriesSchemes");
        else
            urlArray = rootDict.values["LSApplicationQueriesSchemes"].AsArray();
        urlArray.AddString("mqq");
        urlArray.AddString("mqqapi");
        urlArray.AddString("wtloginmqq2");
        urlArray.AddString("mqqopensdkapiV4");
        urlArray.AddString("mqqopensdkapiV3");
        urlArray.AddString("mqqopensdkapiV2");
        urlArray.AddString("mqqwpa");
        urlArray.AddString("mqqOpensdkSSoLogin");
        urlArray.AddString("mqqgamebindinggroup");
        urlArray.AddString("mqqopensdkfriend");
        urlArray.AddString("mqzone");
        urlArray.AddString("weixin");
        urlArray.AddString("wechat");

        rootDict.SetString("NSCameraUsageDescription", "");
        rootDict.SetString("NSPhotoLibraryUsageDescription", "");


        if (rootDict.values.ContainsKey("NSAppTransportSecurity"))
            rootDict.values.Remove("NSAppTransportSecurity");
        PlistElementDict urlDict = rootDict.CreateDict("NSAppTransportSecurity");
        urlDict.SetBoolean("NSAllowsArbitraryLoads", true);
    }
#endif
}

        这边需要记一下other linker flages参数中-all_load这个参数,坑了我一天,因为米大师Demo中有这个参数,我也用上了,然后各种duplicate symbol错误,刚开始还以为是安全SDK的问题,因为接完安全SDK后就没有打iOS工程,导致我把米大师和安全SDK全删了,发现还有这个错误,对比了各种配置文件,才找到问题所在。

参考:

配置Xcode工程

PBXProject.AddFile Code Examples

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