[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

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