Thursday, December 8, 2011

Unity3D iPhone Player and JIRA Connect Integration

We've been using JIRA internally for our project management and bug tracking for a couple of years now and we've found it to be excellent. Recently Atlassian (the developers of JIRA) released a JIRA Connect library for the iPad/iPhone family.

If you are developing an iPad or iPhone application this library gives you application bug and error reporting, which integrates with JIRA for very little effort.

Using JIRA Connect with Unity3D iPhone together in order to provide a nice way of automatically delivering crash reports and user feedback to your Unity application. For Unity users targeting the iPad/iPhone this quick little boon works for us to. Here is how to do it.

At this point of this post I'm assuming you're familiar somewhat with JIRA and have a working JIRA instance, or are perhaps using the hosted JIRA solution offered by Atlassian (we much prefer to host our own - because we like control like that).

In your JIRA instance; enable the JIRA Connect plugin, the JIRA Connect user and get your API Key from the Administration panel.

Go and download the JIRA Connect source from here.

To get this integration working for Unity iPad/iPhone builds we're going to patch the Unity player source code that gets spat out
by Unity when you make a Unity iPad/iPhone build.

To have a starting position; make a Unity iPad/iPhone build now. Typically, if I have a project directory "ProjectName" I output my iPad/iPhone player build to "ProjectName_build". Generate this now.

Unpack the JIRA Connect source code you have downloaded.

At this point my directory looks like something like (I'm using OSX Lion)



leberkaese: chriskruger$ ls
atlassian-jiraconnect-ios-tip
ProjectName
ProjectName_build
leberkaese: chriskruger$



Open the Xcode project file in your ProjectName_build directory in Xcode. I am using Xcode 4 btw.

We are now going to make some changes to the project that Unity has spat out for us, in order to make use of JIRA Connect. We're basically following the instructions from here.

So the steps as I see them for Xcode 4.


  1. Add the JMCClasses directory to your Unity-iPhone/Classes group. Right click on the Classes group and choose to Add Files to Unity-iPhone. Browse to the atlassian-jiraconnect-ios-tip/JIRAConnect and choose the JMCClasses directory. Select to "make groups for any added folders" and press Add

  2. Select the Unity-iPhone project root in the project explorer, select the Unity-iPhone target and the Summary tab. Scroll down to the Linked Frameworks and Libraries. Add the following libraries for linking, CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics, AVFoundation, CoreLocation, libsqlite





Choose the AppController.mm file in the Classes directory. We're going to edit this to integrate JIRA Connect.

Near the top of AppController.mm we'll add the import statement



Now move down further in the AppController.mm file and find the ApplicationDidFinishLaunching method. We're going to add the follow code in order to activate the library code when our application starts. Note that you'll need to alter this code from my example code in order for JIRA Connect to work with your JIRA instance. Specifically you'll need you JIRA instance's web address and it's API key. You might also want to change the configurations options to suit.

When done applicationDidFinishLaunching will look something like this.


- (void) applicationDidFinishLaunching:(UIApplication*)application
{
printf_console("-> applicationDidFinishLaunching()\n");

JMCOptions* options = [JMCOptions optionsWithUrl:@"https://project.jira.com/"
project:@"PK"
apiKey:@"XXXXXXX-XXXXX-XXXX-XXX-XXXXXXXXXX"
photos:NO
voice:NO
location:NO
crashreporting:YES
customFields:nil];

[[JMC instance] configureWithOptions:options];


if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

[self startUnity:application];
}


We were particularly interested in the crash reporting, so for the most part that's all we setup.

So if you've done this. Check it all compiles and your Unity application still runs.

If it all works we're now in a good position to generate some patches that we'll use to automatically update our Unity build from each time we make a build in Unity.

Create another build outputting it to somewhere like ProjectName_build_vanilla.

Create a some patches using diff.


diff -ru ProjectName_build_vanilla/Unity-iPhone.xcodeproj/project.pbxproj ProjectName_build/Unity-iPhone.xcodeproj/project.pbxproj > xcode.patch

diff -ru ProjectName_build_vanilla/Classes/AppController.mm ProjectName_build/Classes/AppController.mm > AppController.patch


Move these patches to ProjectName/Assets/Editor where they can easily be accessed during the Unity build process.

Now we're going to modify the Unity build post process to apply our patches every time we make a build. So, if it doesn't already exist we will create a file called ProjectName/Assets/Editor/PostprocessBuildPlayer. This file is the standard way Unity permits modifications to the build pipeline.

The contents of our PostprocessBuildPlayer file looks like.



#!/bin/bash

DIR=${0%/*}
INSTALLPATH=${1}
TARGET=${2}
OPT=${3}
COMPANY=${4}
PRODUCT=${5}
LOG=postprocess.txt

echo "Postprocess Start" > ${LOG}
echo "TARGET = ${TARGET}, PRODUCT = ${PRODUCT}" >> ${LOG}
echo "INSTALLPATH = ${INSTALLPATH}" >> ${LOG}

if [ $PRODUCT == "ProductName" ]
then

if [ "${TARGET}" == "iPhone" ]
then
echo "Applying patches for AppController and Xcode" >> ${LOG}
(cd ${INSTALLPATH}; patch -N -p1 < ${DIR}/AppController.patch)
(cd ${INSTALLPATH}; patch -N -p1 < ${DIR}/xcode.patch)
fi

fi


It is just a quick and dirty bash script that applies our patches to the Unity iPad/iPhone player build every time we do a build. Once you've got this working you're now got JIRA Connect integrated into your Unity application.

If you have trouble getting the JIRA Connect library working, define "DEBUG" in the build and the JIRA Connect library will log more information (to the Xcode console) about that it is trying to do when the application starts. This will help you work out what is wrong.

Hope this works for you and please do lets us know if this guide needs updating/error correcting.