How can you add items to the Xcode project targets Info.plist using the XcodeAPI?

Is this possible with the XcodeAPI?

I need to add an API key and some boolean values to the generated xcode projects Info.plist. I don’t see any examples on how to do that.

Perhaps it’s outside the scope of the XcodeAPI? Any suggestions on how to do this using C# in a post build process function?

sim

1 Like

It’s not Unity Cloud Build Specific, but as I wanted to make a tutorial already for a while, I’ll post it here. This is useful when you want to edit the Info.plist of an Xcode project built by Unity when building for iOS. This can be used for example to change the values of Version (CFBundleShortVersionString) and Build (CFBundleVersion) in an Xcode project from within Unity, as a build post-process.

Step-by-step guide

  • Create/Have a Unity project
  • Create a folder inside Assets called Editor
  • Download the Xcode Manipulation API files from https://bitbucket.org/Unity-Technologies/xcodeapi/src/ and place them inside a sub-folder inside Assets > Editor such as Assets > Editor > xcodeapi
  • You can now create a script such as the one below to alter CFBundleVersion in Xcode plist
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.Collections;
using UnityEditor.iOS.Xcode;
using System.IO;

public class ChangeIOSBuildNumber {

    [PostProcessBuild]
    public static void ChangeXcodePlist(BuildTarget buildTarget, string pathToBuiltProject) {

        if (buildTarget == BuildTarget.iOS) {
        
            // Get plist
            string plistPath = pathToBuiltProject + "/Info.plist";
            PlistDocument plist = new PlistDocument();
            plist.ReadFromString(File.ReadAllText(plistPath));
        
            // Get root
            PlistElementDict rootDict = plist.root;
        
            // Change value of CFBundleVersion in Xcode plist
            var buildKey = "CFBundleVersion";
            rootDict.SetString(buildKey,"2.3.4");
        
            // Write to file
            File.WriteAllText(plistPath, plist.WriteToString());
        }
    }
}

Which sets the CFBundleVersion in your Info.plist in a post process step to “2.3.4” (works also in Unity Cloud Build in all Tiers).

I hope this makes sense and helps. Please let me know how it goes! :slight_smile:

24 Likes

Thank you! That worked perfectly.

We are using it for background location and fetch stuff in a native plugin.

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

public class MyPluginPostProcessBuild
{
    [PostProcessBuild]
    public static void ChangeXcodePlist(BuildTarget buildTarget, string pathToBuiltProject)
    {
        if ( buildTarget == BuildTarget.iOS )
        {
            // Get plist
            string plistPath = pathToBuiltProject + "/Info.plist";
            PlistDocument plist = new PlistDocument();
            plist.ReadFromString(File.ReadAllText(plistPath));
           
            // Get root
            PlistElementDict rootDict = plist.root;
           
            // background location useage key (new in iOS 8)
            rootDict.SetString("NSLocationAlwaysUsageDescription", "Uses background location");
           
            // background modes
            PlistElementArray bgModes = rootDict.CreateArray("UIBackgroundModes");
            bgModes.AddString("location");
            bgModes.AddString("fetch");
           
            // Write to file
            File.WriteAllText(plistPath, plist.WriteToString());
        }
    }
}

Need some clarification.
Do I need to download the XcodeAPI and include it in my project if we are already using Unity 5 (5.0.2p3)? It already seems to be included, though I’m guessing it’s not the newest version.

Would this work with 4.6.5? Would that require including the XcodeAPI like you instructed?

Am I correct in assuming this would also work with Unity Cloud Build?

1 Like

Yes, there is also a XCode API for 4.6 and 5. If you use source code of the repro you can alter the framework if necessary and it can be optimised. Yes, it also works with Unity Cloud Build. :sunglasses:

2 Likes

Thanks, i used the sample code shown above and was able to modify the Info.plist to add what i wanted.
The major issue was only understanding what’s the name of the element i need to be added :slight_smile:

In my book, a good API is one that can be used straight away without reading through docs, etc… (naming conventions are good and it’s hard to find your way around).

So, good work guys, Thanks !!! :slight_smile:

1 Like

Found the answer a bit confusing until I realized I didn’t need to actually download the API in Unity version 5.1.1

3 Likes

Yes, the guide was made for 4.6, in 5.x you don’t need to add the XCode API into your project.

1 Like

it works great.
I already made a hack, that I set the version to 1.0.0#1, and then parse it in the post-build-processor.

Is there a way to make cloudbuild auto-increment everytime it builds?

Sweet!
You can use the Build Manifest to determine the build number! I added a sample about the Build Manifest here. :slight_smile:

hey David, some useful posts again. many thanks (you answered my iOS question too!)…

can I ask two things.

  1. is there a similar routine for Android’s manifest.xml ?
  2. Alternatively, is there anyway to just include hard coded plist or manifest files for iOS and Android respectively ?..

I’m extending both to include a custom url scheme e.g. mygamename://

  • But if you need something more fancy, you will have to write some code in a post process script. The xml format is easy to modify, compared to the xcodeproj, so you don’t really need a “manipulation api" if that makes sense?
  • You can have multiple manifests in your project and Unity merges them I think. That’s probably not possible on iOS, but there you have the XCode manipulation API :slight_smile:

thanks

just to confirm…

so for android we just add a manifest to the Assets/Plugins/Android folder

and RTM for Xcode manipulation API ! :wink:

I’m getting lots of errors in PBXProject.cs, like:

Error CS0234: The type or namespace name CombinePaths' does not exist in the namespace UnityEditor.Utils’. Are you missing an assembly reference? (CS0234) (Assembly-CSharp-Editor)

In Unity 4.6.8p3

Any ideas?

Hi,

I’m trying to add URL Schemes to my Info.plist.

While adding frameworks is working just fine, accessing the root dictionary of my plist doesn’t seem to work as expected:

// Add url schema to plist file
string plistPath = path + "/Info.plist";
PlistDocument plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(plistPath));
           
// Get root
PlistElementDict rootDict = plist.root;

When I step debug the code, Mono Develop shows me

FYI, the plistPath is correct.

Am I doing anything wrong?

@urfx yes
@peterworth make sure you update the XCode Manipulation API to the correct version for 4.6
@chrs1885 What’s the plistPath pointing to? I assume path is the path handed over from the post process method?

Which is the correct version for 4.6?

This one should be all right for 4.6, in 5.0 we bundle it already with Unity. Details are in the readme: https://bitbucket.org/Unity-Technologies/xcodeapi/src

That’s the version (latest commit) that gives me errors in Unity 4.6. Same ones that @peterworth mentioned: Namespace CombinePaths does not exist in namespace UnityEditor.Utils, etc. That’s why I thought when you mentioned right version you meant a commit version, I just assumed the latest was only written for Unity 5.

The latest commit should work properly. Did you add the source directly into Unity? That might be broken and might not work without modification I fear, best is to build the dll separately and include the resulting dll into the project. I’ll forward it to the devs, maybe they can fix it for the next release of the public API.

In the meantime if you need precompiled dlls with a working Unity Cloud Build project check out the examples in the UCB Demos for Unity 4 and Unity 5. It’s the Library Demo project which includes the dlls in the Editor folder of the subfolder project.

Yes! :slight_smile: