如何使用Xcode制作imessage扩展包以便可以导入

时间:2017-10-02 12:00:59

标签: ios xcode unity5

我们使用Unity为Xcode生成一个项目,并希望利用iMessage扩展,但唯一的方法就是在Unity生成Xcode项目之后进行扩展,所以每次我们构建项目时我们应该重新设置iMessage扩展。

虽然我们已将iMessage扩展名设为文件夹并保存在磁盘上,以便每次生成Xcode项目时我们都必须

  1. 使用Xcode添加iMessage扩展功能。
  2. 将某些内容拖入Xcode,以使用预制的代码覆盖生成的代码。
  3. 这个程序很烦人,所以我们正在寻找其他方法,这很容易做到这一点。

    有没有办法做到这一点?感谢。

2 个答案:

答案 0 :(得分:1)

是的,你可以使用Unity xcode api 见https://bitbucket.org/Unity-Technologies/xcodeapi

基本上,您创建了一个构建后处理器,用于创建新目标并将贴纸资源添加到新生成的构建中。

using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using MightyEditor.iOS.Xcode;

public class BuildPostProcessor
{
    [PostProcessBuild(2000)]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
    {
        Debug.Log("------ buildTarget:" + buildTarget + " path:" + buildPath);

        if (buildTarget == BuildTarget.iOS)
        {
            string xcodeprojPath = buildPath + "/Unity-iPhone.xcodeproj";
            string pbxprojPath = xcodeprojPath + "/project.pbxproj";

            PBXProject pbxProject = new PBXProject();
            pbxProject.ReadFromFile(pbxprojPath);            

            AddStickers(pbxProject, buildPath, xcodeprojPath, pbxprojPath);

            pbxProject.WriteToFile(pbxprojPath);
        }
    }

    private static void AddStickers(PBXProject pbxProject, string buildPath,string xcodeprojPath,string pbxprojPath)
    {
        string appGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTargetName());
        DirectoryCopy("_Stickers", buildPath + "/Stickers", true);

        string stickersGuid = pbxProject.AddAppExtension(appGuid, "stickers app", "com.apple.product-type.app-extension.messages-sticker-pack", "Stickers/Info.plist");

        pbxProject.AddFile("Stickers/Stickers.xcassets", "Stickers/Stickers.xcassets");
        pbxProject.AddFileToResourcesForTarget(stickersGuid, "Stickers/Stickers.xcassets");

        pbxProject.AddBuildProperty(stickersGuid, "PRODUCT_BUNDLE_IDENTIFIER", "com.blABLA");
        pbxProject.AddBuildProperty(stickersGuid, "TARGETED_DEVICE_FAMILY", "1,2");
        pbxProject.AddBuildProperty(stickersGuid, "ASSETCATALOG_COMPILER_APPICON_NAME", "iMessage App Icon");
        pbxProject.AddBuildProperty(stickersGuid, "ARCHS", "armv7 arm64");
        pbxProject.SetBuildProperty(stickersGuid, "IPHONEOS_DEPLOYMENT_TARGET", "10.0");
        pbxProject.SetBuildProperty(stickersGuid, "DEVELOPMENT_TEAM", "TEAMid");

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

        // Get root
        PlistElementDict rootDict = plist.root;

        rootDict.values["CFBundleVersion"] = new PlistElementString(PlayerSettings.iOS.buildNumber);
        rootDict.values["CFBundleShortVersionString"] = new PlistElementString(PlayerSettings.bundleVersion);

        // Write to info.plist file
        File.WriteAllText(plistPath, plist.WriteToString());

        // This is quite yuck, but there isn't a way with Unity's PBX library to add a scheme and we need to add one for the Stickers target or else xcodebuild fails when we try to build it
        File.WriteAllText(xcodeprojPath + "/xcshareddata/xcschemes/Stickers.xcscheme", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Scheme LastUpgradeVersion = \"0800\" wasCreatedForAppExtension = \"YES\" version = \"2.0\"><BuildAction parallelizeBuildables = \"YES\" buildImplicitDependencies = \"YES\"><BuildActionEntries><BuildActionEntry buildForTesting = \"YES\" buildForRunning = \"YES\" buildForProfiling = \"YES\" buildForArchiving = \"YES\" buildForAnalyzing = \"YES\"><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + stickersGuid + "\" BuildableName = \"Stickers.appex\" BlueprintName = \"Stickers\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></BuildActionEntry></BuildActionEntries></BuildAction><TestAction buildConfiguration = \"Debug\" selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\" selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\" shouldUseLaunchSchemeArgsEnv = \"YES\"><Testables></Testables><MacroExpansion><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + appGuid + "\" BuildableName = \"Unity-Target-New.app\" BlueprintName = \"Unity-iPhone\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></MacroExpansion><AdditionalOptions></AdditionalOptions></TestAction><LaunchAction buildConfiguration = \"Debug\" selectedDebuggerIdentifier = \"\" selectedLauncherIdentifier = \"Xcode.IDEFoundation.Launcher.PosixSpawn\" launchStyle = \"0\" useCustomWorkingDirectory = \"NO\" ignoresPersistentStateOnLaunch = \"NO\" debugDocumentVersioning = \"YES\" debugServiceExtension = \"internal\" allowLocationSimulation = \"YES\" launchAutomaticallySubstyle = \"2\"><AdditionalOptions></AdditionalOptions></LaunchAction><ProfileAction buildConfiguration = \"Release\" shouldUseLaunchSchemeArgsEnv = \"YES\" savedToolIdentifier = \"\" useCustomWorkingDirectory = \"NO\" debugDocumentVersioning = \"YES\" launchAutomaticallySubstyle = \"2\"><MacroExpansion><BuildableReference BuildableIdentifier = \"primary\" BlueprintIdentifier = \"" + stickersGuid + "\" BuildableName = \"Stickers.appex\" BlueprintName = \"Stickers\" ReferencedContainer = \"container:Unity-iPhone.xcodeproj\"></BuildableReference></MacroExpansion></ProfileAction><AnalyzeAction buildConfiguration = \"Debug\"></AnalyzeAction><ArchiveAction buildConfiguration = \"Release\" revealArchiveInOrganizer = \"YES\"></ArchiveAction></Scheme>");
    }

    private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs, bool overrideDest = false)
    {
        // Get the subdirectories for the specified directory.
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);

        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException("Source directory does not exist or could not be found: " + sourceDirName);
        }

        DirectoryInfo[] dirs = dir.GetDirectories();
        // If the destination directory doesn't exist, create it.
        if (!Directory.Exists (destDirName)) {
            Directory.CreateDirectory (destDirName);
        }
        else if(overrideDest)
        {
            Directory.Delete (destDirName, true);
            Directory.CreateDirectory (destDirName);
        }

        // Get the files in the directory and copy them to the new location.
        FileInfo[] files = dir.GetFiles();
        foreach (FileInfo file in files)
        {
            string temppath = Path.Combine(destDirName, file.Name);
            file.CopyTo(temppath, overrideDest);
        }

        // If copying subdirectories, copy them and their contents to new location.
        if (copySubDirs)
        {
            foreach (DirectoryInfo subdir in dirs)
            {
                string temppath = Path.Combine(destDirName, subdir.Name);
                DirectoryCopy(subdir.FullName, temppath, copySubDirs, overrideDest);
            }
        }
    }
}

答案 1 :(得分:0)

我在团结 2018.4...

这是我为将贴纸嵌入过程自动化到 Unity 后期处理构建中所做的工作。

  • 将贴纸资产复制到一个文件夹中,相对于统一项目资产路径
  • 对我来说,该文件夹包含 Stickers.xcassets 和 Info.plist。 (之前从 XCode 生成)
  • 将此后期处理类添加到您的项目中
//
// Copyright (c) 2020 Cizcuz (ID)
// http://www.twitter.com/cizcuz
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

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

public class PostProcess
{
    [PostProcessBuild(100)]
    public static void OnPostProcessBuild(BuildTarget target, string buildPath)
    {
        if (target == BuildTarget.iOS)
        {
            // Add the sticker extension to current pbx
            string PBXPath = PBXProject.GetPBXProjectPath(buildPath);
            PBXProject pbxProject = new PBXProject();
            pbxProject.ReadFromFile(PBXPath);            
            AddStickers(buildPath,pbxProject);
            pbxProject.WriteToFile(PBXPath);
            
            // After this, still need to fix app extension type 
            // I cant find any way to insert proper product Type from unity PBXProject class
            string output = File.ReadAllText(PBXPath);
            File.WriteAllText( PBXPath, output.Replace( "productType = \"com.apple.product-type.app-extension\"",
                                                        "productType = \"com.apple.product-type.app-extension.messages-sticker-pack\"" ) ); 
        }
    }
    
    private static void AddStickers(string buildPath, PBXProject pbxProject)
    {
        const string StickerPackRelPath = "";   // INSERT relative path from <path to project folder>/Assets to your Sticker Asset i.e.: "/../../StickerAssets"
        string stickerFolder = Path.GetFullPath( Application.dataPath + StickerPackRelPath );

        if( Directory.Exists(stickerFolder) ) {
            string PBXPath = PBXProject.GetPBXProjectPath(buildPath);
            string appGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTargetName());

            // Copy folder
            FileUtil.CopyFileOrDirectory(stickerFolder, buildPath + "/Stickers");

            //
            string stickersGuid = pbxProject.AddAppExtension(appGuid, "My Stickers", "com.yourcompany.yourgame.stickers", "Stickers/Info.plist");
            string stickerAssetGuid = pbxProject.AddFile("Stickers/Stickers.xcassets", "Stickers/Stickers.xcassets");
            pbxProject.AddFile("Stickers/Info.plist","Stickers/Info.plist");
            pbxProject.AddFileToBuild(stickersGuid, stickerAssetGuid);

            string debugConfig              = pbxProject.BuildConfigByName( stickersGuid, "Debug");
            string releaseConfig            = pbxProject.BuildConfigByName( stickersGuid, "Release");
            string releaseProfilingConfig   = pbxProject.BuildConfigByName( stickersGuid, "ReleaseForProfiling");
            string releaseRunningConfig     = pbxProject.BuildConfigByName( stickersGuid, "ReleaseForRunning");
            List<string> allRelease = new List<string>() {
                releaseConfig,
                releaseProfilingConfig,
                releaseRunningConfig
            };

            //
            // This is just to match build properties normally exist when you 
            // create the Sticker AppExtension Target by XCode, not really sure if all of this is essential
            // 
            pbxProject.AddBuildProperty( stickersGuid, "PRODUCT_BUNDLE_IDENTIFIER", "com.yourcompany.yourgame.stickers");
            pbxProject.AddBuildProperty( stickersGuid, "TARGETED_DEVICE_FAMILY", "1,2");        // For me is iphone & ipad
            pbxProject.AddBuildProperty( stickersGuid, "IPHONEOS_DEPLOYMENT_TARGET", "10.2");   // Sticker project supported in iOS 10
            pbxProject.AddBuildProperty( stickersGuid, "COPY_PHASE_STRIP", "NO" ); 
            pbxProject.AddBuildProperty( stickersGuid, "DEVELOPMENT_TEAM", "");                 // INSERT #YOURTEAMID# HERE
            pbxProject.AddBuildProperty( stickersGuid, "ALWAYS_SEARCH_USER_PATHS", "NO");
            pbxProject.AddBuildProperty( stickersGuid, "CODE_SIGN_IDENTITY", "iPhone Developer" );
            pbxProject.AddBuildProperty( stickersGuid, "CURRENT_PROJECT_VERSION", PlayerSettings.iOS.buildNumber );
            pbxProject.AddBuildProperty( stickersGuid, "MARKETING_VERSION", PlayerSettings.bundleVersion );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_NO_COMMON_BLOCKS", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_C_LANGUAGE_STANDARD", "gnu11" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_WARN_64_TO_32_BIT_CONVERSION" ,"YES" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_NO_COMMON_BLOCKS", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_WARN_ABOUT_RETURN_TYPE", "YES_ERROR" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_WARN_UNDECLARED_SELECTOR", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_WARN_UNINITIALIZED_AUTOS", "YES_AGGRESSIVE" );
            pbxProject.AddBuildProperty( stickersGuid, "GCC_WARN_UNUSED_FUNCTION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_CXX_LANGUAGE_STANDARD", "gnu++14" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_CXX_LIBRARY", "libc++" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_ENABLE_MODULES", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_ENABLE_OBJC_ARC", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_ENABLE_OBJC_WEAK", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "ENABLE_STRICT_OBJC_MSGSEND", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_BOOL_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_COMMA", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_CONSTANT_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_DIRECT_OBJC_ISA_USAGE", "YES_ERROR" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_DOCUMENTATION_COMMENTS", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_EMPTY_BODY", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_ENUM_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_INFINITE_RECURSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_INT_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_NON_LITERAL_NULL_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_OBJC_LITERAL_CONVERSION", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_OBJC_ROOT_CLASS", "YES_ERROR" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_RANGE_LOOP_ANALYSIS", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_STRICT_PROTOTYPES", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_SUSPICIOUS_MOVE", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_UNGUARDED_AVAILABILITY", "YES_AGGRESSIVE" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN_UNREACHABLE_CODE", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_WARN__DUPLICATE_METHOD_MATCH", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_ANALYZER_NONNULL", "YES" );
            pbxProject.AddBuildProperty( stickersGuid, "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION", "YES_AGGRESSIVE" );           
            pbxProject.AddBuildProperty( stickersGuid, "MTL_FAST_MATH", "YES" );
            pbxProject.AddBuildPropertyForConfig( debugConfig, "ONLY_ACTIVE_ARCH", "YES" );
            pbxProject.AddBuildPropertyForConfig( debugConfig, "GCC_OPTIMIZATION_LEVEL", "0" );
            pbxProject.AddBuildPropertyForConfig( debugConfig, "DEBUG_INFORMATION_FORMAT", "dwarf" ); 
            pbxProject.AddBuildPropertyForConfig( debugConfig, "ENABLE_TESTABILITY", "YES" );
            pbxProject.AddBuildPropertyForConfig( debugConfig, "MTL_ENABLE_DEBUG_INFO", "YES" );
            pbxProject.AddBuildPropertyForConfig( allRelease, "ENABLE_NS_ASSERTIONS", "NO" );
            pbxProject.AddBuildPropertyForConfig( allRelease, "MTL_ENABLE_DEBUG_INFO", "NO" );
            pbxProject.AddBuildPropertyForConfig( allRelease, "VALIDATE_PRODUCT", "YES" );

            // Sets property for asset catalog
            pbxProject.AddBuildProperty(stickersGuid, "ASSETCATALOG_COMPILER_APPICON_NAME", "iMessage App Icon");

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

            // Get root
            PlistElementDict rootDict = plist.root;
            rootDict.values["CFBundleVersion"] = new PlistElementString(PlayerSettings.iOS.buildNumber);
            rootDict.values["CFBundleShortVersionString"] = new PlistElementString(PlayerSettings.bundleVersion);

            // Update info.plist file
            File.WriteAllText(plistPath, plist.WriteToString());
        }
    }
}