[Unity]配置Xcode工程(2)--添加Capability

        之前已经写过一篇关于XCode配置的,但那篇其实还有一个小bug,就是开启不了有些Capability,需要自己手动开启,这其实很繁琐,需要复制粘贴文本等。

        刚开始怀疑是不是Unity版本的问题,因为用的是Unity官方自带的API来添加Capability。之前的Unity版本是2017.4.7f1,最近项目升级了Unity版本,现在是2017.4.22f1版本,但测试了,还是开启不了有些Capability。

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

        注释掉的代码测试过,开启不了PushNotifications,下面的2个能给开启。但也有问题,看下图:

        也用过ProjectCapabilityManager来尝试开启Capability,发现没有用,倒是能修复BackgroudModes的问题。网上找了一堆文章,发现都没有好的解决方案。最后不甘心的去官网下载了源码来看,官网地址:https://bitbucket.org/Unity-Technologies/xcodeapi/src。最后终于解决一键生成XCode工程的问题,虽然还剩下一个问题,这估计不好解决

        看了ProjectCapabilityManager源码后,大致清楚开启Capability需要修改3个地方,一个是project.pbxproj,一个是info.plist,一个则是entitlements。

        举个例子BackgroudModes的问题,其实只要修改info.plist,就可以开启。代码如下:

        /// <summary>
        /// 处理Plist工程
        /// </summary>
        /// <param name="project"></param>
        /// <param name="plistPath"></param>
        private static void GeneratePlistFile(PlistElementDict rootDict, string plistPath)
        {
            PlistElementArray urlArray = null;
            //Add BackgroundModes
            if (!rootDict.values.ContainsKey("UIBackgroundModes"))
                urlArray = rootDict.CreateArray("UIBackgroundModes");
            else
                urlArray = rootDict.values["UIBackgroundModes"].AsArray();
            urlArray.values.Clear();
            urlArray.AddString("remote-notification");
        }

        加不加这句代码都没问题,已测试:

        project.AddCapability(target, PBXCapabilityType.BackgroundModes);

        entitlements的用法则是动态生成一个entitlements文件,举个例子,添加KeychainSharing:

        string key_KeychainSharing = "keychain-access-groups";
        var arr = (tempEntitlements.root[key_KeychainSharing] = new PlistElementArray()) as PlistElementArray;

        arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.lycqsh"));
        arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.wsj.keystoregroup"));

        最重要的是entitlements的路径不要写错,是相对路径,我之前写成绝对路径,找这个问题,找了半天,这个路径也是有问题的,要去掉最前面的/,路径应该Unity-iPhone/test.entitlements或者test.entitlements

        最终项目使用的代码:

    private static void AddCapability(PBXProject project, string pathToBuiltProject)
    {
        string target = project.TargetGuidByName(PBXProject.GetUnityTargetName());

        // Add BackgroundModes And Need to modify info.plist
        project.AddCapability(target, PBXCapabilityType.BackgroundModes);

        project.AddCapability(target, PBXCapabilityType.InAppPurchase);

        // Need Create entitlements
        string relativeEntitlementFilePath = "Unity-iPhone/xxxx.entitlements";
        string absoluteEntitlementFilePath = pathToBuiltProject + "/" + relativeEntitlementFilePath;

        PlistDocument tempEntitlements = new PlistDocument();

        string key_KeychainSharing = "keychain-access-groups";
        var arr = (tempEntitlements.root[key_KeychainSharing] = new PlistElementArray()) as PlistElementArray;

        arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.xxxx"));
        arr.values.Add(new PlistElementString("$(AppIdentifierPrefix)com.tencent.wsj.keystoregroup"));

        string key_PushNotifications = "aps-environment";
        tempEntitlements.root[key_PushNotifications] = new PlistElementString("production");

        project.AddCapability(target, PBXCapabilityType.PushNotifications, relativeEntitlementFilePath);
        project.AddCapability(target, PBXCapabilityType.KeychainSharing, relativeEntitlementFilePath);

        string projPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
        File.WriteAllText(projPath, project.WriteToString());
        tempEntitlements.WriteToFile(absoluteEntitlementFilePath);

        ModifyEntitlementFile(absoluteEntitlementFilePath);
    }

    private static void ModifyEntitlementFile(string absoluteEntitlementFilePath)
    {
        if (!File.Exists(absoluteEntitlementFilePath)) return;

        try
        {
            StreamReader reader = new StreamReader(absoluteEntitlementFilePath);
            var content = reader.ReadToEnd().Trim();
            reader.Close();

            var needFindString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            var changeString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
            Debug.Log("Before: " + content);
            content = content.Replace(needFindString, changeString);
            Debug.Log("After: " + content);
            StreamWriter writer = new StreamWriter(new FileStream(absoluteEntitlementFilePath, FileMode.Create));
            writer.WriteLine(content);
            writer.Flush();
            writer.Close();
        }
        catch (Exception e)
        {
            Debug.Log("ModifyEntitlementFile - Failed: " + e.Message);
        }
    }

        这里还有一个问题。就是PushNotifications的问题,查到了这好像是官方Unity5.6版本就有的问题,会导致如下的结果:

        再手动关闭和开启PushNotifications,会发现其他的也生效了,比如KeychainSharing:

        这一步操作,通过SVN比较发现变化了2个文件,上面代码中有一个接口(ModifyEntitlementFile)就是按照这种格式进行修改,发现没有用,估计是另一个文件产生作用,但因为打开是乱码,非常不好处理。

        虽然没有达到预期的效果,但也不错,省去了拷贝字符串和开启其他Capability的工作,也是一种简化。希望有大神知道还可以再怎么优化。

ProjectCapabilityManager核心代码:

        /// <summary>
        /// Creates a new instance of ProjectCapabilityManager. The returned 
        /// instance assumes ownership of the referenced pbxproj project file, 
        /// the entitlements file and project Info.plist files until the last 
        /// WriteToFile() call.
        /// </summary>
        /// <param name="pbxProjectPath">Path to the pbxproj file.</param>
        /// <param name="entitlementFilePath">Path to the entitlements file.</param>
        /// <param name="targetName">The name of the target to add entitlements for.</param>
        public ProjectCapabilityManager(string pbxProjectPath, string entitlementFilePath, string targetName)
        {
            m_BuildPath = Directory.GetParent(Path.GetDirectoryName(pbxProjectPath)).FullName;

            m_EntitlementFilePath = entitlementFilePath;
            m_PBXProjectPath = pbxProjectPath;
            project = new PBXProject();
            project.ReadFromString(File.ReadAllText(m_PBXProjectPath));
            m_TargetGuid = project.TargetGuidByName(targetName);
        }

        /// <summary>
        /// Writes the modifications to the project file, entitlements file and 
        /// the Info.plist file. Any external changes to these files after
        /// the ProjectCapabilityManager instance has been created and before
        /// the call to WriteToFile() will be overwritten.
        /// </summary>
        public void WriteToFile()
        {
            File.WriteAllText(m_PBXProjectPath, project.WriteToString());
            if (m_Entitlements != null)
                m_Entitlements.WriteToFile(PBXPath.Combine(m_BuildPath, m_EntitlementFilePath));
            if (m_InfoPlist != null)
                m_InfoPlist.WriteToFile(PBXPath.Combine(m_BuildPath, "Info.plist"));
        }

        private PlistDocument GetOrCreateEntitlementDoc()
        {
            if (m_Entitlements == null)
            {
                m_Entitlements = new PlistDocument();
                string[] entitlementsFiles = Directory.GetFiles(m_BuildPath, m_EntitlementFilePath);
                if (entitlementsFiles.Length > 0)
                {
                    m_Entitlements.ReadFromFile(entitlementsFiles[0]);
                }
                else
                {
                    m_Entitlements.Create();
                }
            }

            return m_Entitlements;
        }

        更新:最后一个问题也解决了,PushNotifications的字段不要写production,改为development,就解决了,昨天好像是SVN更新后,代码没有生效,就没有测试到改成development的结果,就误以为无效。

        string key_PushNotifications = "aps-environment";
        tempEntitlements.root[key_PushNotifications] = new PlistElementString("development");

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值