Showing posts with label Xcode. Show all posts
Showing posts with label Xcode. Show all posts

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.

Tuesday, October 11, 2011

Moving iPhone Developer Credentials from one Mac to another

Update: So apparently in Xcode 4 (at least) there is an official way to do this... outlined here

I recently reinstalled OSX on my Mac and upgraded to Lion. Of course I forgot to transfer my iPhone developer credentials before I did it. I had to go back to the provisioning portal and setup my new certificate and get a new developer profile. While it wasn't a huge time waste I should have transferred my certificates and profile to save myself some time.

This is what I should have done.


  • Open Xcode

  • Window->Organizer
  • DEVELOPMENT -> Provisioning Profiles

  • Choose your Provisioning profile, right click and "Reveal in Finder"

  • Save the resulting file

  • Open Keychain Access

  • Export your private and public certificates to files and save them

  • Transfer all the file to your new system

  • Drag and drop Provisioning Profile into Xcode's Organiser on your new system

  • Import the certificates file you exported into Keychain Access on your new system



NOTE: There is a very annoying bug in Keychain Access that means you need to re-import your certificates at the command line. Attempting to you import you certificates using the Keychain Access GUI yields "An error has occurred. Unable to import an item. The contents of this item cannot be retrieved". This is just a blatant bug in Keychain Access you can import the files into Keychain Access at the command line with the following commands.

security import priv_key.p12 -k ~/Library/Keychains/login.keychain
security import pub_key.pem -k ~/Library/Keychains/login.keychain

Thursday, August 4, 2011

Xcode 3.2.6 and OSX Lion (10.7) - Make it install

Today I enthusiastically installed OSX Lion on my development system. I was probably stupidly naive to think it would be a straightforward upgrade.

Attempting to install Xcode 3.2.6, the version I currently prefer, it seemed to silently fail. I wasn't sure why. I did notice running the installation wizard; that at the point of selecting Installation Components the Xcode Tool Set component (Usually compulsory) was greyed out and marked as skip.



After some research, It seems support for Xcode 3.2.6 on Lion is somewhat neglected as Xcode 4.x is the future. Long story short I needed to use 3.2.6. It can be motivated to install on Lion.

After mounting the developer tools dmg you can open a terminal and issue the following commands to successfully install Xcode 3.2.6 on OSX Lion (10.7)

export COMMAND_LINE_INSTALL=1
open "/Volumes/Xcode and iOS SDK/Xcode and iOS SDK.mpkg"

Monday, June 20, 2011

Xcode: iPhone or iPad application code sign error

This morning on a re-imaged OSX machine I attempted to compile an ipad application and I was rewarded with the error below.

codesign error: code signing identity 'iphone developer' does not match any code-signing certificate in your keychain. once added to the keychain, touch a file or clean the project to continue.

I was puzzled. I'd already made a developer certificate request to Apple, had it signed and installed it in my Keychain Access, I'd also downloaded and installed the Apple Worldwide Developer Relations Certification Authority certificate. I'd installed the required development profile that matched my ipad device Unique Identifier, my personal developer certificate and the application I am developing but still, every time I hit build it gave me a code sign error. I didn't get it.

At some point it a suspicion formed. In my Keychain Access I noticed my certificates where installed in the System keychain. I'm not even sure why they got installed there, I don't think I did it explicitly.

I moved my certificates to the login keychain which I assume belongs to the logged in user on OSX (i.e. myself). Attempting to re-compile the source code of my ipad project yield a positive result. Moving the certificates to the login keychain seemed to work! So I post my small solution here today in the hope that somebody else might benefit.

Friday, December 24, 2010

Downloading files from the Apple Developer website using wget (for poor connections or scheduling)

Recently we had some issues downloading the latest iphone SDK. Firstly due to a crappy 3G broadband connection; we never seemed to be able to download the entire 3.5 Gigabyte file without a dropout. Unfortunately for us, Apple seem to have overlooked this possibility with their developer website and they do not offer the download using a more robust facility. Note to Apple. Ftp would be nice.

Secondly with several team members located in the same city but not on the same LAN we wanted to distribute the update to all members via our shared linux server. Unfortunately, this said server is getting a little long in the tooth now and being a 32 bit linux distribution it does not support files of the size that is the Xcode and IOS dmg. We were going to have to split the file into more managable chunks. What a pain.

The command line tool wget often yields answers to these kinds of problems so consequently it was our initial foray into finding a solution. Firstly it can provide an extra layer of robustness for downloading files, secondly it's very easy to schedule downloads via cron. For those of you wondering why this is a consideration - welcome to the reality of living in the internet 3rd world - Australia. With the typical internet plans in Australia, heavy internet users such as ourselves find it important to spread our download usage between peak periods (any time you're likely to be awake) and offpeak periods (any time you're likely to be sleeping) to maximise our bandwidth allocation.

Frustratingly, downloading the IOS SDK via wget is complicated by the need for any web client connecting to the Apple Developer website to have been authenticated. The Apple website is known to use cookies to authenticate web clients, and several recipes for extracting authetication credentials from browser cookies into a file and using then via the wget command line interface are well known - at least for Firefox.

The basic procedure for accessing content using wget from a site requiring authentication involves logging into the said site using a standard web browser, once authenticated via a login page one can set abou extracting the authentication cookie from the browser. The extracted cookie is then fed to wget which can use the cookie for permission to download the desired content.

Being on a Macintosh system we are by default provided with Safari. Not bothering to install Firefox on every system one uses, we figured it was easier just to stick with Safari. Luckily the same technique can be performed with Safari as with Firefox. The technique for Safari is not as well known as the Firefox technique, so we'll cover it here.

Safari stores its cookies on a per user basis within a user's home directory. Specifically cookies are stored in a simple XML file. Have a look in Library/Cookies/Cookies.plist. You can see all of Safari's cookies in there.

To get the required cookie into the Cookies.plist before we proceed, use Safari to login to the Apple Developer Website using your Apple ID credentials. Safari should now have the requisite cookie. Opening the Cookies.plist with a text editor to view the cookie; we're looking for the one called ADCDownloadAuth.

With wget expecting it's cookie information in the nescape cookie.txt file format we'd like a quick and simple way to convert from one format to the other. Luckily this is relatively easy to do on a Macintosh system. As the language Ruby is preinstalled on Tiger, Leopard and Snow Leopard systems we may as well leverage the language to do this job.

Install the plist Ruby library and run the short ruby script listing below to convert the file to Firefox's cookies.txt format.

$ sudo gem install plist
$ irb
>> require 'plist'
>> result = Plist::parse_xml("Library/Cookies/Cookies.plist")
>> File.open("cookies.txt", "w") {f result.each {r f.write("#{r["Domain"]}\tTRUE\t#{r["Path"]}\tFALSE\t#{r["Expires"].strftime("%s")}\t#{r["Name"]}\t#{r["Value"]}\n")}}

Now that we have our cookies.txt file we can download the file we would like. Note that the URL for the sdk was found by looking at Apple's Download website to see where the download link led.

Below is the wget command line used to download the Xcode and iPhone SDK. Note that the command line variables for wget tell it to pipe the downloaded file to split which breaks the file up to make our venerable Linux file and webserver happy (2GB file limit). We're splitting the download into 512mb chunks here.

To make sure the authetication works I needed to use the header flag and insert the cookie value at the command line. Looking at the cookie.txt file to again find the ADCDownloadAuth key and it's datavalue we place this data in exchange of the "XXX" marked command line below for this recipe to work.

wget -qO- -U firefox -ct 0 --timeout=60 --waitretry=60 --load-cookies cookies.txt -c http://adcdownload.apple.com/ios/ios_sdk_4.2__final/xcode_3.2.5_and_ios_sdk_4.2_final.dmg --header="Cookie: ADCDownloadAuth=XXX" | split --bytes=512m - xcode_3.2.5_and_ios_sdk_4.2_final.dmg


You should now see your download commence and with everything to plan you'll have your dmg ready to install. You can ftp to you Macintosh. Once aboard you can
cat part1 part2 part3 ... > combined.dmg

In order to restore the split components. Happy Developing with the latest SDK!