Create applications for the iPhone

I little while ago I figured out how to disable A2DP on my iPhone. It requires some changes to property lists, which requires additional tooling and makes it less accessible to less experienced users. If it was a Windows based device, then I would have created an application to make the changes. So why not do this for the iPhone?

The iPhone also has a compiler and SDK, but it uses the Objective C language and the Cocoa Touch framework. I am used to Windows programming for the last 15 years and I can tell you that iPhone development is completely different. I bought two books that got me started on Objective C and iPhone development:

Useful books

Title: Learn Objective-C on the Mac
Author: Mark Dalrymple & Scott Knaster
ISBN: 978-1-4302-1815-9

This book describes all the aspects of Objective-C. I think it is a little verbose and when you already familiar with object-oriented programming, then you probably want to skip a lot of details. I bought it, because I wanted to make sure I didn’t miss anything. Make sure you know Objective-C, because it’s not just a different C++ dialect.

Title: Beginning iPhone 3 Development: Exploring the iPhone SDK
Author: Dave Mark & Jeff LaMarche
ISBN: 978-1-4302-2459-4

I first downloaded a PDF version of this book via a torrent site and liked it so much that I decided to buy the (updated) paper version of the book. It describes iPhone development from the ground up, so it’s a good starter for iPhone development. It describes all the common controls and views that are used in iPhone applications. I am not a Cocoa expert, but I think that if you are then this book is not for you and you should look for a bit more in-depth book.

Get the right tools

Developing iPhone applications is only possible on Mac OS X, so you need an Apple computer. The standard development environment is called Xcode. You need to obtain an Apple Developer Connection membership to be able to download Xcode. The online membership is free, so make sure you register.

Once you have been registered, then you should download and install Xcode. Make sure you download the right version. If you are running OS X v10.5 you need to download Xcode v3.1.x. Snow Leopard users (OS X v10.6) need Xcode v3.2.x. This is all you need to develop software for Mac OS X, but it doesn’t contain the iPhone bits. Go to the iPhone section on the developer website and download the iPhone SDK.

This is all you need to create iPhone applications and test the applications in the iPhone simulator.

Test application on your own iPhone

Once you are ready developing and testing your application in the simulator, then you need to test it on your own iPhone. You can enroll in the iPhone Developer Program, which will cost you at least $99. If you plan to put the application in Apple’s AppStore, then you need to do this. There is no other way to get your application in the AppStore.

My application will not be approved in the AppStore, because it changes system settings and this is not allowed or possible from applications in the AppStore. My application will be distributed via Cydia (only for jailbroken iPhones). You don’t need to enroll for the iPhone Developer Program, but you need to make some modifications to your Xcode installation to make sure you can sign your application.

Obtain a code signing identity

You need to obtain a code signing identity. Fire up Keychain Access and choose Keychain Access – Certificate Assistant – Create a certificate… and use the following settings:

KeyChain

Note that you create a certificate with the name iPhone developer for code signing and you want to override defaults. Click continue and accept the defaults (although you can change your email address). Make sure the certificate is stored in your login keychain.

Patch Xcode v3.2 to deploy

There are two ways to patch Xcode to allow the application to be build. This first method is to patch Xcode v3.2 to be able to sign applications without a provisioning profile (note that this patch is only valid for v3.2!!!):

#!/bin/bash
cd /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Plug-ins/iPhoneOS\ Build\ System\ Support.xcplugin/Contents/MacOS/
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 count=300752
printf "\xc8\x2f\x00\x00" >> working
dd if=iPhoneOS\ Build\ System\ Support of=working bs=1 skip=300756 seek=300756
/bin/mv -n iPhoneOS\ Build\ System\ Support iPhoneOS\ Build\ System\ Support.original
/bin/mv working iPhoneOS\ Build\ System\ Support
chmod a+x iPhoneOS\ Build\ System\ Support

Another approach seems more elegant. Create a backup of /Developer/Platforms/iPhoneOS.platform/Info.plist and modify the Info.plist by replacing the two occurrences of XCiPhoneOSCodeSignContext with XCCodeSignContext.

Update project settings for code signing

Application signing Project – Edit Project Settings, select the Build tab and find the Code signing section. Select the Code Signing Identity. At the lower left part of the dialog, there is a popup menu and you should select the Add Build Setting Condition. Change the Any SDK to Device – iPhone OS 3.0. Select the iPhone developer certificate in the right column. If it doesn’t show up, then you didn’t create a proper certificate. The screen below shows the correct settings:

ProjectSettings

Sign your application

Applications on the iPhone need to be signed. You can use the official Apple signing method, which is pretty complicated, or use Saurik’s pseudo-signing method. In this tutorial I will use the pseudo-signing, because it’s easy and codesign checking has been hacked out of the jailbroken kernels anyway. There are two ways to pseudo-sign your application:

  1. Sign the applications on the iPhone itself. SSH to your iPhone and run apt-get install ldid. This will install the ldid utility in the /usr/bin directory. After you have copied your executable to the iPhone, then you need to run ldid -S <ProgramName>. This will sign the application, so you can run it.
  2. Sign the application on your Mac. Download ldid from TheBigBoss site to /usr/bin. Make sure that you can execute it (chmod 755 /usr/bin/ldid). Make sure you sign you applications at the end of the build process. In XCode select Project – New Build Phase – New Run Script Build Phase and use the following script:

    /usr/bin/ldid -S $TARGET_BUILD_DIR/$TARGET_NAME.app/$TARGET_NAME

If you forget to sign the application, then your application will crash immediately after starting.

Create a deployment package

I could have copied the text on Saurik’s website, but if you look here then you find everything that you need to create packages to deploy you application. After transferring the package to your iPhone, then you can install it using dpkg -i package.deb. You need to refresh your springboard to make sure the application is shown on screen. I use gUICache (available through Cydia) to refresh. Cydia refreshes automatically, after you (un)install a package.

Submit the application to a repository

When your application is ready, then you probably want to release it. You need to host the application via a repository, such as TheBigBoss.org. This repository is available in most Cydia configurations, so you are sure that users with a jailbroken iPhone can find your application. You need to have a Debian compliant package and need to fill in a form. The application will be hosted in the repository within 24 hours.

Resources

Bluetooth profile selector [jailbreak]

A little while back I described how to disable A2DP on your iPhone. It required manual modification of some files on the iPhone, which is not for the faint of heart. Now, I have created an application that allows you to change the Bluetooth profiles on a per-device basis. It works very easy.

Bluetooth device selectionBluetooth profilesAbout BTPS

Go to Cydia and look for the Bluetooth Profile Selector application. It is hosted with the BigBoss repository that is installed with Cydia by default. After installation you should see a red box with a Bluetooth icon inside of it.

The application shows all Bluetooth devices that have been detected. Just tap on one of the devices and the next screen is displayed that contains all the profiles that the iPhone can use on that device. The default setting enables all profiles, but you can choose which profiles that you want to enable. When you’re finished, just press the home button and the settings will be applied. During this process the Bluetooth server is restarted, so you’ll lose any active Bluetooth connections for a short while.

You can also download the package here. Put it on your iPhone and use SSH to run dpkg -i BTPS.deb to install it.

UPDATE: Apple has changed something in v4.3.1 and the profile selector cannot be used since then. Unfortunately, I don’t have an iPhone with v4.3.1, so I cannot test it. There has been some people that claim that they can fix it, so you can download the code here.

I received several requests from people if they could donate. You can donate via Paypal if you like:


Why I decided to jailbreak my iPhone

After owning the iPhone for a while, I was fed up with the closed nature of the device. I wanted to disable A2DP and found out that there was no way to do it. I decided to jailbreak the device to take a look about how to do this and found out that there are numerous other advantages as well:

  • The iPhone defaults to output audio on an A2DP device, when it is in the neighborhood. I want to always use the dock connector, but you need to modify your iPhone settings to do this.
  • Some Microsoft Exchange configurations are configured so your iPhone requires an access code at least once per hour. I use my iPhone often, so this was quite annoying. I installed Exchange Unlock to disable this functionality.
  • Access toggles easily using SBSettings application (available through Cydia) to enable some hidden features of the iPhone (i.e. numerical battery level). You can also access some frequently used toggles (WIFI, BlueTooth, …) much easier or show a list of running applications.
  • You can run applications in the background with the Backgrounder application (available through Cydia). This is especially great when using navigation products that are normally disabled when you are receiving or placing a phone call. Make sure you terminate the application when you really don’t need it anymore to prevent the application from draining the battery.
  • The default battery indication is quite lousy, but you can enable a numerical display. You can enable the SBShowBatteryLevel key in /var/mobile/Library/Preferences/com.apple.springboard.plist file or use a third party tool like SBSettings (available through Cydia). This application also allows to perform some other neat tricks, so make sure you take a look at it.
  • Install IPA files from other sources then the iTunes Store. Install AppSync for OS 3.0 on your iPhone (available through Cydia via Hackulo.us repository). Drag the IPA files into iTunes and you can sync them just like normal applications. The only difference is that you’re not updated about updates of course.
  • Access your phone using SSH, so you get access to the entire filesystem and are able to execute any command on your iPhone.
  • There are numerous other reasons why you want to jailbreak your iPhone. Some people like Winterboard to change the appearance of the phone. I like the default style, so I decided to stick with the normal springboard.

Are there any disadvantages? Yes, there are (unfortunately):

  • Whenever you upgrade your iPhone’s firmware, then you lost your jailbreak and need to start over again. This isn’t a major issue, because iPhone updates aren’t released very often. Always make sure you check if you can jailbreak the new version before you perform the upgrade.
  • Some applications can destabilize your iPhone. I only install applications that I really need and test them thorough. The applications listed above have never affected the stability and battery life in any way. You only need to be careful with Backgrounder, because you can easily leave an application in the background without knowing.

Howto disable A2DP on the iPhone

UPDATE [October 4, 2009]: I have created a utility that prevents the manual labour and can be installed via Cydia.

UPDATE [August 20, 2009]: The previous post described a method that didn’t work well. Shawn Porter pointed out the problem, so I have updated the post and now it works fine.

I have an iPhone 3G and use it in my car as a music player. I have installed an GROM audio adapter for the iPhone, so I can connect it to my Mazda 6 car stereo. The GROM adapter even allows to use the controls on the steering wheel. Everything worked just fine, until iPhone OS 3.0 came along.

iPhone OS 3.0 includes support for A2DP, which is capable of stream audio via BlueTooth to another device. Unfortunately, there is no way to disable A2DP and it will always select the A2DP source when it is available. You can switch back to the dock connector, but you need to do this each time you start your car.

Apple should make an option to select which BlueTooth profiles should be enabled for a certain connection, but this is not possible with the current firmware. I decided to jailbreak my iPhone and try to find a solution.

The interesting directory is /var/mobile/Library/Preferences, where the iPhone stores the BlueTooth settings. These settings are stored in the PLIST format, so you need a PLIST editor (Mac or PC) or you need to convert them by hand. Transfer the com.apple.MobileBluetooth.services.plist to your computer (refer to Simon’s blog to find out how to do this). You can also use iFile to edit the file on your iPhone directly (thanks to Richard van den Berg for pointing it out).

Open the com.apple.MobileBluetooth.services.plist in your PLIST editor and make sure you edit the A2DPService section and store the devices you don’t want to use A2DP in the UnauthorizeList (without the letter “d”). This dictionary will probably not exist yet, so you need to add it by hand. You need to know the MAC address, but it is probably listed already in this file.

<key>A2DPService</key>
<dict>
  <key>State</key>
  <true/>
  <key>UnauthorizeList</key>
  <dict>
    <key>00:10:60:D0:91:D0</key>        <!-- This is the MAC address -->
    <date>2009-08-08T01:00:00Z</date>   <!-- Timestamp -->
  </dict>
</dict>

Transfer the PLIST file back to your iPhone and reboot the device. Once it gets back on, then the A2DP service should be disabled.