$ODVGDLU$OODQ Beijing Cambridge Farnham Kln Sebastopol Tokyo Basic Sensors in iOS Ly Alasuaii Allan Copyiight 2011 Alasuaii Allan. All iights ieseiveu. Piinteu in the Uniteu States ol Ameiica. PuLlisheu Ly O`Reilly Meuia, Inc., 1005 Giavenstein Highway Noith, SeLastopol, CA 95+72. O`Reilly Looks may Le puichaseu loi euucational, Lusiness, oi sales piomotional use. Online euitions aie also availaLle loi most titles (http://ny.sajariboo|son|inc.con). Foi moie inloimation, contact oui coipoiate/institutional sales uepaitment: (S00) 99S-993S oi corporatcorci||y.con. Editor: Biian ]epson Proofreader: O`Reilly Piouuction Seivices Cover Designer: Kaien Montgomeiy Interior Designer: Daviu Futato Illustrator: RoLeit Romano Printing History: ]uly 2011: Fiist Euition. Nutshell HanuLook, the Nutshell HanuLook logo, anu the O`Reilly logo aie iegisteieu tiauemaiks ol O`Reilly Meuia, Inc. Basic Scnsors in iOS, the image ol a Malay lox-Lat, anu ielateu tiaue uiess aie tiauemaiks ol O`Reilly Meuia, Inc. Many ol the uesignations useu Ly manulactuieis anu selleis to uistinguish theii piouucts aie claimeu as tiauemaiks. Vheie those uesignations appeai in this Look, anu O`Reilly Meuia, Inc. was awaie ol a tiauemaik claim, the uesignations have Leen piinteu in caps oi initial caps. Vhile eveiy piecaution has Leen taken in the piepaiation ol this Look, the puLlishei anu authoi assume no iesponsiLility loi eiiois oi omissions, oi loi uamages iesulting liom the use ol the inloimation con- taineu heiein. ISBN: 97S-1-++9-30S+6-9 LSI 1311179730 Table of Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. The Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 AvailaLle Sensoi Haiuwaie 1 Dilleiences Between iPhone anu iPau 2 Device Oiientation anu the iPau + Detecting Haiuwaie Dilleiences + Cameia AvailaLility 5 Auuio Input AvailaLility 5 GPS AvailaLility 6 Magnetometei AvailaLility 6 Setting Reguiieu Haiuwaie CapaLilities 6 Peisistent ViFi 7 Backgiounu Moues 7 2. Using the Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 The Haiuwaie 9 Captuiing Stills anu Viueo 10 Viueo ThumLnails 1S Viueo ThumLnails Using the UIImagePickei 1S Viueo ThumLnails Using AVFounuation 19 Saving Meuia to the Photo AlLum 20 Viueo Customization 23 3. Using Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 The Haiuwaie 25 Meuia PlayLack 26 Recoiuing anu Playing Auuio 31 Recoiuing Auuio 32 Playing Auuio 35 v 4. Using the Accelerometer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 ALout the Acceleiometei 37 Viiting an Acceleiometei Application 3S Deteimining Device Oiientation +3 Deteimining Device Oiientation Diiectly Using the Acceleiometei +6 OLtaining Notilications when Device Oiientation Changes +S Vhich Vay Is Up? +9 Convenience Methous loi Oiientation 52 Detecting Shaking 53 5. Using the Magnetometer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 ALout the Magnetometei 57 Viiting a Magnetometei Application 59 Deteimining the Heauing in Lanuscape Moue 62 Measuiing a Magnetic Fielu 6S 6. Using Core Motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Coie Motion 71 Pulling Motion Data 72 Pushing Motion Data 73 Accessing the Gyioscope 75 Measuiing Device Motion 79 Compaiing Device Motion with the Acceleiometei S3 7. Going Further . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 The iPhone SDK S7 Geolocation anu Maps S7 Thiiu-Paity SDKs S7 Speech Recognition SS Computei Vision SS Augmenteu Reality SS Exteinal Accessoiies SS vi | Table of Contents Preface Ovei the last lew yeais the new geneiation ol smait phones, such as Apple`s iPhone, has linally staiteu to live up to theii name anu have Lecome the piimaiy inteilace uevice loi geogiaphically taggeu uata. Howevei not only uo these uevices know wheie they aie, they can tell you how they`ie Leing helu, they aie sulliciently poweilul to oveilay uata layeis on the cameia view, anu iecoiu anu inteipiet auuio uata, anu they can uo all this in ieal time. These aie not just smait phones, these aie computeis that just happen to Le aLle to make phone calls. This Look shoulu pioviue a soliu intiouuction to using the haiuwaie leatuies in the iPhone, iPou touch, anu iPau. Who Should Read This Book? This Look pioviues an intiouuction to the hot topic ol location-enaLleu sensois on the iPhone. Il you aie a piogiammei who has hau some expeiience with the iPhone Leloie, this Look will help you push youi knowleuge luithei. Il you aie an expeiienceu Mac piogiammei, alieauy lamiliai with OLjective-C as a language, this Look will give you an intiouuction to the haiuwaie specilic paits ol iPhone piogiamming. What You Should Already Know? The Look assumes some pievious expeiience with the OLjective-C language. Auui- tionally some lamiliaiity with the iPhone platloim woulu Le helplul. Il you`ie new to the iPhone platloim you may Le inteiesteu in Lcarning iPhonc Progranning, also Ly Alasuaii Allan (O`Reilly). What Will You Learn? This Look will guiue you thiough guiue you thiough ueveloping applications loi the iPhone platloim that make use ol the onLoaiu sensois: the thiee-axis acceleiometei, vii the magnetometei (uigital compass), the gyioscope, the cameia anu the gloLal posi- tioning system Whats In This Book? Chaptei 1, Thc Hardwarc This chaptei summaiizes the availaLle sensois on the iPhone anu iPau platloims anu how they have, oi coulu Le, useu in applications. It talks aLout the uilleiences Letween the haiuwaie platloims. Chaptei 2, Using thc Cancra Valkthiough ol how to use the iPhone`s cameia loi still anu viueo. How to cieate viueo thumLnails anu customise viueo. Chaptei 3, Using Audio Valkthiough ol how to playLack iPou meuia, as well as how to play anu iecoiu auuio on youi uevice. Chaptei +, Using thc Accc|cronctcr Valkthiough ol how to use the acceleiometei, uiscussion ol what is implieu with iespect to the oiientation ol the uevice Ly the iaw ieauings. Chaptei 5, Using thc Magnctonctcr Valkthiough ol how to use the magnetometei, uiscussion ol comLining the mag- netometei anu acceleiometei to get the yaw, pitch anu ioll ol the uevice. Chaptei 6, Using Corc Motion This paiagiaph uiscusses the new Coie Motion liamewoik; this new liamewoik allows youi application to ieceive motion uata liom Loth the acceleiometei anu (on the latest geneiation ol uevices) the gyioscope. Chaptei 7, Going Iurthcr Pioviues a collection ol pointeis to moie auvanceu mateiial on the topics we cov- eieu in the Look, anu mateiial coveiing some ol those topics that we uiun`t manage to talk aLout in this Look. Conventions Used in This Book The lollowing typogiaphical conventions aie useu in this Look: |ta|ic Inuicates new teims, URLs, email auuiesses, lilenames, anu lile extensions. Constant width Useu loi piogiam listings, as well as within paiagiaphs to ielei to piogiam elements such as vaiiaLle oi lunction names, uataLases, uata types, enviionment vaiiaLles, statements, anu keywoius. viii | Preface Constant width bold Shows commanus oi othei text that shoulu Le typeu liteially Ly the usei. Constant width italic Shows text that shoulu Le ieplaceu with usei-supplieu values oi Ly values uetei- mineu Ly context. This icon signilies a tip, suggestion, oi geneial note. This icon signilies a waining oi caution. Using Code Examples This Look is heie to help you get youi joL uone. In geneial, you may use the coue in this Look in youi piogiams anu uocumentation. You uo not neeu to contact us loi peimission unless you`ie iepiouucing a signilicant poition ol the coue. Foi example, wiiting a piogiam that uses seveial chunks ol coue liom this Look uoes not ieguiie peimission. Selling oi uistiiLuting a CD-ROM ol examples liom O`Reilly Looks uoes ieguiie peimission. Answeiing a guestion Ly citing this Look anu guoting example coue uoes not ieguiie peimission. Incoipoiating a signilicant amount ol example coue liom this Look into youi piouuct`s uocumentation uoes ieguiie peimission. Ve appieciate, Lut uo not ieguiie, attiiLution. An attiiLution usually incluues the title, authoi, puLlishei, anu ISBN. Foi example: Basic Scnsors in iOS, Ly Alasuaii Allan. Copyiight 2011 O`Reilly Meuia, Inc., 97S-1-++93-0S+6-9. Il you leel youi use ol coue examples lalls outsiue laii use oi the peimission given heie, leel liee to contact us at pcrnissionsorci||y.con. A lot ol the examples won`t woik completely in the simulatoi, so you`ll neeu to ueploy them to youi uevice to test the coue. Safari Books Online Salaii Books Online is an on-uemanu uigital liLiaiy that lets you easily seaich ovei 7,500 technology anu cieative ieleience Looks anu viueos to linu the answeis you neeu guickly. Vith a suLsciiption, you can ieau any page anu watch any viueo liom oui liLiaiy online. Reau Looks on youi cell phone anu moLile uevices. Access new titles Leloie they aie Preface | ix availaLle loi piint, anu get exclusive access to manusciipts in uevelopment anu post leeuLack loi the authois. Copy anu paste coue samples, oiganize youi lavoiites, uown- loau chapteis, Lookmaik key sections, cieate notes, piint out pages, anu Lenelit liom tons ol othei time-saving leatuies. O`Reilly Meuia has uploaueu this Look to the Salaii Books Online seivice. To have lull uigital access to this Look anu otheis on similai topics liom O`Reilly anu othei puL- lisheis, sign up loi liee at http://ny.sajariboo|son|inc.con. How to Contact Us Please auuiess comments anu guestions conceining this Look to the puLlishei: O`Reilly Meuia, Inc. 1005 Giavenstein Highway Noith SeLastopol, CA 95+72 S00-99S-993S (in the Uniteu States oi Canaua) 707-S29-0515 (inteinational oi local) 707-S29-010+ (lax) Ve have a weL page loi this Look, wheie we list eiiata, examples, anu any auuitional inloimation. You can access this page at: http://www.orci||y.con/cata|og/978111930819 Supplementaiy mateiials aie also availaLle at: http://www.progranningiphoncscnsors.con To comment oi ask technical guestions aLout this Look, senu email to: boo|qucstionsorci||y.con Foi moie inloimation aLout oui Looks, couises, conleiences, anu news, see oui weLsite at http://www.orci||y.con. Finu us on FaceLook: http://jaccboo|.con/orci||y Follow us on Twittei: http://twittcr.con/orci||yncdia Vatch us on YouTuLe: http://www.youtubc.con/orci||yncdia Acknowledgments Eveiyone has one Look in them. This is my seconu, oi uepenuing how you want to look at it, my Platloim 9', since this Look, along with the othei thiee loithcoming shoit Looks on iOS anu sensoi technology, will loim the Lulk ol Progranning iOS1 Scnsors, which woulu pioLaLly Le classeu Ly most as my seconu ieal Look loi O`Reilly. x | Preface At which point, I`u like to thank my euitoi at O`Reilly, Biian ]epson, loi holuing my hanu just one moie time. As evei his haiu woik maue my haiu woik much Lettei than it otheiwise woulu have Leen. I also veiy much want to thank my wile Gemma HoLson loi hei continueu suppoit anu encouiagement. Those small, anu sometimes laigei, saciilices an authoi`s spouse ioutinely has to make uon`t get any less inconvenient the seconu time aiounu. I`m not suie why she let me wiite anothei, peihaps Lecause I claimeu to enjoy wiiting the liist one so much. Thank you Gemma. Finally to my son Alex, still too young to ieau what his uauuy has wiitten, hopelully this volume will keep you in Looks to chew on just a little longei. Preface | xi CHAPTER 1 The Hardware The aiiival ol the iPhone changeu the whole uiiection ol soltwaie uevelopment loi moLile platloims, anu has hau a piolounu impact on the haiuwaie uesign ol the smait phones that have lolloweu it. The aiiival ol the iPau has tuineu what was a single class ol uevice into a platloim. Available Sensor Hardware Vhile the iPhone is almost unigue amongst moLile platloims in guaianteeing that youi application will iun on all ol the cuiient uevices (see Figuie 1-1), howevei theie is an incieasing amount ol vaiiation in availaLle haiuwaie Letween the vaiious mouels, as shown in TaLle 1-1. Iigurc 1-1. Tinc|inc showing thc avai|abi|ity oj iPhonc, iPod Touch, iPad nodc|s 1 Tab|c 1-1. Hardwarc support in various iPhonc, iPod touch, and iPad Hardware Feature iPhone iPod touch iPad iPad 2 O r i g i n a l 3 G 3 G S 4 1 s t
G e n 2 n d
G e n 3 r d
G e n 4 t h
G e n W i F i 3 G W i F i 3 G Cellular WiFi Bluetooth Speaker Audio In Accelerometer Magnetometer Gyroscope GPS Proximity Sensor Camera Video Vibration Most ol the examples in this Look will Le Luilt as iPhone howevei uepenuing on the availaLility ol haiuwaie the examples will iun egually well on the iPou touch anu iPau; the unueilying coue is egually applicaLle as we`ie uealing loi the most pait uiiectly with that haiuwaie. Differences Between iPhone and iPad The most stiiking, anu oLvious, uilleience Letween the iPhone anu the iPau is scieen size. The oiiginal iPhone scieen has +S0320 pixel iesolution at 163 pixels pei inch. The iPhone + anu +th geneiation iPou touch Retina Displays have a iesolution ol 9606+0 pixel at 326 pixels pei inch. Meanwhile Loth geneiations ol the iPau scieen have 102+76S pixel iesolution at 132 pixels pei inch. This uilleience will Le the single most lunuamental thing to allect the way you uesign youi usei inteilace on the two platloims. Attempting to tieat the iPau as simply a iathei oveisizeu iPou touch oi iPhone will leau to Lauly uesigneu applications. The metaphois you use on the two uilleient platloims The incieaseu scieen size ol the uevice means that you can uevelop uesktop-sizeu ap- plications, not just phone-sizeu applications, loi the iPau platloim. Although in uoing so, a iethink ol the usei inteilace to auapt to multi-touch is neeueu. Vhat woiks loi the iPhone oi the uesktop, won`t automatically woik on an iPau. Foi example, Apple 2 | Chapter 1:The Hardware totally ieuesigneu the usei inteilace ol the iVoik suite when they moveu it to the iPau. Il you`ie intenuing to poit a Mac OS X uesktop application to the iPau you shoulu uo something similai. Inteiestingly theie is now an option loi iOS uevelopeis to poit theii iPhone anu iPau piojects uiiectly to Mac OS X. The Chameleon Pioject http://chanc|conprojcct.org is a uiop in ieplacement loi UIKit that iuns on Mac OS X, allowing iOS applications to Le iun on the uesktop with little mouilication, in some cases none. Due to its size anu lunction the iPau is immeuiately associateu in oui minus with othei moie lamiliai oLjects like a legal pau oi a Look. Holuing the uevice tiiggeis poweilul associations with these items, anu we`ie mentally willing to accept the iPau has a suc- cessoi to these oLjects. This is simply not tiue loi the iPhone; the uevice is physically too small. The Human Interface Guidelines Apple has Lecome almost inlamous loi stiict auheience to its Human Inteilace Guiue- lines. Designeu to piesent useis with a consistent visual anu Lehavioial expeiience acioss applications anu the opeiating system the inteilace guiuelines mean that (most) applications iunning on the Mac OS X uesktop have a consistent look anu leel. Vith the aiiival ol the iPhone anu the iPau, Apple hau to uiaw up new sets ol guiuelines loi theii moLile platloims, iauically uilleient liom the tiauitional uesktop. Even loi uevelopeis who aie skeptical aLout whethei they ieally neeueu to stiictly au- heie to the guiuelines (especially when Apple peiiouically steps outsiue them) the Human Inteilace Guiuelines have iemaineu a Lenchmaik against which the usei ex- peiience can Le measuieu. Copies ol the Human Inteilace Guiuelines loi Loth the iPhone anu the iPau aie availaLle loi uownloau liom the App Stoie Resouice Centei. I woulu iecommenu that you ieau the moLile Human Inteilace Guiuelines caielully, il only Lecause violating them coulu leau to youi application Leing iejecteu Ly the ieview team uuiing the App Stoie appioval piocess. Howevei this Look is not aLout how to uesign youi usei inteilace oi manage youi usei expeiience. Foi the most pait the examples I piesent in this Look aie simple view-Laseu applications that coulu Le egually wiitten loi the iPhone anu iPou touch oi the iPau. The usei inteilace is only theie to illustiate how to use the unueilying haiuwaie. This Look is aLout how to use the collection ol sensois in these moLile uevices. Differences Between iPhone and iPad | 3 Device Orientation and the iPad The sliuei Lutton on the siue ol the iPau can, optionally, Le useu to lock the uevice`s oiientation. This means that il you want the scieen to stay in poitiait moue, it won`t move when you tuin it siueways il lockeu. Howevei uespite the piesence ol the iotation lock (anu unlike the iPhone wheie many applications only suppoiteu Poitiait moue) an iPau application is expecteu to suppoit all oiientations egually. Apple has this to say aLout iPau applications: An application`s intei- lace shoulu suppoit all lanuscape anu poitiait oiientations. This Le- havioi uilleis slightly liom the iPhone, wheie iunning in Loth poitiait anu lanuscape moues is not ieguiieu. To implement Lasic suppoit loi all inteilace oiientations, you shoulu implement the shouldAutorotateToInterfaceOrientation: methou in all ol youi application`s view contiolleis, ietuining YES loi all oiientations. Auuitionally, you shoulu conliguie the auto-iesizing maik piopeity ol youi views insiue Inteilace Builuei so that they coiiectly iesponu to layout changes (i.e. iotation ol the uevice). Going beyond basic support Il you want to go Leyonu Lasic suppoit loi alteinative oiientations theie is moie woik involveu. Fiistly loi custom views, wheie the placement ol suLviews is ciitical to the UI anu neeu to Le piecisely locateu, you shoulu oveiiiue the layoutSubviews methou to auu youi custom layout coue. Howevei, you shoulu oveiiiue this methou only il the autoiesizing Lehaviois ol the suLviews aie not what you uesiie. Vhen an oiientation event occuis, the UIWindow class will woik with the liont-most UIViewController to aujust the cuiient view. Theieloie il you neeu to peiloim tasks Leloie, uuiing, oi altei completing uevice iotation you shoulu use the ielevant iotation UIViewController notilication methous. Specilically the view contiollei`s willRotate ToInterfaceOrientation:duration:, willAnimateRotationToInterfaceOrienta tion:duration:, anu didRotateFromInterfaceOrientation: methous aie calleu at iele- vant points uuiing iotation allowing you to peiloim tasks ielevant to the oiientation change in piogiess. Foi instance you might make use ol these callLacks to allow you to auu oi iemove specilic views anu ieloau youi uata in those views. Detecting Hardware Differences Because youi application will likely suppoit multiple uevices, you`ll neeu to wiite coue to check which leatuies aie suppoiteu anu aujust youi application`s Lehavioi as appiopiiate. 4 | Chapter 1:The Hardware Camera Availability Ve covei the cameia in uetail in Chaptei 2, howevei it is simple mattei to ueteimine whethei a cameia is piesent in the uevice: BOOL available = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]; Once you have ueteimineu that a cameia is piesent you can enguiie whethei it suppoits viueo Ly making a call to ueteimine the availaLle meuia types the cameia suppoits: NSArray *media = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera]; Il the kUTTypeMovie meuia type is ietuineu as pait ol the aiiay, then the cameia will suppoit viueo iecoiuing: if ( [media containsObject:(NSString *)kUTTypeMovie ] ){ NSLog(@"Camera supports movie capture."); } Audio Input Availability An initial poll ol whethei auuio input is availaLle can Le uone using the AVAudioSes sion class Ly checking the inputIsAvailable class piopeity: AVAudioSession *audioSession = [AVAudioSession sharedInstance]; BOOL audioAvailable = audioSession.inputIsAvailable; You will neeu to auu the A\Ioundation.Irancwor| (iight-click/Con- tiol-click on the Fiamewoiks loluei in Xcoue, then choose AuuExisting Fiamewoiks). You`ll also neeu to impoit the heauei (put this in youi ueclaiation il you plan to implement the AVAudioSessionDe legate piotocol uiscusseu latei): #import <AVFoundation/AVFoundation.h> You can also Le notilieu ol any changes in the availaLility ol auuio input, e.g., il a seconu geneiation iPou touch usei has pluggeu in heauphones with miciophone capaLilities. Fiist, nominate youi class as a uelegate: audioSession.delegate = self; Anu then ueclaie it as implementing the AVAudioSessionDelegate piotocol in the ueclaiation: @interface YourAppDelegate : NSObject <UIApplicationDelegate, AVAudioSessionDelegate > Then implement the inputIsAvailableChanged: in the implementation: Detecting Hardware Differences | 5 - (void)inputIsAvailableChanged:(BOOL)audioAvailable { NSLog(@"Audio availability has changed"); } GPS Availability The shoit answei to a commonly askeu guestion is that the Coie Location liamewoik uoes not pioviue any way to get uiiect inloimation aLout the availaLility ol specilic haiuwaie such as the GPS at application iun time, although you can check whethei location seivices aie enaLleu: BOOL locationAvailable = [CLLocationManager locationServicesEnabled]; Howevei, you can ieguiie the piesence ol GPS haiuwaie loi youi application to loau (see Setting Reguiieu Haiuwaie CapaLilities). Magnetometer Availability Foitunately Coie Location uoes allow you to check loi the piesence ol the magneto- metei (uigital compass) laiily simply: BOOL magnetometerAvailable = [[CLLocationManager headingAvailable]; Setting Required Hardware Capabilities Il youi application ieguiies specilic haiuwaie leatuies in oiuei to iun you can auu a list ol ieguiieu capaLilities to youi application`s |njo.p|ist lile. Youi application will not stait unless those capaLilities aie piesent on the uevice. To uo this, open the pioject anu click on the application`s |njo.p|ist lile to open it in the Xcoue euitoi. Click on the Lottommost entiy in the list. A plus Lutton will appeai to the iight-hanu siue ol the key-value paii taLle. Click on this Lutton to auu a new iow to the taLle, anu scioll uown the list ol possiLle options anu select Reguiieu uevice capaLilities (the UIRequiredDeviceCapabilities key). This will auu an (empty) aiiay to the p|ist lile. The alloweu values loi the keys aie: telephony wifi sms still-camera auto-focus-camera front-facing-camera camera-flash 6 | Chapter 1:The Hardware video-camera accelerometer gyroscope location-services gps magnetometer gamekit microphone opengles-1 opengles-2 armv6 armv7 peer-peer A lull uesciiption ol the possiLle keys is given in the Device Suppoit section ol the iPhone Application Piogiamming Guiue availaLle liom the iPhone Development Centei. Persistent WiFi Il youi application ieguiies a peisistent ViFi connection you can set the Boolean UIRequiresPersistentWiFi key in the Application`s |njo.p|ist lile to ensuie that ViFi is availaLle. Il set to YES the opeiating system will open a ViFi connection when youi application is launcheu anu keep it open while the application is iunning. Il this key is not piesent, oi is set to NO, the Opeiating System will close the active ViFi connection altei 30 minutes. Background Modes Setting the UIBackgroundModes key in the Application`s |njo.p|ist lile notilies the opei- ating systems that the application shoulu continue to iun in the Lackgiounu, altei the usei closes it, since it pioviues specilic Lackgiounu seivices. Apple has this to say aLout Lackgiounu moues, These keys shoulu Le useu spaiingly anu only Ly applications pioviuing the inuicateu seivices. Vheie alteinatives loi iunning in the Lackgiounu exist, those alteina- tives shoulu Le useu insteau. Foi example, applications can use the sig- nilicant location change inteilace to ieceive location events insteau ol iegisteiing as a Lackgiounu location application. Setting Required Hardware Capabilities | 7 Theie aie thiee possiLle key values: audio, location, anu voip. The audio key inuicates that altei closing the application will continue to play auuiLle content. The location key inuicates that the application pioviues location-Laseu inloimation loi the usei us- ing the stanuaiu Coie Location seivices, iathei than the newei signilicant location change seivice. Finally, the voip key inuicates that the application pioviues Voice-ovei- IP seivices. Applications maikeu with this key aie automatically launcheu altei system Loot so that the application can attempt to ie-estaLlish VoIP seivices. 8 | Chapter 1:The Hardware CHAPTER 2 Using the Camera Phones with cameias only staiteu appeaiing on the maiket in late 2001; now they`ie eveiywheie. By the enu ol 2003 moie cameia phones weie solu woiluwiue than stanu- alone uigital cameias, anu Ly 2006 hall ol the woilu`s moLile phones hau a Luilt-in cameia. The social impact ol this phenomenon shoulu not Le unueiestimateu; the uLiguity ol these uevices has hau a piolounu allect on society anu on the way that news anu in- loimation piopagate. MoLile phones aie constantly caiiieu, which means theii cameia is always availaLle. This constant availaLility has leu to some innovative thiiu paity applications, especially with the new geneiation ol smait phones. The iPhone has Leen uesigneu with always-on connectivity in minu. The Hardware Until iecently, only the iPhone has leatuieu a cameia in all ol the availaLle mouels. Howevei the latest geneiation ol Loth the iPou touch anu iPau now also have cameias. The oiiginal iPhone anu iPhone 3G leatuie a lixeu-locus 2.0-megapixel cameia, while the iPhone 3GS leatuies a 3.2-megapixel cameia with auto-locus, auto-white Lalance anu auto-macio locus (up to 10cm). The iPhone 3GS cameia is also aLle ol captuiing 6+0+S0 pixel viueo at 30 liames pei seconu. Although the eailiei mouels aie physically capaLle ol captuiing viueo, they aie limiteu in soltwaie anu this leatuie is not availaLle at the usei level. The latest iPhone + leatuies a 5-megapixel cameia with Lettei low- light sensitivity anu Lacksiue illuminateu sensoi. The cameia has an LED llash anu is capaLle ol captuiing 720p HD viueo at 30 liames pei seconu. The iPhone + also has a lowei-iesolution liont-lacing cameia, which is capaLle ol captuiing 360p HD viueo at 30 liames pei seconu. 9 The iPhone 3GS anu iPhone + cameias aie known to sullei liom ro||ing shuttcr cjjcct when useu to take viueo. This ellect is a loim ol aliasing that may iesult in uistoition ol last moving oLjects, oi image ellects uue to lighting levels that change as a liame is captuieu. At the time ol wiit- ing it`s not cleai whethei the +th geneiation iPou touch anu iPau 2 cam- eias sullei the same pioLlem. The latest geneiation ol iPou touch anu iPau also have Loth ieai- anu liont-lacing cameias, Loth ol which aie lai lowei iesolution than the cameia litteu to the iPhone +, see TaLle 2-1 loi uetails. You`ll notice the uilleience in sizes Letween still anu viueo images on the iPou touch anu the iPau 2. It`s uncleai whethei Apple is using a 12S0720 sensoi anu ciopping oll the lelt anu iight siues ol the viueo image loi still images, oi whethei it is using a 960720 sensoi anu up-scaling it on the siues loi viueo. The latei woulu Le an unusual appioach loi Apple, Lut is not inconceivaLle. Tab|c 2-1. Cancra hardwarc support in various iPhonc nodc|s Model Focus Flash Megapixels Size Video Original iPhone Fixed No 2.0 16001200 No iPhone 3G Fixed No 2.0 16001200 No iPhone 3GS Autofocus No 3.2 20481536 VGA at 30fps iPhone 4 Autofocus LED flash 5.0 for still 25921944 720p at 30fps 1.4 for video 12801024 Fixed No 1.4 12801024 360p at 30fps iPod touch (4th Gen) Fixed No 0.69 for still 960720 720p at 30fps 0.92 for video 1280720 Fixed No 1.4 12801024 VGA at 30fps iPad 2 Fixed No 0.69 for still 960720 720p at 30fps 0.92 for video 1280720 Fixed No 1.4 12801024 VGA at 30fps All mouels piouuce geocoueu images Ly uelault. Capturing Stills and Video The UIImagePickerViewController is an Apple-supplieu inteilace loi choosing images anu movies, anu taking new images oi movies (on suppoiteu uevices). This class han- ules all ol the ieguiieu inteiaction with the usei anu is veiy simple to use. All you neeu to uo is tell it to stait, then uismiss it altei the usei selects an image oi movie. 10 | Chapter 2:Using the Camera Let`s go aheau anu Luilu a simple application to illustiate how to use the image pickei contiollei. Open Xcoue anu stait a new pioject. Select a View-Laseu Application loi the iPhone, anu name it Mcdia when ieguesteu. The liist thing to uo is set up the main view. This is going to consist ol a single Lutton that is piesseu to Liing up the Image Pickei contiollei. An UIImageView will uisplay the image, oi thumLnail ol the viueo, that is captuieu. Select the Mcdia\icwContro||cr.h inteilace lile to open it in the euitoi anu auu a UIBut ton anu an associateu methou to the inteilace lile. Flag these as an IBOutletanu IBAction respectively. You also neeu to auu a UIImageView to uisplay that image ietuineu Ly the image pickei, which also neeus to Le llaggeu as an IBOutlet. Finally, auu a UIImage PickerController, anu llag the view contiollei as Loth UIImagePickerControllerDele gate anu UINavigationControllerDelegate. The coue to auu to the uelault template is shown in Lolu: #import <UIKit/UIKit.h> @interface MediaViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> { IBOutlet UIButton *pickButton; IBOutlet UIImageView *imageView; UIImagePickerController *pickerController; } -(IBAction) pickImage:(id) sender; @end Both UIImagePickerControllerDelegate anu UINavigationControllerDelegate uec- laiations aie necessaiy loi the class to inteiact with the UIImagePickerController. Next, open the Mcdia\icwContro||cr.n implementation lile anu auu a stuL loi the pickImage: methou. As always, iememLei to ielease the pickButton, imageView anu the pickerController in the dealloc methou: -(IBAction) pickImage:(id) sender { // Code goes here later } - (void)dealloc { [pickButton release]; [imageView release]; [pickerController release]; [super dealloc]; } Altei saving youi changes (-S) single click on the Mcdia\icwContro||cr.xib NIB lile to open it in Inteilace Builuei. Diag anu uiop a UIButton anu a UIImageView into the main View winuow. Go aheau anu change the Lutton text to something appiopiiate, anu in the Attributcs |nspcctor ol the Utilities panel set the UIImageView`s view moue to Capturing Stills and Video | 11 Le Aspect Fit. Use the Size inspectoi iesize the UIImageView to a +:3 iatio. I useu 2S0210 points which lits nicely in a Poitiait-moue iPhone scieen. Next click on File`s Ownei in the main panel. In the Connections inspectoi ol the Utilities panel, connect Loth the pickButton outlet anu the pickImage: ieceiveu action to the Lutton you just uioppeu into the View choosing Touch Up Insiue as the action, see Figuie 2-1. Iigurc 2-1. Connccting thc U|Button to Ii|c`s Owncr Then connect the imageView outlet to the UIImageView in oui usei inteilace. Click on the Mcdia\icwContro||cr.n implementation lile anu uncomment the viewDid Load: methou. You`ie going to use this to initialize the UIImagePickerController. Make the changes shown in Lolu: - (void)viewDidLoad { [super viewDidLoad]; pickerController = [[UIImagePickerController alloc] init]; pickerController.allowsEditing = NO; pickerController.delegate = self; } 12 | Chapter 2:Using the Camera This allocates anu initializes the UIImagePickerController; uon`t loiget to ielease it insiue the dealloc methou. This line pievents the pickei contiollei liom uisplaying the ciop anu iesize tools. Il enaLleu, the ciop anu iesize stage is shown altei captuiing a still. Foi viueo, the tiimming inteilace is piesenteu. This line sets the uelegate class to Le the cuiient class, the MediaViewController. The UIImagePickerController can Le uiiecteu to select an image (oi viueo) liom thiee image souices: UIImagePickerControllerSourceTypeCamera, UIImagePickerController SourceTypePhotoLibrary anu UIImagePickerControllerSourceTypeSavedPhotosAlbum. Each piesents a uilleient view to the usei allowing hei to take an image (oi a viueo) with the cameia, liom the image liLiaiy, oi liom the saveu photo alLum. Now wiite the pickImage: methou that will piesent the image pickei contiollei to the usei. Theie aie a lew goou ways to uo that, uepenuing on the inteilace you want to piesent. The liist methou, makes use ol a UIActionSheet to choose the souice type, piesenting the usei with a list to ueciue whethei they will take a still image oi a viueo: -(void)pickImage: (id)sender { UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Photo",@"Video",nil]; popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque; [popupQuery showInView:self.view]; [popupQuery release]; } Il we`ie going to use this methou we must specily that the view contiollei suppoits the UIActionSheetDelegate piotocol in the inteilace lile: @interface MediaViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIActionSheetDelegate> { In the implementation lile, pioviue an actionSheet:clickedButtonAtIndex: uelegate methou to hanule piesenting the image pickei inteilace. Il theie is no cameia piesent the souice will Le set to the saveu photos alLum: - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; } else { pickerController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; Capturing Stills and Video | 13 } if (buttonIndex == 0) { pickerController.mediaTypes = [NSArray arrayWithObject: kUTTypeImage]; } else if (buttonIndex == 1) { pickerController.mediaTypes = [NSArray arrayWithObject: kUTTypeMovie]; } [self presentModalViewController:pickerController animated:YES]; } Heie we check whethei the cameia is availaLle; il it is we set the sourceType to Le the cameia. Il the cameia is not availaLle, we set the sourceType to Le the Saveu Photo AlLum. Since we`ve maue use ol the kUTTypeImage anu kUTTypeMovie type coues in this methou we have to auu the MoLile Coie Seivices liamewoik to oui pioject. Foi those ol you useu to woiking in Xcoue 3, the way you auu liame- woiks to youi pioject has changeu. In the past you weie aLle to iight- click on the Fiamewoik`s gioup anu then select AuuExisting Fiame- woiks. Unloitunately this is no longei possiLle anu auuing liamewoiks has Lecome a moie laLoiious piocess. To auu the liamewoik, select the Meuia pioject lile in the Pioject navigatoi winuow. You shoulu see a panel as in see Figuie 2-2. Select the Taiget anu click on the Builu Phases taL. Select the Link with LiLiaiies uiop uown anu use the - Lutton to auu the Mobi|cCorcScrviccs.jrancwor| liom the list ol availaLle liamewoiks. Auu the lollowing to the view contiollei inteilace lile: #import <MobileCoreServices/MobileCoreServices.h> Altei saving the changes you can click on the Builu anu Run Lutton. You shoulu Le piesenteu with an inteilace much like Figuie 2-3 (lelt). Clicking on the Go Lutton you shoulu Le piesenteu with the UIActionSheet that piompts the usei to choose Le- tween still image anu viueo captuie. Il you uo go aheau anu test the application in the iPhone Simulatoi you`ll notice that theie aien`t any images in the Saveu Photos loluei, see Fig- uie 2-3 (iight). Howevei theie is a way aiounu this pioLlem. In the Simulatoi, tap on the Salaii Icon anu uiag anu uiop a pictuie liom youi computei (you can uiag it liom the Finuei oi iPhoto) into the Liowsei. Fiom the Liowsei you can save the image to the Saveu Photos loluei. Insteau ol explicitly choosing an image oi viueo via the action sheet, you coulu insteau allow the usei to pick the souice. The lollowing alteinative coue ueteimines whethei youi uevice suppoits a cameia anu auus all ol the availaLle meuia types to an aiiay. Il theie is no cameia piesent the souice will again Le set to the saveu photos alLum: 14 | Chapter 2:Using the Camera -(void)pickImage: (id)sender { if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; NSArray* mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera]; pickerController.mediaTypes = mediaTypes; } else { pickerController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; } [self presentModalViewController:pickerController animated:YES]; } Iigurc 2-2. Adding thc Mobi|cCorcScrviccs.jrancwor| to thc projcct Heie insteau ol piesenting an action sheet anu allowing the usei to choose which souice type they wish to use we inteiiogate the haiuwaie anu ueciue which souice types aie availaLle. Ve can see the uilleient inteilaces these two methous geneiate in Fig- uie 2-+. The lelt inteilace is the still cameia inteilace, the miuule image is the viueo cameia inteilace anu the linal (iight-hanu) image is the joint inteilace, which allows the usei to eithei take still image oi viueo. Capturing Stills and Video | 15 The linal inteilace, wheie the usei may choose to ietuin eithei a still image oi a viueo, is the one piesenteu Ly the seconu veision ol the pickImage: methou. This coue is also moie llexiLle as it will iun unmouilieu on any ol the iPhone mouels that have a cameia uevice. Il youi application ieguiies eithei a still image oi a viueo (anu can not hanule Loth) you shoulu Le caielul to specily eithei kUTTypeImage oi kUTTypeMovie meuia type as you uiu in the liist veision ol the methou. You can choose eithei ol the two uilleient methous I`ve talkeu aLout aLove to piesent the image pickei contiollei to the usei. In eithei case when the usei has linisheu picking an image (oi viueo) the lollowing uelegate methou will Le calleu in the view contiollei: -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if( [info objectForKey:@"UIImagePickerControllerMediaType"] == kUTTypeMovie ) { // add code here } else { imageView.image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; } [self dismissModalViewControllerAnimated:YES]; } Iigurc 2-3. Thc initia| Mcdia app|ication intcrjacc (|cjt), thc U|ActionShcct that pops up whcn thc button is prcsscd (nidd|c), and thc Savcd Photos jo|dcr that appcars whcn thc cancra is unavai|ab|c (right) 16 | Chapter 2:Using the Camera Ve must uismiss the image pickei inteilace in all cases. Vhen the UIImagePickerController ietuins it passes an NSDictionary containing a numLei ol keys, listeu in TaLle 2-2. Use the UIImagePickerControllerMediaType key to ueciue whethei the image pickei is ietuining a still image oi a movie to its uelegate methou. Tab|c 2-2. Kcys jron thc NSDictionary rcturncd by thc inagc pic|cr contro||cr Key Object type UIImagePickerControllerMediaType kUTTypeImage or kUTypeMovie UIImagePickerControllerOriginalImage UIImage UIImagePickerControllerEditedImage UIImage UIImagePickerControllerCropRect CGRect UIImagePickerControllerMediaURL NSURL Ve can ietiieve the oiiginal image (oi cioppeu veision il euiting is enaLleu) uiiectly liom the NSDictionary that was passeu into the uelegate methou. This image ieleience can Le passeu uiiectly to the UIImageView anu uisplayeu, as shown in the coue in the next section anu Figuie 2-5. Iigurc 2-1. Thc thrcc dijjcrcnt U||nagcPic|crContro||cr intcrjaccs Capturing Stills and Video | 17 Video Thumbnails Theie is no easy way to ietiieve a thumLnail ol a viueo, unlike still photos. This section illustiates two methous ol giaLLing iaw image uata liom an image pickei. Video Thumbnails Using the UIImagePicker One way to giaL a viueo liame loi cieating a thumLnail is to uiop uown to the unuei- lying Quaitz liamewoik to captuie an image ol the pickei itsell. To uo so, auu the lollowing highlighteu coue to the image pickei uelegate uesciiLeu pieviously in this chaptei: -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if( [info objectForKey:@"UIImagePickerControllerMediaType"] == kUTTypeMovie ) { CGSize pickerSize = CGSizeMake(picker.view.bounds.size.width, picker.view.bounds.size.height-100); UIGraphicsBeginImageContext(pickerSize); [picker.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); imageView.image = thumbnail; Iigurc 2-5. A thunbnai| oj a sing|c jranc oj vidco disp|aycd in a U||nagc\icw 18 | Chapter 2:Using the Camera } else { imageView.image = image; } [self dismissModalViewControllerAnimated:YES]; } Since picker.view.layer is pait ol the UIView paient class anu is ol type CALayer, the compilei uoesn`t know aLout renderInContext: methou unless you impoit the Quaitz- Coie heauei lile. Auu the lollowing to the implementation lile: #import <QuartzCore/QuartzCore.h> Video Thumbnails Using AVFoundation Anothei methou to oLtain a thumLnail that will iesult in a Lettei image is to use the AVFoundation liamewoik. Fiist ieplace the coue you auueu in the pievious section with the highlighteu coue Lelow: -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if( [info objectForKey:@"UIImagePickerControllerMediaType"] == kUTTypeMovie ) { AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:[info objectForKey:UIImagePickerControllerMediaURL] options:nil]; AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; generator.appliesPreferredTrackTransform=TRUE; [asset release]; CMTime thumbTime = CMTimeMakeWithSeconds(0,30); AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) { if (result != AVAssetImageGeneratorSucceeded) { NSLog(@"Error:%@", error); } imageView.image = [[UIImage imageWithCGImage:im] retain]; [generator release]; }; CGSize maxSize = CGSizeMake(320, 180); generator.maximumSize = maxSize; [generator generateCGImagesAsynchronouslyForTimes: [NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler]; } else { imageView.image = image; Video Thumbnails | 19 } [self dismissModalViewControllerAnimated:YES]; } Then make suie to auu the AVFounuation anu CoieMeuia liamewoiks to the pioject Ly impoiting the heauei liles at the top ol the implementation: #import <AVFoundation/AVFoundation.h> #import <CoreMedia/CoreMedia.h> The only ieal uownsiue ol this methou is that AVAssetImageGenerator makes use ol key liames, which aie typically spaceu at one seconu inteivals. Hopelully the key liame will make a goou thumLnail image. Saving Media to the Photo Album You can save Loth images anu viueos to the Photo AlLum using the UIImageWriteToSa vedPhotosAlbum anu UISaveVideoAtPathToSavedPhotosAlbum methous. The methou will also oLtain a thumLnail image loi the viueo il uesiieu. The saving lunctions in this example aie asynchionous; il the application is inteiiupteu (e.g., takes a phone call) oi teiminateu, the image oi viueo will Le lost. You neeu to ensuie that youi usei is awaie that piocessing is happening in the Lackgiounu as pait ol youi application inteilace. The lollowing example save the image to the Photo AlLum Ly auuing a call to UIImage WriteToSavedPhotosAlbum to the image pickei uelegate. The example will then pioviue leeuLack when the image has Leen successlully saveu oi an eiioi occuis. Auu the lol- lowing highlighteu lines to the image pickei contiollei piesenteu eailiei in the chaptei: -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
CGSize pickerSize = CGSizeMake(picker.view.bounds.size.width, picker.view.bounds.size.height-100); UIGraphicsBeginImageContext(pickerSize); [picker.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); imageView.image = thumbnail; } else { UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; UIImageWriteToSavedPhotosAlbum( image, self, @selector( imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), 20 | Chapter 2:Using the Camera nil); imageView.image = image; } [self dismissModalViewControllerAnimated:YES]; } Then auu the lollowing methou, which piesents a UIAlertView notilying the usei that the save has occuiieu: - (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSString *title; NSString *message; if (!error) { title = @"Photo Saved"; message = @"The photo has been saved to your Photo Album"; } else { title = NSLocalizedString(@"Error Saving Photo", @""); message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } The call to UIImageWriteToSavedPhotosAlbum can typically take up to + seconus to complete in the Lackgiounu. Il the application is inteiiupteu oi teiminateu uuiing this time then the image may not have Leen saveu. You can similaily auu the lollowing highlighteu lines to the uelegate methou to save captuieu viueo: -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { if( [info objectForKey:@"UIImagePickerControllerMediaType"] == kUTTypeMovie ) { NSString *tempFilePath = [[info objectForKey:UIImagePickerControllerMediaURL] path]; if ( UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(tempFilePath) ) { UISaveVideoAtPathToSavedPhotosAlbum( tempFilePath, self, @selector(video:didFinishSavingWithError:contextInfo:), tempFilePath); } CGSize pickerSize = CGSizeMake(picker.view.bounds.size.width, picker.view.bounds.size.height-100); UIGraphicsBeginImageContext(pickerSize); Saving Media to the Photo Album | 21 [picker.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); imageView.image = thumbnail; } else { UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; UIImageWriteToSavedPhotosAlbum(image, self, @selector( imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), nil); imageView.image = image; } [self dismissModalViewControllerAnimated:YES]; } Next auu the lollowing methou to iepoit whethei the viueo has Leen successlully saveu to the uevice`s Photo AlLum, oi an eiioi occuiieu: - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(NSString *)contextInfo { NSString *title; NSString *message; if (!error) { title = @"Video Saved"; message = @"The video has been saved to your Photo Album"; } else { title = NSLocalizedString(@"Error Saving Video", @""); message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } Make suie you`ve saveu youi changes, anu click on the Run Lutton in the Xcoue toolLai to compile anu ueploy the application to youi uevice. Il eveiything is woiking, you will see a thumLnail altei you take a photo oi viueo. Altei a lew seconus a conliimation uialog will appeai iepoiting success oi an eiioi. See Figuie 2-6. 22 | Chapter 2:Using the Camera Iigurc 2-. Saving inagcs (or vidco) to thc Photo A|bun Video Customization Il you aie captuiing viueo you can make some viueo-specilic customizations using the videoQuality anu videoMaximumDuration piopeities ol the UIImagePickerController class: pickerController.videoQuality = UIImagePickerControllerQualityTypeLow; pickerController.videoMaximumDuration = 90; // Maximum 90 seconds duration TaLle 2-3 illustiates the expecteu sizes ol a typical 90 seconu movie lile loi the thiee possiLle image guality levels, which uelaults to UIImagePickerControllerQualityType Medium. Tab|c 2-3. Sizc oj 90 scconds duration vidco jor dijjcrcnt qua|ity scttings Quality Size UIImagePickerControllerQualityTypeLow 1.8 MB UIImagePickerControllerQualityTypeMedium 8.4 MB UIImagePickerControllerQualityTypeHigh 32 MB Video Customization | 23 The maximum, anu uelault, value loi the videoMaximumDuration piopeity is 10 minutes. Useis aie loiceu to tiim longei viueo to match the uuiation you ieguest. 24 | Chapter 2:Using the Camera CHAPTER 3 Using Audio The main classes loi hanuling auuio in the SDK aie in the AVFounuation anu Meuia Playei liamewoiks. This chaptei will pioviue a Liiel oveiview ol how to play anu iecoiu auuio using these liamewoiks. The Hardware Vhilst most phones have only one miciophone, iPhone + has two. The main micio- phone is locateu noimally on the Lottom next to the uock connectoi, while the seconu miciophone is Luilt into the top neai the heauphone jack. This seconu miciophone is intenueu loi viueo-calling, Lut is also useu in conjunction with the main miciophone to suppiess Lackgiounu noise. In compaiison the iPau 2 has a single miciophone, Lut theie is a uilleience Letween the two mouels which coulu leau to a uilleience in auuio iecoiuing guality Letween the 3G anu ViFi-only mouels. On the ViFi-only mouel, the miciophone hole is Luilt- into the Lack ol the uevice, wheieas on 3G mouels, it`s Luilt into the antenna casing. Theie aie suggestions that this uilleience may leau to cleanei auuio iecoiuings with the ViFi mouel, with the 3G mouel sounuing mullleu anu echo-pione Ly compaiison. Both the iPhone + anu the iPau use an Apple Lianueu Ciiius Logic 33SS05S9 loi theii auuio DAC, with a lieguency iesponse ol 20Hz to 20kHz, anu auuio sampling ol 16- Lit at ++.1kHz. All ol the cuiient iPhone, iPau anu iPou touch mouels use a 2.5mm +-pole TRRS (tip, iing, iing, sleeve) connectoi which has a somewhat unoithouox mapping to the stanu- aiu RCA connectoi as shown in TaLle 3-1. Tab|c 3-1. Mapping bctwccn thc iPhonc`s 1-po|c jac| and thc standard RCA conncctor co|ors Apple RCA Tip RCA White 1st Ring RCA Yellow 25 Apple RCA 2nd Ring RCA Ground Sleeve RCA Red Media Playback Let`s liist look at playing Lack existing meuia stoieu in the iPou liLiaiy. Apple has pioviueu convenience classes that allow you to select anu play Lack iPou meuia insiue youi own application as pait ol the Meuia Playei liamewoik. The lollowing examples make use ol the iPou liLiaiy; this is not piesent in the iPhone Simulatoi anu will only woik coiiectly on the uevice itsell. The appioach uses pickei contiolleis anu uelegates as in the pievious chaptei. In this example I use an MPMediaPickerController that, via the MPMediaPickerControllerDele gate piotocol, ietuins an MPMediaItemCollection oLject containing the meuia items the usei has selecteu. The collection ol items can Le playeu using an MPMusicPlayerControl ler oLject. Lets go aheau anu Luilu a simple meuia playei application to illustiate how to use the meuia pickei contiollei. Open Xcoue anu stait a new View-Laseu Application pioject, naming it Auuio when ieguesteu. Click on the Auuio pioject lile in the Pioject nav- igatoi winuow, select the Taiget anu click on the Builu Phases taL. Click on the Link with LiLiaiies uiop uown anu click on the - Lutton to auu the MeuiaPlayei liamewoik. Euit the Audio\icwContro||cr.h inteilace lile to impoit the MeuiaPlayei liamewoik anu ueclaie the class as an MPMediaPickerControllerDelegate. Then auu the IBOutlet in- stance vaiiaLles anu IBAction methous loi the Luttons we will cieate in Inteilace Builuei: #import <UIKit/UIKit.h> #import <MediaPlayer/MediaPlayer.h> @interface AudioViewController : UIViewController <MPMediaPickerControllerDelegate> { IBOutlet UIButton *pickButton; IBOutlet UIButton *playButton; IBOutlet UIButton *pauseButton; IBOutlet UIButton *stopButton; MPMusicPlayerController *musicPlayer; } - (IBAction)pushedPick:(id)sender; - (IBAction)pushedPlay:(id)sender; 26 | Chapter 3:Using Audio - (IBAction)pushedPause:(id)sender; - (IBAction)pushedStop:(id)sender; @end Save youi changes, anu open the Audio\icwContro||cr.n implementation lile. In the pushedPick: methou, instantiate an MPMediaPickerController oLject. The view will Le moual, which means that the usei must make a selection to leave picking moue. Ve`ll link this methou uiiectly to a Lutton in the usei inteilace: -(IBAction) pushedPick:(id)sender { MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio]; mediaPicker.delegate = self; mediaPicker.allowsPickingMultipleItems = YES; [self presentModalViewController:mediaPicker animated:YES]; [mediaPicker release]; } You must now implement the lollowing two uelegate methous, which aie useu to uis- miss the view contiollei anu hanule the ietuineu items: - (void) mediaPicker:(MPMediaPickerController *) mediaPicker didPickMediaItems:(MPMediaItemCollection *) userMediaItemCollection {
[self dismissModalViewControllerAnimated: YES]; musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; [musicPlayer setQueueWithItemCollection: userMediaItemCollection]; } - (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker { [self dismissModalViewControllerAnimated: YES]; } The MPMusicPlayeiContiollei iesponus to all the messages you might expect, e.g., play, pause, stop, volume, etc. These can Le linkeu to Luttons in the usei inteilace il you want to give useis uiiect contiol ovei these lunctions. You`ll link the iemaining methous uiiectly to Luttons in the usei inteilace: -(IBAction) pushedPlay:(id)sender { [musicPlayer play]; } -(IBAction) pushedPause:(id)sender { [musicPlayer pause]; } -(IBAction) pushedStop:(id)sender { [musicPlayer stop]; } Media Playback | 27 RememLei to ielease the instance oLjects in the dealloc methou: - (void)dealloc { [pickButton release]; [playButton release]; [pauseButton release]; [stopButton release]; [musicPlayer release]; [super dealloc]; } Save youi changes, anu click on the Audio\icwContro||cr.xib NIB lile to open it in Inteilace Builuei. Diag loui UIButton elements liom the LiLiaiy winuow into the View winuow. DouLle click on each ol them anu change the uelault text to Le Pick, Play, Pause anu Stop. Then open the Assistant Euitoi (ViewAssistant EuitoiShow Assistant Euitoi) anu Contiol-Click anu uiag to associate the Luttons with theii ie- spective IBOutlet anu IBAction outlets anu actions in the Audio\icwContro||cr.h in- teilace lile, see Figuie 3-1. Iigurc 3-1. Connccting thc app|ication`s uscr intcrjacc in |ntcrjacc Bui|dcr Save youi changes anu click on the Run Lutton in the Xcoue toolLai to Luilu anu ueploy the coue to youi uevice. 28 | Chapter 3:Using Audio RememLei that you`ll neeu to test the application on youi uevice. Once the application loaus, tap on the Pick Lutton to Liing up the pickei contiollei, select some songs, anu tap the Done Lutton.(see Figuie 3-2). Piess the Play Lutton anu the music you selecteu shoulu stait playing. Iigurc 3-2. Thc initia| nain vicw (|cjt), thc MPMcdiaPic|crContro||cr (nidd|c), and thc nain intcrjacc whi|c a song is bcing p|aycd (right) Once playLack has Legun you neeu to keep tiack ol the cuiiently playing item anu uisplay that to the usei. At the veiy least you must pioviue some way loi the usei to pause oi stop playLack, anu peihaps to change theii selection. The MPMusicPlayerCon troller class pioviues two methous: the beginGeneratingPlaybackNotifications: methou, anu a coiiesponuing endGeneratingPlaybackNotifications:. Auu the high- lighteu line Lelow to youi mediaPicker:didPickMediaItems: uelegate methou: - (void) mediaPicker:(MPMediaPickerController *) mediaPicker didPickMediaItems:(MPMediaItemCollection *) userMediaItemCollection {
[self dismissModalViewControllerAnimated: YES]; musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; [musicPlayer setQueueWithItemCollection: userMediaItemCollection]; Media Playback | 29 [musicPlayer beginGeneratingPlaybackNotifications]; } Vhen the Legin methou is invokeu the class will stait to geneiate notilications when the playei state changes anu when the cuiient playLack item changes. Youi application can access this inloimation Ly auuing itsell as an oLseivei using the NSNotification Center class: - (void) mediaPicker:(MPMediaPickerController *) mediaPicker didPickMediaItems:(MPMediaItemCollection *) userMediaItemCollection {
[self dismissModalViewControllerAnimated: YES]; musicPlayer = [MPMusicPlayerController applicationMusicPlayer]; [musicPlayer setQueueWithItemCollection: userMediaItemCollection]; [musicPlayer beginGeneratingPlaybackNotifications]; NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(handleNowPlayingItemChanged:) name:@"MPMusicPlayerControllerNowPlayingItemDidChangeNotification" object:musicPlayer]; [notificationCenter addObserver:self selector:@selector(handlePlaybackStateChanged:) name:@"MPMusicPlayerControllerPlaybackStateDidChangeNotification" object:musicPlayer]; } This will invoke the selectoi methous in the class when the appiopiiate notilication aiiives. You coulu, loi example, use the liist to upuate a UILabel in the view telling the usei the name ol the cuiiently playing song. Foi now let`s just go aheau anu implement these methous to piint messages to the console log. In the Audio\icwContro||cr.n implementation lile, auu the methou Lelow. This will Le calleu when the cuiient item Leing playeu changes: - (void)handleNowPlayingItemChanged:(id)notification { MPMediaItem *currentItem = [musicPlayer nowPlayingItem]; NSString *title = [currentItem valueForProperty:MPMediaItemPropertyTitle]; NSLog(@"Song title = %@", title); } Unusually, the MPMeuiaItem class only has one instance methou, the valueForProp erty: methou. This is Lecause the class can wiap a numLei ol meuia types, anu each type can have a laiily wiue iange ol metauata associateu with it. A lull list ol possiLle keys can Le lounu in the MPMeuiaItem class ieleience, Lut keys incluue MPMediaI temPropertyTitle, MPMediaItemPropertyArtwork, etc. You can use this to upuate the usei inteilace, e.g., changing the state ol the play anu stop Luttons when the music enus: 30 | Chapter 3:Using Audio - (void)handlePlaybackStateChanged:(id)notification { MPMusicPlaybackState playbackState = [musicPlayer playbackState]; if (playbackState == MPMusicPlaybackStatePaused) { NSLog(@"Paused"); } else if (playbackState == MPMusicPlaybackStatePlaying) { NSLog(@"Playing"); } else if (playbackState == MPMusicPlaybackStateStopped) { NSLog(@"Stopped"); } } Save youi changes, anu click on the Run Lutton in the Xcoue toolLai to Luilu anu ueploy youi coue onto youi uevice. Once youi application loaus, piess the Pick Lut- ton to Liing up the pick contiollei again, select some songs, anu piess the Done Lutton. Piess Play anu the music shoulu stait playing. You shoulu also see something similai to the log messages Lelow in the DeLuggei Console: 2011-06-01 19:23:07.602 Audio[2844:707] Song title = Affirmation 2011-06-01 19:23:07.617 Audio[2844:707] Playing You coulu go on to uevelop the application Ly uisplaying inloimation aLout the cui- iently playing anu gueueu songs. Let`s move on liom playing existing meuia anu look at how to play anu iecoiu youi own auuio on the uevice. Recording and Playing Audio The AVAudioRecorder class is pait ol the AVFounuation liamewoik anu pioviues auuio iecoiuing capaLilities loi an application. The liamewoik allows you to: Recoiu until the usei stops the iecoiuing Recoiu loi a specilieu uuiation Pause anu iesume a iecoiuing The coiiesponuing AVAudioPlayer class (also pait ol the AVFounuation liamewoik) pioviues some laiily sophisticateu lunctionality allowing you to play sounu in youi application. It can: Play sounus ol any uuiation Play sounus liom liles oi memoiy Lulleis Loop sounus Play multiple sounus simultaneously (one sounu pei auuio playei) with piecise synchionization Contiol ielative playLack level anu steieo positioning loi each sounu you aie playing Recording and Playing Audio | 31 Seek to a paiticulai point in a sounu lile, which suppoits such application leatuies as last loiwaiu anu iewinu Recording Audio Lets Luilu a simple application to iecoiu some auuio to a lile anu play it Lack latei. Open Xcoue anu stait a new View-Laseu Application, naming it Rccordcr when ieguesteu. Vhen the Xcoue pioject opens, auu both the AVFounuation anu CoieAuuio liame- woiks to the pioject in a similai mannei as we auueu the MeuiaPlayei liamewoik to the Auuio application eailiei in the chaptei. Click on the Rccordcr\icwContro||cr.h inteilace lile to open it in the Stanuaiu Euitoi anu make the lollowing changes to the template lile geneiateu loi you Ly Xcoue: #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface RecorderViewController : UIViewController <AVAudioRecorderDelegate> { IBOutlet UIButton *startStopButton; NSURL *tmpFile; AVAudioRecorder *recorder; BOOL recording; } - (IBAction)startStopButtonPressed; @end Save youi changes anu open the coiiesponuing RecorderViewController.xib lile in In- teilace Builuei. Diag anu uiop a UIButton liom the OLject LiLiaiy in the Utilities pane into the View anu change the title text to Stait Recoiuing. Then connect it to the IBOutlet anu IBAction in youi inteilace lile using the Assistant Euitoi, as in Figuie 3-3. Save youi changes anu open the Rccordcr\icwContro||cr.n implementation lile in the Stanuaiu Euitoi, making the lollowing changes to the uelault template geneiateu Ly Xcoue: #import "RecorderViewController.h" #import <CoreAudio/CoreAudioTypes.h> @implementation RecorderViewController - (IBAction)startStopButtonPressed { AVAudioSession * audioSession = [AVAudioSession sharedInstance]; if (!recording) { // Add code here... 32 | Chapter 3:Using Audio } else { // Add code here... } } - (void)dealloc { [startStopButton release]; [tmpFile release]; [recorder release]; [super dealloc]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; recording = NO; Iigurc 3-3. Connccting thc uscr intcrjacc in |ntcrjacc Bui|dcr Recording and Playing Audio | 33 } - (void)viewDidUnload { [super viewDidUnload]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end Then make the lollowing changes to the startStopButtonPressed methou: - (IBAction)startStopButtonPressed { AVAudioSession * audioSession = [AVAudioSession sharedInstance]; if (!recording) { recording = YES; [audioSession setCategory:AVAudioSessionCategoryRecord error:nil]; [audioSession setActive:YES error:nil]; [startStopButton setTitle:@"Stop Recording" forState:UIControlStateNormal]; NSMutableDictionary* recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue: [NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; tmpFile = [NSURL fileURLWithPath: [NSTemporaryDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"caf"]]]; recorder = [[AVAudioRecorder alloc] initWithURL:tmpFile settings:recordSetting error:nil]; [recorder setDelegate:self]; [recorder prepareToRecord]; [recorder record]; } else { recording = NO; [audioSession setActive:NO error:nil]; 34 | Chapter 3:Using Audio [startStopButton setTitle:@"Start Recording" forState:UIControlStateNormal]; [recorder stop]; } } Il you save youi changes anu click on the Run Lutton to Luilu anu ueploy the application to youi uevice you shoulu see the Stait Recoiuing Lutton changes to Stop Recoiu- ing when piesseu. Piessing the Lutton again shoulu change the text Lack to Stait Recoiuing. In the next section I`ll show you a way to check that the uevice is actually iecoiuing auuio. Playing Audio Open up the Rccordcr\icwContro||cr.h inteilace lile anu auu the lollowing IBOutlet instance vaiiaLle: IBOutlet UIButton *playButton; along with the lollowing IBAction methou: - (IBAction)playButtonPressed; Iigurc 3-1. Adding thc P|ay Rccording button to thc uscr intcrjacc Recording and Playing Audio | 35 Then single click on the Rccordcr\icwContro||cr.xib lile to open it in Inteilace Builuei. Diag anu uiop anu new UIButton into the view anu change the title text to Le Play Recoiuing. Use the Assistant Euitoi to connect the new Lutton to the iecently auueu IBOutlet anu IBAction in the inteilace lile, see Figuie 3-+. Save youi changes, ietuin to the Rccordcr\icwContro||cr.n implementation lile anu auu the lollowing methou implementation: - (IBAction)playButtonPressed { AVAudioSession * audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; AVAudioPlayer * player = [[AVAudioPlayer alloc] initWithContentsOfURL:tmpFile error:nil]; [player prepareToPlay]; [player play]; } Save youi changes anu click on the Run Lutton in the Xcoue toolLai to Luilu anu ueploy the application to youi uevice. You shoulu see something like Figuie 3-5. Il you now tap on the Stait Recoiuing Lutton the title ol the Lutton shoulu change to Stop Recoiuing; speak into the iPhone`s miciophone loi lew seconus anu tap the Lutton again. Then tap on the Play Recoiuing Lutton anu you shoulu heai youisell speaking. Iigurc 3-5. Thc jinishcd Rccordcr app|ication 36 | Chapter 3:Using Audio CHAPTER 4 Using the Accelerometer An acceleiometei measuies the lineai acceleiation ol the uevice. The oiiginal iPhone, anu liist geneiation iPou touch, use the LIS302DL 3-axis MEMS Laseu acceleiometei piouuceu Ly STMicioelectionics. Latei iPhone anu iPou touch mouels use a similai LIS331DL chip, also manulactuieu Ly STMicioelectionics. Both ol these acceleiometeis can opeiate in two moues, allowing the chip to measuie eithei 2g anu Sg. In Loth moues the chip can sample at eithei 100 Mhz oi +00 Mhz. Apple opeiates the acceleiometei in the 2g moue (piesumaLly at 100 Mhz) with a nominal iesolution ol 0.01Sg. In the Sg moue the iesolution woulu Le loui times coaisei, anu the piesumption must Le that Apple ueciueu Lettei iesolution woulu Le moie uselul than a wiuei iange. Unuei noimal conuitions the uevice will actually measuie g-loices to appioximately 2.3g howevei measuiements aLove a 2g aie un- caliLiateu. Vhile it shoulu in theoiy Le possiLle to change the opeiating moue ol the acceleiometei, theie is cuiiently no puLlisheu API that allows you to uo so within the SDK. About the Accelerometer The iPhone`s acceleiometei measuies the lineai acceleiation ol the uevice so it can iepoit the uevice`s ioll anu pitch, Lut not its yaw. Il you aie uealing with a uevice that has a uigital compass you can comLine the acceleiometei anu magnetometei ieauings to have ioll, pitch, anu yaw measuiements (see Chaptei 5 loi uetails on how to access the magnetometei). 37 Yaw, pitch, anu ro|| ielei to the iotation ol the uevice in thiee axes. Il you think aLout an aiicialt in the sky, pushing the nose uown oi pulling it up mouilies the pitch angle ol the aiicialt. Howevei, il you keep the nose stiaight aheau you can also mouily the ioll ol the aiicialt using the llaps; one wing will come up, the othei will go uown. By keeping the wings level you can use the tail llap to change the heauing (oi yaw) ol the aiicialt, iotating it in a 2D plane. The acceleiometei iepoits thiee liguies: X, Y, anu Z (see Figuie +-1). Acceleiation values loi each axis aie iepoiteu uiiectly Ly the haiuwaie as G-loice values. Theieloie, a value ol 1.0 iepiesents a loau ol appioximately 1-giavity (Eaith`s giavity). X coiie- sponus to ioll, Y to pitch, anu Z to whethei the uevice is liont siue up oi liont siue uown, with a value ol 0.0 Leing iepoiteu when the iPhone is euge-on. Vhen uealing with acceleiation measuiements you must keep in minu that the accel- eiometei is measuiing just that: the lineai acceleiation ol the uevice. Vhen at iest (in whatevei oiientation) the liguies iepiesent the loice ol giavity acting on the uevice, anu coiiesponu to the ioll anu pitch ol the uevice (in the X anu Y uiiections at least). But while in motion, the liguies iepiesent the acceleiation uue to giavity, plus the accelei- ation ol the uevice itsell ielative to its iest liame. Writing an Accelerometer Application Let`s go aheau anu implement a simple application to illustiate how to appioach the acceleiometei. Open Xcoue anu stait a new View-Laseu application loi the iPhone, anu name the pioject Acceleiometei when piompteu loi a lilename. The iaw acceleiometei uata can also Le accesseu using the Coie Motion liamewoik, which was new in iOS +.0. I talk aLout how to uo this in Chaptei 6. It is theieloie possiLle, even likely, that the UIAccelerome ter class uiscusseu in this chaptei my Le uepiecateu in a lutuie iOS ielease. Click on the Accc|cronctcr\icwContro||cr.xib lile to open it into Inteilace Builuei. Since you want to Loth iepoit the iaw liguies liom the acceleiometei anu also uisplay them using a piogiess Lai, go aheau anu uiag anu uiop thiee UIProgressView contiols liom the OLject LiLiaiy into the View winuow. Then auu two UILabel elements loi each piogiess Lai: one to holu the X, Y, oi Z laLel anu the othei to holu the acceleiometei measuiements. Altei you uo that, the view shoulu look something a lot like Figuie +-2. Go aheau anu close the Utilities panel anu click to open the Assistant Euitoi. Then Contiol-Click anu uiag liom the thiee UIProgressView elements, anu the thiee UILa bel elements to the Acc|cronctcr\icwContro||cr.h heauei lile. The heauei lile shoulu 38 | Chapter 4:Using the Accelerometer Le uisplayeu in the Assistant Euitoi on the iight-hanu siue ol the Xcoue + inteilace (see Figuie +-3). This will automatically cieate anu ueclaie thiee UILabel anu thiee UIProgressView vai- iaLles as IBOutlet oLjects. Since they aien`t going to Le useu outsiue the class, theie isn`t much point in ueclaiing them as class piopeities, which you`u uo Ly Contiol-click anu uiag liom the element to outsiue the cuily Liace. Altei uoing this the coue shoulu look like this: #import <UIKit/UIKit.h> @interface AccelerometerViewController : UIViewController { Iigurc 1-1. Thc iPhonc accc|cronctcr axcs Writing an Accelerometer Application | 39 IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; } @end Close the Assistant Euitoi, ietuin to the Stanuaiu Euitoi anu click on the Accc|cronc- tcr\icwContro||cr.h inteilace lile. Now go aheau anu set up a UIAccelerometer instance. Also ueclaie the class as a UIAccelerometerDelegate. Heie`s how the shoulu look when you aie uone: #import <UIKit/UIKit.h> @interface AccelerometerViewController : UIViewController <UIAccelerometerDelegate> { IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; Iigurc 1-2. Thc Accc|cronctcr app|ication U| 40 | Chapter 4:Using the Accelerometer IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; UIAccelerometer *accelerometer; } @end Heie we ueclaie that the class implements the UIAccelerometer uelegate piotocol. Make suie you`ve saveu youi changes anu click on the coiiesponuing Accc|cronctcr- \icwContro||cr.n implementation lile to open it in the Xcoue euitoi. You uon`t actually have to uo veiy much heie, as Inteilace Builuei hanuleu most ol the heavy lilting Ly auuing coue to piopeily hanule the usei inteilace elements. Heie`s what the lile shoulu look like when you aie uone: #import "AccelerometerViewController.h" @implementation AccelerometerViewController - (void)viewDidLoad { Iigurc 1-3. Connccting thc U| c|cncnts to your codc in |ntcrjacc Bui|dcr Writing an Accelerometer Application | 41 accelerometer = [UIAccelerometer sharedAccelerometer]; accelerometer.updateInterval = 0.1; accelerometer.delegate = self; [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)viewDidUnload { [xBar release]; xBar = nil; [yBar release]; yBar = nil; [zBar release]; zBar = nil; [xLabel release]; xLabel = nil; [yLabel release]; yLabel = nil; [zLabel release]; zLabel = nil; [super viewDidUnload]; } - (void)dealloc { [xLabel release]; [yLabel release]; [zLabel release]; [xBar release]; [yBar release]; [zBar release]; accelerometer.delegate = nil; [accelerometer release]; [super dealloc]; } - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark UIAccelerometerDelegate Methods - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)acceleration { xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x]; xBar.progress = ABS(acceleration.x); 42 | Chapter 4:Using the Accelerometer yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y]; yBar.progress = ABS(acceleration.y); zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z]; zBar.progress = ABS(acceleration.z); } @end The UIAccelerometer is a singleton oLject, so we giaL a ieleience to the singleton iathei than allocate anu initialize a new instance ol the class. Ve set the upuate inteival to 0.1, hence the accelerometer:didAccelerate: methou will Le calleu 10 times eveiy seconu. Ve ueclaie that this class is the uelegate loi the UIAccelerometer. Ve implement the accelerometer:didAccelerate: uelegate methou anu use it to set the X, Y, anu Z laLels to the iaw acceleiometei ieauings each time it is calleu. The piogiess Lai values aie set to the aLsolute value (the value without iegaiu to sign) ol the acceleiometei ieauing. OK, you`ie uone. Beloie you click the Run Lutton, make suie you`ve conliguieu the pioject to ueploy onto youi iPhone oi iPou touch to test it. Since this application makes use ol the acceleiometei, anu iPhone Simulatoi uoesn`t have one, you`ie going to have to test it uiiectly on the uevice. Il all goes well, you shoulu see something that looks a lot like Figuie +-+. Determining Device Orientation Apple pioviue an easy way ol ueteimining the uevice oiientation, a call to UIDevice will ietuin the cuiient oiientation ol the uevice: UIDevice *device = [UIDevice currentDevice]; UIDeviceOrientation orientation = device.orientation; This call will ietuin a UIDeviceOrientation that can Le: UIDeviceOrientationUnknown, UIDeviceOrientationPortrait, UIDeviceOrientationPortraitUpsideDown, UIDeviceOr ientationLandscapeLeft, UIDeviceOrientationLandscapeRight oi UIDeviceOrientation FaceUp. The sensoi unueilying this call is the acceleiometei, anu you`ll see latei in this chaptei how to ietiieve the uevice oiientation uiiectly liom the iaw acceleiometei ieauings. As ol the time ol wiiting unuei iOS +.3 the uevice uoes not coiiectly iepoit a piopei oiientation when youi application is liist launcheu, with UIDevice ietuining null when gueiieu. Determining Device Orientation | 43 Lets go aheau anu mouily the Acceleiometei application to uisplay the uevice oiienta- tion. Click on the Accc|cronctcr\icwContro||cr.h inteilace lile to open it in the Stanuaiu Euitoi anu auu the lollowing coue, highlighteu Lelow, to the class inteilace: @interface AccelerometerViewController : UIViewController <UIAccelerometerDelegate> { IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; IBOutlet UILabel *orientationLabel; UIAccelerometer *accelerometer; } - (NSString *)stringFromOrientation:(UIDeviceOrientation) orientation; @end Iigurc 1-1. Thc Accc|cronctcr app|ication running on an iPhonc 1 sitting jacc-up on ny dcs|, ncasuring a 1-gravity accc|cration straight down 44 | Chapter 4:Using the Accelerometer Ve`ie going to uisplay the cuiient oiientation using in a UILabel, so we`ie going to have to wiite a convenience methou stringFromOrienation: to conveit the UIDeviceOrienta tion type ietuineu Ly the UIDevice to an NSString to uisplay in that laLel. Make suie you`ve saveu youi changes, anu click on the coiiesponuing Accc|cronctcr- \icwContro||cr.n implementation lile anu auu the lollowing methou: - (NSString *)stringFromOrientation:(UIDeviceOrientation) orientation { NSString *orientationString; switch (orientation) { case UIDeviceOrientationPortrait: orientationString = @"Portrait"; break; case UIDeviceOrientationPortraitUpsideDown: orientationString = @"Portrait Upside Down"; break; case UIDeviceOrientationLandscapeLeft: orientationString = @"Landscape Left"; break; case UIDeviceOrientationLandscapeRight: orientationString = @"Landscape Right"; break; case UIDeviceOrientationFaceUp: orientationString = @"Face Up"; break; case UIDeviceOrientationFaceDown: orientationString = @"Face Down"; break; case UIDeviceOrientationUnknown: orientationString = @"Unknown"; break; default: orientationString = @"Not Known"; break; } return orientationString; } Once you have auueu the stringFromOrienation: methou, auu the lollowing coue, highlighteu Lelow, to the existing accelerometer:didAccelerate: methou in the same class: - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)acceleration { xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x]; xBar.progress = ABS(acceleration.x); yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y]; yBar.progress = ABS(acceleration.y); zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z]; zBar.progress = ABS(acceleration.z); Determining Device Orientation | 45 UIDevice *device = [UIDevice currentDevice]; orientationLabel.text = [self stringFromOrientation:device.orientation]; } Make suie you`ve saveu youi changes, anu click on the Accc|cronctcr\icwContro|- |cr.xib lile to open it in Inteilace Builuei. Diag anu uiop a UILabel liom the OLject LiLiaiy into the View. Go aheau anu iesize anu centei up the text using the AttiiLutes inspectoi liom the Utilities panel. Close the Utilities panel anu open the Assistant Euitoi, which shoulu show the coiie- sponuing inteilace lile loi the view contiollei. Contiol-click anu uiag anu connect the UILabel element to the orientationLabel outlet in youi coue, as in Figuie +-5. Save youi changes, anu click Run Lutton in the Xcoue toolLai to compile anu ueploy youi application to youi uevice. Il all goes well you shoulu see something much like Figuie +-6. As you move the uevice aiounu, the laLel will upuate itsell to iellect the cuiient uevice oiientation. Determining Device Orientation Directly Using the Accelerometer Insteau ol gueiying UIDevice you can use the iaw acceleiometei ieauings to ueteimine the uevice oiientation uiiectly using the atan2 lunction as shown Lelow: Iigurc 1-5. Connccting thc oricntation out|ct to thc U| 46 | Chapter 4:Using the Accelerometer float x = -[acceleration x]; float y = [acceleration y]; float angle = atan2(y, x); Foi any ieal aiguments x anu y that aie not Loth egual to zeio, atan2(y, x) is the angle in iauians Letween the positive x-axis ol a plane anu the point given Ly the specilieu cooiuinates on it. The angle is positive loi countei-clockwise angles, anu negative loi clockwise angles. Let`s go aheau anu mouily the accelerometer:didAccelerate: methou to calculate the oiientation. Click on the Accc|cronctcr\icwContro||cr.n implementation lile to open it in the Stanuaiu Euitoi anu ieplace these lines: UIDevice *device = [UIDevice currentDevice]; orientationLabel.text = [self stringFromOrientation:device.orientation]; with the coue highlighteu Lelow: - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)acceleration { xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x]; xBar.progress = ABS(acceleration.x); Iigurc 1-. Thc Accc|cronctcr app|ication rcporting thc dcvicc oricntation Determining Device Orientation | 47 yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y]; yBar.progress = ABS(acceleration.y); zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z]; zBar.progress = ABS(acceleration.z); float x = -[acceleration x]; float y = [acceleration y]; float angle = atan2(y, x); if(angle >= 2.25 && angle <= 0.75) { orientationLabel.text = [self stringFromOrientation:UIInterfaceOrientationPortrait]; } else if(angle >= 0.75 && angle <= 0.75){ orientationLabel.text = [self stringFromOrientation:UIInterfaceOrientationLandscapeRight]; } else if(angle >= 0.75 && angle <= 2.25) { orientationLabel.text = [self stringFromOrientation:UIInterfaceOrientationPortraitUpsideDown]; } else if(angle <= 2.25 || angle >= 2.25) { orientationLabel.text = [self stringFromOrientation:UIInterfaceOrientationLandscapeLeft]; } } Il you save youi changes, anu click on the Run Lutton to ieLuilu anu ueploy youi application onto youi uevice, theie shoulu see little oi no change in the application`s opeiation. Howevei, having access to each component ol the oiientation opens up many oppoitunities loi cieating tilt-Laseu contiols. Obtaining Notifications when Device Orientation Changes In auuition to uiiectly gueiying the UIDevice oLject loi the cuiient oiientation, a pio- giam can ieguest to Le notilieu ol changes in the uevice`s oiientation Ly iegisteiing itsell as an oLseivei. Ve can once again mouily the Acceleiometei application to make use ol this leatuie. Open the Accc|cronctcr\icwContro||cr.n lile in the Stanuaiu Euitoi anu uelete the coue auueu in the pievious section liom the accelerometer:didAccelerate: methou. Il you guickly ieLuilu the application at this point anu ueploy it to youi uevice you will see that the UILabel now ieaus LaLel anu will no longei Le upuateu as the uevice oiientation changes. Once you`ve conliimeu that, auu the lollowing methou: -(void) viewWillAppear:(BOOL) animated{ [super viewWillAppear:animated]; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
} Heie we ask the UIDevice class to stait geneiating oiientation notilications, anu we iegistei the view contiollei as an oLseivei. Next auu the selectoi methou, shown Lelow: -(void) receivedRotatation:(NSNotification*) notification { UIDevice *device = [UIDevice currentDevice]; orientationLabel.text = [self stringFromOrientation:device.orientation]; } Heie we simply upuate the UILabel with the uevice oiientation eveiy time a UIDevi ceOrientationDidChangeNotification event is ieceiveu. Finally we neeu to iememLei to iemove the piogiam as an oLseivei to stop the genei- ation ol messages uuiing the teai uown ol oui view contiollei. Auu the lollowing methou to youi coue: -(void) viewWillDisappear:(BOOL) animated{ [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver: self]; [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; } Il you once again save youi changes anu click on the Run Lutton to ieLuilu anu ueploy the application to youi uevice, you will again see little oi no change in the application`s opeiation. Which Way Is Up? A uselul thing to know a lot ol the time is the answei to the guestion which way is up? You can use the same methou useu eailiei to ueteimine the uevice oiientation anu giaphically show this in the View. Fiist you`ie going to neeu an image ol an aiiow. Downloau, oi uiaw in the giaphics package ol youi choice, an image ol an aiiow pointing to the lelt on a tianspaient Lackgiounu. Save it as, oi conveit it to, a PNG loimat lile. Diag-anu-uiop this into youi Xcoue Pioject iememLeiing to tick the Copy items into uestination gioup`s loluei (il neeueu) check Lox in the pop up uialog that appeais when you uiop the liles into Xcoue (see Figuie +-7). Click on the Accc|cronctcr\icwContro||cr.xib lile to open it, anu uiag-anu-uiop a UII mageView liom the OLject LiLiaiy onto youi View. Position it Lelow the thiee UIProg ressBar elements, anu iesize the Lounuing Lox to Le a sguaie using the Size inspectoi ol the Utility Pane. In the AttiiLutes inspectoi ol the Utility Pane, change the Image piopeity to Le the aiiow image that you auueu to youi pioject. Set the View moue to Le Aspect Fit. Uncheck the Opague Lox in the Diawing section so that the aiiow Determining Device Orientation | 49 is ienueieu coiiectly with a tianspaient Lackgiounu. Finally, use the Image uiop- uown to select the aiiow.png image to Le uisplayeu in the UIImageView (see Figuie +-S). Close the Utility Pane anu open the Assistant Euitoi. Contiol-click anu uiag liom the UIImageView in youi View to the arrowImage outlet in the Assistant Euitoi, as in Fig- uie +-9, anu auu an arrrowImage outlet. Altei uoing so youi inteilace lile shoulu look as Lelow: @interface AccelerometerViewController : UIViewController <UIAccelerometerDelegate> { IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; IBOutlet UIImageView *arrowImage; IBOutlet UILabel *orientationLabel; UIAccelerometer *accelerometer; Iigurc 1-7. Adding an arrow inagc to thc Accc|cronctcr projcct 50 | Chapter 4:Using the Accelerometer } Close the Assistant Euitoi anu switch to the Stanuaiu Euitoi. Go aheau anu click on the Accc|cronctcr\icwContro||cr.n implementation lile. Auu the coue highlighteu Le- low to the accelerometer:didAccelerate: methou: - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)acceleration { xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x]; xBar.progress = ABS(acceleration.x); yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y]; yBar.progress = ABS(acceleration.y); zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z]; zBar.progress = ABS(acceleration.z); float x = -[acceleration x]; float y = [acceleration y]; float angle = atan2(y, x); [arrowImage setTransform:CGAffineTransformMakeRotation(angle)]; } Iigurc 1-8. Adding thc U||nagc\icw to your intcrjacc Determining Device Orientation | 51 That`s it. Save youi changes again anu click on the Run Lutton to compile anu ueploy the application to youi uevice. Keep the uevice lace towaius you anu iotate it in llat plane, you shoulu see that the aiiow moves as you uo so, keeping its oiientation point- ing upwaius (see Figuie +-9). Convenience Methods for Orientation Apple pioviues convenience methous to ueteimine whethei the cuiient uevice oiien- tation is poitiait: UIDevice *device = [UIDevice currentDevice]; UIDeviceOrientation orientation = device.orientation; BOOL portrait = UIDeviceOrientationIsPortrait( orientation ); oi lanuscape: BOOL landscape = UIDeviceOrientationIsLandscape( orientation ); These methous ietuin YES il the uevice is in poitiait oi lanuscape moue iespectively; otheiwise they ietuin NO. Iigurc 1-9. Adding a out|ct to your codc 52 | Chapter 4:Using the Accelerometer Detecting Shaking Apple`s shake-uetection algoiithm analyses eight to ten successive paiis ol iaw accel- eiometei tiiplet values anu ueteimines the angle Letween these ieauings. Il the change in angulai velocity Letween successive uata points is laige then the algoiithm uetei- mines that a UIEventSubtypeMotionShake has occuiieu, anu the motionBegan:withE vent: uelegate methou is calleu. Conveisely, il the change in angulai velocity is small anu a shake event has Leen tiiggeieu, the motionEnded:withEvent: uelegate methou is calleu. The iPhone is Lettei at uetecting siue-to-siue iathei than liont-to-Lack oi up-anu-uown motions. Take this into account in the uesign ol youi application. Theie aie thiee motion uelegate methous, miiioiing the methous loi gestuie hanuling: motionBegin:withEvent:, motionEnded:withEvent: anu motionCancelled:withEvent:. The liist inuicates the stait ol a motion event, the seconu the enu ol this event. You cannot geneiate a new motion event loi a seconu (oi two) lollowing the liist event. The Iigurc 1-10. Thc arrow points upwards (dcvicc hc|d vcrtica||y in jront oj thc uscr) Detecting Shaking | 53 linal uelegate methou is calleu when a motion is inteiiupteu Ly a system event, such as an incoming phone call. Let`s go aheau anu auu shake uetection to oui Acceleiometei application. You`ll neeu to auu anothei UILabel to the UI that will change uepenuing on the motion event status. Click on the Accc|cronctcr\icwContro||cr.h inteilace lile to open it in the Stanuaiu Euitoi anu auu anothei UILabel maikeu as an IBOutlet to the class uelinition: @interface AccelerometerViewController : UIViewController <UIAccelerometerDelegate> { IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; IBOutlet UILabel *orientationLabel; IBOutlet UILabel *shakeLabel; IBOutlet UIImageView *arrowImage; UIAccelerometer *accelerometer; } Save youi changes anu click on the Accc|cronctcr\icwContro||cr.n implementation lile to open it in the Xcoue euitoi. The easiest way to ensuie that the view contiollei ieceives motion events is to piomote it to Fiist Responuei in the viewDidAppear: methou. RememLei to make the contiollei iesign as liist iesponuei when the view goes away. Auu the viewDidAppear: methou anu mouily the existing viewWillDisappear: methou as highlighteu Lelow. Use the canBe comeFirstResponder methou to inuicate that the view contiollei can inueeu Lecome the Fiist Responuei: - (BOOL)canBecomeFirstResponder { return YES; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self becomeFirstResponder]; } -(void) viewWillDisappear: (BOOL) animated{ [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver: self]; [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; [self resignFirstResponder]; } 54 | Chapter 4:Using the Accelerometer Save youi changes anu click on the Accc|cronctcr\icwContro||cr.xib lile loi the last time. Diag-anu-uiop a UILabel into the View liom the OLject LiLiaiy anu connect it to the shakeLabel outlet as in Figuie +-11. Save youi changes anu ietuin to the Accc|cronctcr\icwContro||cr.n lile in the euitoi, anu auu the lollowing uelegate methous to the implementation: - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { if ( motion == UIEventSubtypeMotionShake ) { shakeLabel.text = @"SHAKE"; shakeLabel.textColor = [UIColor redColor]; } return; } - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { if ( motion == UIEventSubtypeMotionShake ) { shakeLabel.text = @"NO SHAKE"; shakeLabel.textColor = [UIColor greenColor]; } return; } - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event { if ( motion == UIEventSubtypeMotionShake ) { Iigurc 1-11. Connccting thc sha|cLabc| out|ct Detecting Shaking | 55 shakeLabel.text = @"SHAKE CANCELLED"; shakeLabel.textColor = [UIColor blackColor]; } return; } Save youi changes anu click on the Run Lutton in the Xcoue toolLai. Altei the appli- cation is Luilt anu ueployeu to youi uevice, tiy shaking the phone. You shoulu see something veiy much like Figuie +-12. Iigurc 1-12. Sha|c dctcction on thc iPhonc 56 | Chapter 4:Using the Accelerometer CHAPTER 5 Using the Magnetometer The magnetometei is a magnetoiesistive peimalloy sensoi lounu in the iPhone 3GS, iPhone + anu iPau 2, in auuition to the acceleiometei. The iPhone 3GS uses the AN-203 integiateu ciicuit piouuceu Ly Honeywell, while the iPhone + anu iPau 2 make use ol the newei AKMS975 piouuceu Ly AKM Semiconuuctoi. The sensoi is locateu towaius the top iight hanu coinei ol the uevice, anu measuies lielus within a 2 gauss (200 miciotesla) iange, anu is sensitive to magnetic lielus ol less than 100 miciogauss (0.01 miciotesla). The Eaith`s magnetic lielu is ioughly 0.6 gauss (60 miciotesla). The lielu aiounu a iaie eaith magnet can Le 1+,000 gauss oi moie. The magnetometei measuies the stiength ol the magnetic lielu suiiounuing the uevice. In the aLsence ol any stiong local lielus, these measuiements will Le ol the amLient magnetic lielu ol the Eaith, allowing the uevice to ueteimine its heauing with iespect to the geomagnetic Noith Pole anu act as a uigital compass. The geomagnetic heauing anu tiue heauing ielative to the geogiaphical Noith Pole can vaiy wiuely, Ly seveial tens ol uegiees uepenuing on youi location. About the Magnetometer ComLining the heauing (yaw) inloimation (see Figuie 5-1) ietuineu Ly this uevice with the ioll anu pitch inloimation ietuineu Ly the acceleiometei will let you ueteimine the tiue oiientation ol the uevice in ieal time. As well as iepoiting the cuiient location, the CLLocationManager class can, in the case wheie the haiuwaie suppoits it, iepoit the cuiient heauing ol the uevice. Il location upuates aie also enaLleu, the location managei ietuins Loth tiue heauing anu magnetic heauing values. Il location upuates aie not enaLleu, the location managei ietuins only the magnetic heauing value. 57 Magnetic heauing upuates aie availaLle even il the usei has switcheu oll location upuates in the Settings application. Auuitionally, useis aie QRW piompteu to give peimission to use heauing uata, as it is assumeu that magnetic heauing inloimation cannot compiomise usei piivacy. On an enaLleu uevice the magnetic heauing uata shoulu theieloie al- ways Le availaLle to youi application. As mentioneu pieviously, the magnetometei ieauings will Le allecteu Ly local magnetic lielus, so the CLLocationManager may attempt to caliLiate its heauing ieauings Ly uis- Iigurc 5-1. Using thc nagnctonctcr (a.|.a. thc digita| conpass) in thc iPhonc 3GS you can dctcrninc thc hcading (yaw) oj thc dcvicc 58 | Chapter 5:Using the Magnetometer playing a heauing caliLiation panel (see Figuie 5-2) Leloie it staits to issue upuate messages. Howevei, Leloie it uoes so it will call the locationManagerShouldDisplayHeadingCali bration: uelegate methou: - (BOOL)locationManagerShouldDisplayHeadingCalibration: (CLLocationManager *)manager { return YES; } Il you ietuin YES liom this methou, the CLLocationManager will pop up the caliLiation panel on top ol the cuiient winuow. The caliLiation panel piompts the usei to move the uevice in a liguie-eight pattein so that Coie Location can uistinguish Letween the Eaith`s magnetic lielu anu any local magnetic lielus. The panel will iemain visiLle until caliLiation is complete oi until you uismiss it Ly calling the dismissHeadingCalibra tionDisplay: methou in the CLLocationManager class. Writing a Magnetometer Application Let`s go aheau anu implement a simple view-Laseu application to illustiate how to use the magnetometei. Open Xcoue anu stait a new iPhone pioject, select a View-Laseu Application template, anu name the pioject Compass when piompteu loi a lilename. Iigurc 5-2. Thc Hcading Ca|ibration Panc| Writing a Magnetometer Application | 59 Since you`ll Le making use ol the Coie Location liamewoik, the liist thing you neeu to uo is auu it to oui new pioject. Click on the Compass pioject lile in the Pioject navigatoi winuow on the iight in Xcoue, select the Taiget anu click on the Builu Phases taL, click on the Link with LiLiaiies uiop uown anu click on the - Lutton to open the lile pop- up winuow. Select CorcLocation.jrancwor| liom the list ol availaLle liamewoiks anu click the Auu Lutton. You`ie going to Luilu an application that will act as a compass, so you`ie going to neeu an image ol an aiiow to act as the compass neeule. Downloau oi uiaw in the giaphics package ol youi choice, an image ol an aiiow pointing upwaius on a tianspaient Lack- giounu. Save oi conveit it to, a PNG loimat lile. Diag-anu-uiop this into the Xcoue Pioject, iememLeiing to tick the Copy items into uestination gioup`s loluei (il nee- ueu) check Lox in the pop up uialog that appeais when you uiop the liles into Xcoue. Click on Conpass\icwContro||cr.xib lile to open it in Inteilace Builuei. Diag anu uiop a UIImageView liom the OLject LiLiaiy into the View, positioning it ioughly in the centei ol youi winuow, iesizing the Lounuing Lox to Le a sguaie, as in Figuie 5-3. In the AttiiLutes inspectoi ol the Utilities pane set the View moue to Le Aspect Fit, uncheck the Opague checkLox in the Diawing section, anu select the aiiow image that you auueu to youi pioject in the Image uiop uown. Next uiag-anu-uiop loui UILabel elements liom the OLject LiLiaiy into the View, po- sition the loui laLels as in Figuie 5-3, anu change the text in the lelt most two to ieau Magnetic Heauing: anu Tiue Heauing:. Close the Utility pane anu switch liom the Stanuaiu to the Assistant Euitoi. Contiol- Click anu uiag liom the two iight most UILabel elements to the assistant euitoi to cieate a magneticHeadingLabel anu trueHeadingLabel outlet, anu then again loi the UIImage View to cieate an arrowImage outlet, see Figuie 5-3. Then click on the Conpass\icwContro||cr.h inteilace lile anu go aheau anu ueclaie the class as a CLLocationManagerDelegate, iememLeiing to impoit the CorcLocation.h heauei lile. Altei uoing so the inteilace shoulu look like this: #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface CompassViewController : UIViewController <CLLocationManagerDelegate> { IBOutlet UIImageView *arrowImage; IBOutlet UILabel *magneticHeadingLabel; IBOutlet UILabel *trueHeadingLabel; } @end Save youi changes, anu click on the coiiesponuing Conpass\icwContro||cr.n imple- mentation lile. Uncomment the viewDidLoad methou anu the lollowing coue to the 60 | Chapter 5:Using the Magnetometer implementation. This will cieate an instance ol the CLLocationManager class, anu will senu Loth location anu heauing upuate messages to the uesignateu uelegate class: - (void)viewDidLoad { [super viewDidLoad]; CLLocationManager *locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; if( [CLLocationManager locationServicesEnabled] && [CLLocationManager headingAvailable]) { [locationManager startUpdatingLocation]; [locationManager startUpdatingHeading]; } else { NSLog(@"Can't report heading"); } } It is moie impoitant to check whethei heauing inloimation is availaLle than it is to check whethei location seivices aie availaLle. The availaLility ol heauing inloima- tion is iestiicteu to the latest geneiation ol uevices. You can (optionally) liltei the heauing upuate messages using an angulai liltei. Changes in heauing ol less than this amount will not geneiate an upuate message to the uelegate, loi example: locationManager.headingFilter = 5; // 5 degrees Iigurc 5-3. Connccting thc out|cts to thc U| c|cncnts in |ntcrjacc Bui|dcr Writing a Magnetometer Application | 61 The uelault value ol this piopeity is kCLHeadingFilterNone. You shoulu use this value il you want to Le notilieu ol all heauing upuates. In this example, leave the liltei set to the uelault value. Howevei il you want to liltei messages liom Coie Location this way, auu the aLove line to youi viewDidLoad methou insiue the il-Llock: if( [CLLocationManager locationServicesEnabled] && [CLLocationManager headingAvailable]) { [locationManager startUpdatingLocation]; [locationManager startUpdatingHeading]; locationManager.headingFilter = 5; // 5 degrees } else { ... code ... } The CLLocationManagerDelegate piotocol calls the locationManager:didUpdateHead ing: uelegate methou when the heauing is upuateu. You`ie going to use this methou to upuate the usei inteilace. Auu the lollowing coue to youi view contiollei: - (void)locationManager:(CLLocationManager*)manager didUpdateHeading:(CLHeading*)newHeading { if (newHeading.headingAccuracy > 0) { float magneticHeading = newHeading.magneticHeading; float trueHeading = newHeading.trueHeading; magneticHeadingLabel.text = [NSString stringWithFormat:@"%f", magneticHeading]; trueHeadingLabel.text = [NSString stringWithFormat:@"%f", trueHeading]; float heading = 1.0f * M_PI * newHeading.magneticHeading / 180.0f; arrowImage.transform = CGAffineTransformMakeRotation(heading); } } Il location upuates aie also enaLleu, the location managei ietuins Loth tiue heauing anu magnetic heauing values. Il location upuates aie not enaLleu, oi the location ol the uevice is not yet known, the location managei ietuins only the magnetic heauing value anu the value ietuineu Ly this call will Le -1. Save youi changes, then click on the Run Lutton in the Xcoue toolLai to ueploy youi new application to youi uevice. Il you holu the uevice in Face Up oi Poitiait moue you shoulu see something veiy similai to Figuie 5-+ Lelow. As it stanus oui application has a ciitical llaw. Il the usei oiientates the uevice into Lanuscape Moue, the iepoiteu heauings will Le incoiiect, oi at least look incoiiect to the usei. Determining the Heading in Landscape Mode The magnetic anu tiue heauings aie coiiect when the iPhone uevice is helu like a tia- uitional compass, in poitiait moue, il the usei iotates the uevice, the heauing ieauings 62 | Chapter 5:Using the Magnetometer will still Le in the oiiginal liame ol ieleience. Even though the usei has not changeu the uiiection they aie lacing the heauing values iepoiteu Ly the uevice will have changeu. You`ie going to have to coiiect loi oiientation Leloie iepoiting heauings Lack to the usei, see Figuie 5-5. In the Pioject navigatoi, click on the Conpass\icwContro||cr.xib lile to open it in In- teilace Builuei, then uiag-anu-uiop anothei UILabel liom the OLject LiLiaiy in the Utility pane into the View winuow. Use the Assistant Euitoi connect the laLel to a new outlet in the Conpass\icwContro||cr.h inteilace lile, as in Figuie 5-6. Altei uoing so, the inteilace lile shoulu look as Lelow: @interface CompassViewController : UIViewController <CLLocationManagerDelegate> { IBOutlet UILabel *trueHeadingLabel; IBOutlet UILabel *magneticHeadingLabel; IBOutlet UILabel *orientationLabel; IBOutlet UIImageView *arrowImage; } Ve`ie going to use this to iepoit the cuiient uevice oiientation as we uiu in the Accel- eiometei application in Chaptei +. Iigurc 5-1. Thc Conpass app|ication running on thc iPhonc 3GS Writing a Magnetometer Application | 63 Close the Assistant Euitoi anu ieopen the Conpass\icwContro||cr.h inteilace lile in the Stanuaiu Euitoi. Go aheau anu auu the lollowing convenience methous to the class uelinition: - (float)magneticHeading:(float)heading fromOrientation:(UIDeviceOrientation) orientation; - (float)trueHeading:(float)heading fromOrientation:(UIDeviceOrientation) orientation; - (NSString *)stringFromOrientation:(UIDeviceOrientation) orientation; Save youi changes, anu open the Conpass\icwContro||cr.n implementation lile. Since the CLHeading oLject is ieau only anu you can`t mouily it uiiectly, you`l neeu to auu the lollowing methou to coiiect the magnetic heauing loi the uevice oiientation: - (float)magneticHeading:(float)heading fromOrientation:(UIDeviceOrientation) orientation { Iigurc 5-5. Thc rca| hcading oj thc uscr whcn thcy arc ho|ding thc dcvicc in Landscapc nodc is thc rcportcd hcading - 90 dcgrccs 64 | Chapter 5:Using the Magnetometer float realHeading = heading; switch (orientation) { case UIDeviceOrientationPortrait: break; case UIDeviceOrientationPortraitUpsideDown: realHeading = realHeading + 180.0f; break; case UIDeviceOrientationLandscapeLeft: realHeading = realHeading + 90.0f; break; case UIDeviceOrientationLandscapeRight: realHeading = realHeading - 90.0f; break; default: break; } while ( realHeading > 360.0f ) { realHeading = realHeading - 360; } return realHeading; } Iigurc 5-. Connccting thc oricntation |abc| in |ntcrjacc Bui|dcr Writing a Magnetometer Application | 65 The UIDeviceOiientationFaceUp anu UIDeviceOiientationFaceDown oiientation cases aie unuelineu anu the usei is piesumeu to Le holuing the uevice in UIDevi- ceOiientationPoitiait moue. You will also neeu to auu a coiiesponuing methou to coiiect the tiue heauing: - (float)trueHeading:(float)heading fromOrientation:(UIDeviceOrientation) orientation { float realHeading = heading; switch (orientation) { case UIDeviceOrientationPortrait: break; case UIDeviceOrientationPortraitUpsideDown: realHeading = realHeading + 180.0f; break; case UIDeviceOrientationLandscapeLeft: realHeading = realHeading + 90.0f; break; case UIDeviceOrientationLandscapeRight: realHeading = realHeading - 90.0f; break; default: break; } while ( realHeading > 360.0f ) { realHeading = realHeading - 360; } return realHeading; } Finally, auu the stringFromOrientation: methou liom the pievious section Chap- tei 5. Ve`ll use this to upuate the orientationLabel outlet: - (NSString *)stringFromOrientation:(UIDeviceOrientation) orientation { NSString *orientationString; switch (orientation) { case UIDeviceOrientationPortrait: orientationString = @"Portrait"; break; case UIDeviceOrientationPortraitUpsideDown: orientationString = @"Portrait Upside Down"; break; case UIDeviceOrientationLandscapeLeft: orientationString = @"Landscape Left"; break; case UIDeviceOrientationLandscapeRight: orientationString = @"Landscape Right"; break; case UIDeviceOrientationFaceUp: orientationString = @"Face Up"; break; case UIDeviceOrientationFaceDown: orientationString = @"Face Down"; 66 | Chapter 5:Using the Magnetometer break; case UIDeviceOrientationUnknown: orientationString = @"Unknown"; break; default: orientationString = @"Not Known"; break; } return orientationString; } Retuin to the locationManager:didUpdateHeading: uelegate methou anu mouily the lines highlighteu Lelow to use the new methous anu upuate the heauings uepenuing on the uevice oiientation: - (void)locationManager:(CLLocationManager*)manager didUpdateHeading:(CLHeading*)newHeading { UIDevice *device = [UIDevice currentDevice]; orientationLabel.text = [self stringFromOrientation:device.orientation]; if (newHeading.headingAccuracy > 0) { float magneticHeading = [self magneticHeading:newHeading.magneticHeading fromOrientation:device.orientation]; float trueHeading = [self trueHeading:newHeading.trueHeading fromOrientation:device.orientation]; magneticHeadingLabel.text = [NSString stringWithFormat:@"%f", magneticHeading]; trueHeadingLabel.text = [NSString stringWithFormat:@"%f", trueHeading]; float heading = 1.0f * M_PI * newHeading.magneticHeading / 180.0f; arrowImage.transform = CGAffineTransformMakeRotation(heading); } } You shoulu still use the uiiectly iepoiteu newHeading.magneticHeading loi the com- pass neeule iathei than the aujusteu heauing. Otheiwise the compass will not point coiiectly. Make suie you`ve saveu all the changes to the implementation lile anu click on the Run Lutton in the Xcoue toolLai to ueploy the application onto the uevice. Il all goes well you shoulu see the same compass uisplay as Leloie. Howevei this time il you iotate the uisplay, sees Figuie 5-7, the heauing values shoulu Le the same iiiespective ol the uevice oiientation. Although I have not uiscusseu oi implementeu it heie, il the CLLocationManager oLject encounteis an eiioi, it will call the locationManager:didFailWithError: uelegate methou: - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if ([error code] == kCLErrorDenied) { Writing a Magnetometer Application | 67 // User has denied the application's request to use location services. [manager stopUpdatingHeading]; } else if ([error code] == kCLErrorHeadingFailure) { // Heading could not be determined } } Measuring a Magnetic Field To use the uevice to measuie a magnetic lieluloi instance that ol a small Lai magnet, oi the lielu geneiateu Ly an electiic cuiient in a wiieyou shoulu liist make a zeio- point measuiement ol the amLient magnetic lielu ol the Eaith. Fuithei ieauings shoulu suLtiact this zeio-point measuiement. Vhen measuiing, move the magnet to the uevice iathei than moving the uevice to the magnet. Moving the uevice will cause the magnetic lielu ol the Eaith acioss the meas- uiing sensoi to change, which will spoil the zeio point caliLiation you took eailiei. Il the uevice must Le moveu, only small movements shoulu Le attempteu. You can ietiieve the iaw magnetic lielu measuiements along the X, Y anu Z-axes Ly gueiying the CLHeading oLject passeu to the locationManager:didUpdateHeading: methou: Iigurc 5-7. Hcading va|ucs arc now thc sanc irrcspcctivc oj oricntation 68 | Chapter 5:Using the Magnetometer - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)heading { double x = heading.x; double y = heading.y; double z = heading.z; double magnitude = sqrt(x*x + y*y + z*z); ... code ... } The values ietuineu aie noimalizeu into a 12S iange, measuieu in miciotesla (T), iepiesenting the ollset liom the magnetic lielu lines measuieu Ly the magnetometei. Apple pioviues sample coue that uisplays the iaw x, y, anu z magneto- metei values, a plotteu histoiy ol those values, anu a computeu magnituue (size oi stiength) ol the magnetic lielu. The coue can Le uownloaueu liom the iPhone uevelopei weLsite at http://dcvc|opcr.app|c .con/|ibrary/ios/=sanp|ccodc/Tcs|anctcr. Measuring a Magnetic Field | 69 CHAPTER 6 Using Core Motion The iPhone +, latest geneiation iPou touch, anu the iPau have a viLiational gyioscope in auuition to an acceleiometei anu a magnetometei. The MicioElectioMechanical (MEMs) gyioscope insiue the iPhone + anu the +th geneiation iPou touch is the AGDS 2032, neaily iuentical to an oll-the-shell STMicioelectionics L3G+200D uevice The iPau 2 uses an AGDS 2103 sensoi, also liom STMicioelectionics. These mouels opeiate Ly making use ol a plate calleu a piool mass that oscillates when a uiive signal is applieu to capacitoi plates. Vhen the usei iotates the phone, the piool mass is uisplaceu in the X, Y anu Z uiiections anu an ASIC piocessoi measuies the capacitance change ol the plates. The capacitance vaiiation is useu to uetect the angulai iate applieu to the package. An acceleiometei pioviues measuiement ol loices in the X, Y anu Z-axes Lut it cannot measuie iotation. On the othei hanu, since a gyioscope is a iate ol change uevice, you aie aLle to measuie the change in iotations aiounu an axis. By using Loth sensois in comLination you can measuie the movement ol the uevice in a six uegiees-ol-lieeuom ineitial system, allowing you to use ueau ieckoning to linu the physical location (anu oiientation ol the uevice) ielative to an initial staiting position. All ineitial systems have an inheient uiilt, so ueau ieckoning shoulu not Le iegaiueu as Leing staLle ovei the long teim. Core Motion The aiiival ol iOS + Liought with it the new Coie Motion liamewoik; this new liame- woik allows youi application to ieceive motion uata liom Loth the acceleiometei anu (on the latest geneiation ol uevices) the gyioscope. 71 Theie is no suppoit loi Coie Motion in the iOS Simulatoi, theieloie all testing ol youi Coie Motion ielateu coue must Le uone on the uevice. The coue in this chaptei will only woik on uevices that have a gyioscope, see Chaptei 1 loi moie inloimation. Vith the CMMotionManager class you can stait ieceiving acceleiometei, gyioscope, anu comLineu uevice motion events at a iegulai inteival, oi you can poll them peiiouically: CMMotionManager *motionManager = [[CMMotionManager alloc] init]; if (!motionManager.isDeviceMotionAvailable) { NSLog(@"Device supports motion capture."); } RememLei to ielease the managei altei you`ie uone with it: [motionManager release]; The CMMotionManager class olleis Loth the iaw acceleiometei anu gyioscope uata sep- aiately as well a comLineu CMDeviceMotion oLject that encapsulates the piocesseu uevice motion uata liom Loth the acceleiometei anu the gyioscope. Vith this comLineu mo- tion measuiement Coie Motion pioviues highly accuiate measuiements ol uevice at- tituue, the (unLiaseu) iotation iate ol a uevice, the uiiection ol giavity on a uevice, anu the acceleiation that the usei is giving to a uevice. The iotation iate iepoiteu Ly the CMDeviceMotion oLject is uilleient than that iepoiteu uiiectly Ly the gyioscope. Even il the uevice is sitting llat on the taLle the gyio will not ieau zeio. It will ieau some non-zeio value that uilleis liom uevice to uevice anu ovei time uue to changes in things like uevice tempeiatuie. Coie Motion actively tiacks anu iemoves this Lias liom the gyio uata. Pulling Motion Data The CMMotionManager class olleis two appioaches to oLtaining motion uata. The sim- plest way is to pull the motion uata. Youi application will stait an instance ol the managei class anu peiiouically ask loi measuiements ol the comLineu uevice motion: [motionManager startDeviceMotionUpdates]; CMDeviceMotion *motion = motionManager.deviceMotion; Although il you aie only inteiesteu in the iaw gyioscope uata (oi acceleiometei uata) you can also ask loi those uiiectly: CMGyroData *gyro = motionManager.gyroData; CMAccelerometerData *accel = motionManager.accelerometerData; This is the most ellicient methou ol oLtaining motion uata. Howevei, il theie isn`t a natuial timei in youi applicationsuch as a peiiouic upuate ol youi main viewthen 72 | Chapter 6:Using Core Motion you may neeu an auuitional timei to tiiggei youi upuate ieguests. RememLei to stop the upuates anu ielease the motion managei altei you`ie uone with them: [motionManager stopDeviceMotionUpdates]; [motionManager release]; Youi application shoulu cieate only a single instance ol the CMMotion Manager class. Multiple instances ol this class can allect the iate at which an application ieceives uata liom the acceleiometei anu gyioscope. Pushing Motion Data Insteau ol using this simple pull methouology, you can specily an upuate inteival anu implement a Llock ol coue loi hanuling the motion uata. The managei class can then Le askeu to uelivei upuates using the NSOperationsQueue, which allows the hanulei to push the measuiements to the application. Foi example: motionManager.deviceMotionUpdateInterval = 1.0/60.0; [motionManager startDeviceMotionUpdatesToQueue: queue withHandler: handler]; oi similaily loi the inuiviuual acceleiometei anu gyioscope uata: [motionManager startAccelerometerUpdatesToQueue:queue withHandler: handler]; [motionManager startGyroUpdatesToQueue:queue withHandler:handler]; Vith this seconu methouology you`ll get a continuous stieam ol motion uata, Lut theie is a laige incieaseu oveiheau associateu with implementing it (see TaLle 6-1). Youi application may not Le aLle to keep up with the associateu uata iate especially il the uevice is in iapiu motion. Tab|c -1. Exanp|c CPU usagc jor Corc Motion push updatcs at 100 and 20Hz a At 100Hz At 20Hz Total Application Total Application DeviceMotion 65% 20% 65% 10% Accelerometer 50% 15% 46% 5% Accel + Gyro 51% 10% 50% 5% a Figures for an application running on an iPhone 4 running iOS 4.0 (Reproduced with permission. Credit: Jeffrey Powers, Occipital) Using Coie Motion`s comLineu CMDeviceMotion oLject, as opposeu to accessing the iaw CMAccelerometer oi CMGyroData oLjects, consumes ioughly 15 moie total CPU ie- gaiuless ol the upuate iate. The goou news is that is not Lecause ol the gyioscope itsell; ieauing Loth the acceleiometei anu gyioscope uiiectly is not noticeaLly slowei than ieauing the acceleiometei on its own. Because ol this associateu CPU oveiheaus push is ieally only iecommenueu loi uata collection applications wheie the point ol the application is to oLtain the motion uata itsell. Howevei il youi application neeus to Le iapiuly upuateu as to uevice motion you can uo this easily: Core Motion | 73 CMMotionManager *motionManager = [[CMMotionManager alloc] init]; motionManager.deviceMotionUpdateInterval = 1.0/60.0; if (motionManager.deviceMotionAvailable ) { queue = [[NSOperationQueue currentQueue] retain]; [motionManager startDeviceMotionUpdatesToQueue:queue withHandler:^ (CMDeviceMotion *motionData, NSError *error) {
CMAttitude *attitude = motionData.attitude; CMAcceleration gravity = motionData.gravity; CMAcceleration userAcceleration = motionData.userAcceleration; CMRotationRate rotate = motionData.rotationRate; // handle data here...... }]; } else { [motionManager release]; } Il we weie inteiesteu solely in the iaw gyioscope uata we coulu uo the lollowing: CMMotionManager *motionManager = [[CMMotionManager alloc] init]; motionManager.gyroUpdateInterval = 1.0/60.0; if (motionManager.gyroAvailable) { queue = [[NSOperationQueue currentQueue] retain]; [motionManager startGyroUpdatesToQueue:queue withHandler: ^ (CMGyroData *gyroData, NSError *error) {
CMRotationRate rotate = gyroData.rotationRate; NSLog(@"rotate x = %f, y = %f, z = %f", rotate.x, rotate.y, rotate.z); // handle rotation-rate data here...... }]; } else { [motionManager release]; } Il we want Loth the iaw anu gyioscope anu acceleiometei ieauings outsiue ol the CMDeviceMotion oLject, we coulu mouily the aLove coue as highlighteu: CMMotionManager *motionManager = [[CMMotionManager alloc] init]; motionManager.gyroUpdateInterval = 1.0/60.0; motionManager.accelerometerUpdateInterval = 1.0/60.0; if (motionManager.gyroAvailable && motionManager.accelerometerAvailable) { queue = [[NSOperationQueue currentQueue] retain]; [motionManager startGyroUpdatesToQueue:queue withHandler: ^ (CMGyroData *gyroData, NSError *error) { CMRotationRate rotate = gyroData.rotationRate; NSLog(@"rotate x = %f, y = %f, z = %f", rotate.x, rotate.y, rotate.z); // handle rotation-rate data here...... }]; [motionManager startAccelerometerUpdatesToQueue:queue withHandler: ^ (CMAccelerometerData *accelData, NSError *error) { CMAcceleration accel = accelData.acceleration; 74 | Chapter 6:Using Core Motion NSLog( @"accel x = %f, y = %f, z = %f", accel.x, accel.y, accel.z); // handle acceleration data here...... }]; } else { [motionManager release]; } Accessing the Gyroscope Let`s go aheau anu implement a simple view-Laseu application to illustiate how to use the gyioscope on its own Leloie looking again at Coie Motion anu CMDeviceMotion. Open Xcoue anu stait a new View-Laseu Application iPhone pioject anu name it Gy- ioscope when piompteu loi a lilename. Since we`ll Le making use ol the Coie Motion liamewoik, the liist thing we neeu to uo is auu it to oui new pioject. Click on the pioject lile at the top ol the Pioject navigatoi winuow on the iight in Xcoue, select the Taiget anu click on the Builu Phases taL, click on the Link with LiLiaiies uiop uown anu click on the - Lutton to open the lile pop- up winuow. Select CorcMotion.jrancwor| liom the list ol availaLle liamewoiks anu click the Auu Lutton. Now go aheau anu click on the Gyroscopc\icwContro||cr.xib lile to open it in Inteilace Builuei. As you uiu loi the acceleiometei Lack in Chaptei +, you`ie going to Luilu a simple inteilace to iepoit the iaw gyioscope ieauings. Go aheau anu uiag anu uiop thiee UIProgressView liom the OLject LiLiaiy into the View winuow, then auu two UILabel elements loi each piogiess Lai: one to holu the X, Y, oi Z laLel anu the othei to holu the iotation measuiements. Altei you uo that, the view shoulu look something a lot like Figuie 6-1. Go aheau anu close the Utilities panel anu click to open the Assistant Euitoi. Then Contiol-Click anu uiag liom the thiee UIProgressView elements, anu the thiee UILa bel elements that will holu the measuieu values, to the Gyroscopc\icwContro||cr.h heauei lile which shoulu Le uisplayeu in the Assistant Euitoi on the iight-hanu siue ol the inteilace (see Figuie 6-2). This will automatically cieate anu ueclaie thiee UILabel anu thiee UIProgressView vai- iaLles as an IBOutlet. Since they aien`t going to Le useu outsiue the class, theie isn`t much point in ueclaiing them as class piopeities, which you`u uo with a Contiol-click anu uiag liom the element to outsiue the cuily Liace. Altei uoing this, the coue shoulu look like this: #import <UIKit/UIKit.h> @interface GyroscopeViewController : UIViewController { IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; Accessing the Gyroscope | 75 IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; } @end Close the Assistant Euitoi, ietuin to the Stanuaiu Euitoi anu click on the Gyroscopc- \icwContro||cr.h inteilace lile. Go aheau anu impoit the Coie Motion heauei lile, anu ueclaie a CMMotionManager anu NSOperationQueue instance vaiiaLles. Heie`s how the shoulu look when you aie uone: #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface GyroscopeViewController : UIViewController { IBOutlet UIProgressView *xBar; IBOutlet UIProgressView *yBar; IBOutlet UIProgressView *zBar; IBOutlet UILabel *xLabel; IBOutlet UILabel *yLabel; IBOutlet UILabel *zLabel; Iigurc -1. Thc Gyroscopc U| 76 | Chapter 6:Using Core Motion CMMotionManager *motionManager; NSOperationQueue *queue; } @end Make suie you`ve saveu youi changes anu click on the coiiesponuing Gyroscopc\icw- Contro||cr.n implementation lile to open it in the Xcoue euitoi. You uon`t actually have to uo veiy much heie, as Inteilace Builuei hanuleu most ol the heavy lilting with iespect to the UI, you just neeu to go aheau an implement the guts ol the application to monitoi the gyioscope upuates: @implementation GyroscopeViewController - (void)dealloc { [xBar release]; [yBar release]; [zBar release]; [xLabel release]; [yLabel release]; [zLabel release]; [queue release]; [super dealloc]; } Iigurc -2. Connccting thc U| c|cncnts to your codc in |ntcrjacc Bui|dcr Accessing the Gyroscope | 77 - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; motionManager = [[CMMotionManager alloc] init]; motionManager.gyroUpdateInterval = 1.0/2.0; // Update every 1/2 second. if (motionManager.gyroAvailable) { NSLog(@"Gyroscope avaliable"); queue = [[NSOperationQueue currentQueue] retain]; [motionManager startGyroUpdatesToQueue:queue withHandler: ^ (CMGyroData *gyroData, NSError *error) { CMRotationRate rotate = gyroData.rotationRate; xLabel.text = [NSString stringWithFormat:@"%f", rotate.x]; xBar.progress = ABS(rotate.x); yLabel.text = [NSString stringWithFormat:@"%f", rotate.y]; yBar.progress = ABS(rotate.y); zLabel.text = [NSString stringWithFormat:@"%f", rotate.z]; zBar.progress = ABS(rotate.z); }]; } else { NSLog(@"Gyroscope not available"); [motionManager release]; } } - (void)viewDidUnload { [motionManager stopGyroUpdates]; [motionManager release]; [xBar release]; xBar = nil; [yBar release]; yBar = nil; [zBar release]; zBar = nil; [xLabel release]; xLabel = nil; [yLabel release]; yLabel = nil; [zLabel release]; zLabel = nil; [super viewDidUnload]; } 78 | Chapter 6:Using Core Motion - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end The CMRotationRate uata stiuctuie pioviues the iate ol iotations aiounu X-, Y-, anu Z-axes in units ol iauians pei seconu. Vhen inspecting the stiuctuie iememLei the iight-hanu iule to ueteimine the uiiection ol positive iotation. Vith youi thumL in the positive uiiection on an axis, youi lingeis cuil will give the positive iotation uiiection aiounu that axis (see Figuie 6-3). A negative iotation goes away liom the tips ol those lingeis. Let`s test that: click on the Run Lutton in the Xcoue toolLai to Luilu anu ueploy the application to youi uevice (iememLei you can`t test this coue in the iOS Simulatoi). Il all goes well you shoulu see something much like Figuie 6-+ as you ioll the uevice aiounu the Y-axis. As mentioneu Leloie the measuiement ol iotation iate encapsulateu Ly a CMGyroData oLject is Liaseu Ly vaiious lactois. You can oLtain a much moie accuiate (unLiaseu) measuiement Ly accessing the iotationRate piopeity ol CMDeviceMotion il that is neeueu Ly youi application. Measuring Device Motion Let`s go aheau anu Luilu a similai application to the one aLove, Lut this time iepoiting the uata exposeu Ly the CMDeviceMotion oLject: CMAttitude *attitude = motionData.attitude; CMAcceleration gravity = motionData.gravity; CMAcceleration userAcceleration = motionData.userAcceleration; CMRotationRate rotate = motionData.rotationRate; Open Xcoue anu stait a new iPhone pioject, select a View-Laseu Application template, anu name the pioject Motion when piompteu loi a lilename. As Leloie, impoit the Coie Motion liamewoik into the pioject anu then click on the Motion\icwContro|- |cr.xib lile to open it in Inteilace Builuei, anu then pioceeu to uiag-anu-uiop UIProg ressBar anu UILabel elements into youi View in a similai mannei as you uiu loi the Gyioscope application eailiei in the chaptei. You`ll neeu laLels loi the yaw, pitch anu ioll values, along with piogiess Lais anu laLels loi the usei acceleiation, giavity anu iotation values. Once you`ve uone this, go aheau anu connect the vaiious Lais anu laLels as IBOutlet using the Assistant Euitoi into the Motion\icwContro||cr.h inteilace lile as in Fig- uie 6-5. Measuring Device Motion | 79 Once you`ve uone this, save youi changes anu open up the Motion\icwContro||cr.h inteilace lile in the Stanuaiu Euitoi. Go aheau anu impoit the Coie Motion liamewoik: #import <CoreMotion/CoreMotion.h> Foi this example you`ie going to pull the uevice motion upuates iathei than push them using the NSOperationQueue anu a hanulei Llock. Auu the lollowing instance vaiiaLles to the view contiollei class: CMMotionManager *motionManager; NSTimer *timer; Then in the coiiesponuing Motion\icwContro||cr.n implementation lile, mouily the viewDidLoad methou as lollows: Iigurc -3. Thc iPhonc gyroscopc axcs 80 | Chapter 6:Using Core Motion - (void)viewDidLoad { [super viewDidLoad]; motionManager = [[CMMotionManager alloc] init]; motionManager.deviceMotionUpdateInterval = 1.0 / 10.0; [motionManager startDeviceMotionUpdates]; if (motionManager.deviceMotionAvailable ) { timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(updateView:) userInfo:nil repeats:YES]; } else { [motionManager stopDeviceMotionUpdates]; Iigurc -1. Mcasuring rotation on thc iPhonc 1 whi|st ro||ing it around thc Y-axis Measuring Device Motion | 81 [motionManager release]; } } This will stait the motion managei anu Legin polling loi uevice motion upuates. Auu the lollowing lines to the viewDidUnload methou to coiiesponuing stop the timei anu upuates: [timer invalidate]; [motionManager stopDeviceMotionUpdates]; [motionManager release]; Once you have uone this you shoulu go aheau anu implement the updateView: methou that will Le calleu Ly the NSTimer oLject: -(void) updateView:(NSTimer *)timer { CMDeviceMotion *motionData = motionManager.deviceMotion; CMAttitude *attitude = motionData.attitude; CMAcceleration gravity = motionData.gravity; CMAcceleration userAcceleration = motionData.userAcceleration; CMRotationRate rotate = motionData.rotationRate; yawLabel.text = [NSString stringWithFormat:@"%2.2f", attitude.yaw]; Iigurc -5. Thc Motion app|ication U| with thc |BOut|ct conncctcd in |ntcrjacc Bui|dcr to thc Motion\icwContro||cr.h intcrjacc ji|c 82 | Chapter 6:Using Core Motion pitchLabel.text = [NSString stringWithFormat:@"%2.2f", attitude.pitch]; rollLabel.text = [NSString stringWithFormat:@"%2.2f", attitude.roll]; accelIndicatorX.progress = ABS(userAcceleration.x); accelIndicatorY.progress = ABS(userAcceleration.y); accelIndicatorZ.progress = ABS(userAcceleration.z); accelLabelX.text = [NSString stringWithFormat:@"%2.2f",userAcceleration.x]; accelLabelY.text = [NSString stringWithFormat:@"%2.2f",userAcceleration.y]; accelLabelZ.text = [NSString stringWithFormat:@"%2.2f",userAcceleration.z]; gravityIndicatorX.progress = ABS(gravity.x); gravityIndicatorY.progress = ABS(gravity.y); gravityIndicatorZ.progress = ABS(gravity.z); gravityLabelX.text = [NSString stringWithFormat:@"%2.2f",gravity.x]; gravityLabelY.text = [NSString stringWithFormat:@"%2.2f",gravity.y]; gravityLabelZ.text = [NSString stringWithFormat:@"%2.2f",gravity.z]; rotIndicatorX.progress = ABS(rotate.x); rotIndicatorY.progress = ABS(rotate.y); rotIndicatorZ.progress = ABS(rotate.z); rotLabelX.text = [NSString stringWithFormat:@"%2.2f",rotate.x]; rotLabelY.text = [NSString stringWithFormat:@"%2.2f",rotate.y]; rotLabelZ.text = [NSString stringWithFormat:@"%2.2f",rotate.z]; } Save youi changes anu hit the Run Lutton in the Xcoue toolLai to Luilu anu ueploy the application to youi uevice. Il all goes well you shoulu see something much like Fig- uie 6-6. Comparing Device Motion with the Accelerometer At this stage we can illustiate the uilleience Letween giavity anu usei-contiiLuteu ac- celeiation values iepoiteu Ly Coie Motion to the iaw acceleiation values iepoiteu Ly the UIAccelerometer, uiscusseu Lack in Chaptei +. Re-open the Motion\icwContro||cr.xib lile in Inteilace Builuei anu auu anothei section to the UI, which will iepoit the iaw ieauings liom the UIAccelerometer oLject. Go aheau anu connect these thiee Lais to IBOutlet instance vaiiaLles in the Motion\icwContro|- |cr.h inteilace lile using the Assistant Euitoi as Leloie, see Figuie 6-7. As you can see liom Figuie 6-7, I`ve changeu the UIProgressView style liom Delault to Bai using the AttiiLutes inspectoi in the Utility pane. This will help uilleientiate this sectionuata iepoiteu liom the UIAccelerometerliom the othei sections whose values aie iepoiteu Ly the CMMotionManager. Once that is uone, close the Assistant Euitoi anu open the Motion\icwContro||cr.h inteilace lile using the Stanuaiu Euitoi. Go aheau anu ueclaie the view contiollei as a UIAccelerometerDelegate anu auu a UIAccelerometer instance vaiiaLle as shown heie: @interface MotionViewController : UIViewController <UIAccelerometerDelegate> { Measuring Device Motion | 83 ... UIAccelerometer *accelerometer; } @end Leloie opening the coiiesponuing implementation lile. In the viewDidLoad methou, auu the lollowing coue to initialize the UIAccelerometer oLject. You shoulu see Chaptei + loi moie uetails on the UIAccelerometer class anu associateu methous: - (void)viewDidLoad { [super viewDidLoad]; motionManager = [[CMMotionManager alloc] init]; motionManager.deviceMotionUpdateInterval = 1.0 / 10.0; [motionManager startDeviceMotionUpdates]; if (motionManager.deviceMotionAvailable ) { timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(updateView:) userInfo:nil repeats:YES]; } else { [motionManager stopDeviceMotionUpdates]; [motionManager release]; Iigurc -. Thc Motion app|ication running on an iPhonc 1 sitting j|at on thc dcs|, with gravity in thc ncgativc Z-dircction without any rotation or uscr accc|cration 84 | Chapter 6:Using Core Motion } accelerometer = [UIAccelerometer sharedAccelerometer]; accelerometer.updateInterval = 0.2f; accelerometer.delegate = self; } Altei uoing this all you neeu to uo is auu the accelerometer:didAccelerate: uelegate methou: - (void)accelerometer:(UIAccelerometer *)meter didAccelerate:(UIAcceleration *)acceleration {
rawAccelLabelX.text = [NSString stringWithFormat:@"%2.2f", acceleration.x]; rawAccelIndicatorX.progress = ABS(acceleration.x); rawAccelLabelY.text = [NSString stringWithFormat:@"%2.2f", acceleration.y]; rawAccelIndicatorY.progress = ABS(acceleration.y); rawAccelLabelZ.text = [NSString stringWithFormat:@"%2.2f", acceleration.z]; rawAccelIndicatorZ.progress = ABS(acceleration.z); } Iigurc -7. Thc additiona| U|Progrcss\icw and U|Labc| c|cncnts to rcport thc raw U|Accc|cronctcr rcadings to thc uscr Measuring Device Motion | 85 Click on the Run Lutton in the Xcoue toolLai to Luilu anu ueploy the application to the uevice as Leloie. Il all goes well you shoulu see something much like Figuie 6-S. Move the uevice aiounu anu you can see how the iaw acceleiometei values anu the ueiiveu giavity anu usei acceleiation values coiiesponu to each othei. Iigurc -8. Thc Motion app|ication running on an iPhonc 1 sitting j|at on thc dcs| 86 | Chapter 6:Using Core Motion CHAPTER 7 Going Further I`ve coveieu a laii amount ol giounu in the last lew chapteis, anu you shoulu now have a soliu giasp ol the Lasics ol hanuling the sensoi uata piouuceu Ly the haiuwaie. The iPhone SDK PieuictaLly in a Look talking aLout sensois I`ve locuseu on the paits ol the SDK that will Le most helplul, anu allow you to use the Lasic sensoi haiuwaie in youi own applications. But even theie I`ve lelt out a lot in an attempt to simplily anu get you staiteu guickly, especially when it comes to auuio. A moie in-uepth look at the iPhone SDK is availaLle in Progranning iOS 1, Ly Matt NeuLuig (O`Reilly). Geolocation and Maps The iPhone is one ol the most populai uevices loi geolocation: useis use it loi eveiything liom uiiving uiiections to linuing a iestauiant close to them. As a uevelopei, you can get in on the geolocation game Ly using the Coie Location liamewoik, one ol the most poweilul anu inteiesting liamewoiks in the iPhone SDK. It aLstiacts the uetails ol ueteimining a usei`s location, anu uoes all the heavy lilting loi you Lehinu the scenes. Fiom theie you can use the MapKit liamewoik to emLeu maps uiiectly into youi views, anu then go aheau anu annotate those maps. I`ll ueep-uive into Loth these topics in upcoming title Gco|ocation in iOS, Ly Alasuaii Allan (O`Reilly). Third-Party SDKs The same Look will investigate thiiu-paity geo-SDKs such as the Skyhook Viieless Local Faves anu Spot Rank SDKs, along with coveiage ol SimpleGeo anu SG Context anu Places. 87 Speech Recognition I coveieu Lasic manipulation ol the auuio haiuwaie, Lut moving on liom this you might Le thinking aLout integiating speech iecognition into youi application. At least until Apple gets iounu to auuing this to the ollicial iOS SDK, the Lest way to uo this is pioLaLly using the CMU Pocketsphinx anu CMU Flite liLiaiies. Theie aie actually two laiily goou OLjective-C wiappeis to the liLiaiies, these aie VocalKit anu OpenEais. Ol the two, at least at the time ol wiiting, OpenEais pioLaLly has is the Lest uocumentation which may Le a ueciuing lactoi il you`ie not a expeit in speech iecognition. Computer Vision The Open Souice Computei Vision (OpenCV) LiLiaiy is a collection ol ioutines in- tenueu loi ieal-time computei vision, ieleaseu unuei the BSD License, liee loi Loth piivate anu commeicial use. The liLiaiy has a numLei ol uilleient possiLle applications incluuing oLject iecognition anu tiacking. Ve uelve into computei vision anu lace iecognition in the upcoming title Augncntcd Rca|ity in iOS, Ly Alasuaii Allan (O`Reilly). Vhile you wait you might want to take a look at some ol the sample coue liom this title which is alieauy on the weL at http://progranningiphoncscnsors.con/pagcs/oscon .htn|. Augmented Reality Unsuipiisingly peihaps, the same title will also take a close look at Augmenteu Reality, which has Lecome one ol the killei applications loi the iOS platloim. The Look walks you thiough Luiluing a simple location-awaie AR toolkit, anu some ol the sample coue is alieauy online at http://progranningiphoncscnsors.con/nastcrc|ass/thcc|ass.htn|. Il you`ie inteiesteu in AR you might also want to take a look at the associateu viueo masteiclass on iOS Sensois which leatuies me, amongst othei things, walking you thiough the AR toolkit coue. The viueo masteiclass Ma|ing usc oj iPhonc and iPad Location Scnsors was lilmeu using Xcoue 3 anu iOS +.0. Vhile the coue is still line, the step-Ly-step walkthioughs in Xcoue aie somewhat out ol uate. External Accessories Vhile the iOS platloim comes with a giowing iange ol sensois; GPS, acceleiometeis, magnetometeis anu most iecently gyioscopes. They also have a (neai-)uLiguitous uata connection, whethei via a local wiieless hotspot oi via caiiiei uata, anu usei positioning 88 | Chapter 7:Going Further via multiple methous incluuing GPS. The uevice makes an excellent huL loi a uistiiL- uteu sensoi netwoik. Howevei until iecently it was actually guite uillicult to inteilace these otheiwise intei- esting uevices into a stanuaiu seiial inteilace, as the iPhone`s piopiietaiy uock connectoi is a majoi stumLling Llock. All this has changeu. In the upcoming title iOS and Scnsor Nctwor|s Ly Alasuaii Allan (O`Reilly) we`ll uiscuss using the MFi appioveu Reupaik Seiial CaLle. This is an olli- cially Apple appioveu ioute, anu makes use ol Apple`s own Exteinal Accessoiy Fiame- woik to connect youi uevice to any stanuaiu seiial (RS-232) capaLle uevice. In auuition to this we will go on to uiscuss othei methous to use the phone as the huL ol a sensoi netwoik, anu pait ol the Inteinet ol Things. External Accessories | 89 About the Author $ODVGDLU$OODQ is the authoi ol Lcarning iPhonc Progranning, Progranning iPhonc Scnsors, Basic Scnsors in iOS, Gco|ocation iOS, iOS Scnsor Apps with Arduino, anu Augncntcd Rca|ity in iOS, all puLlisheu Ly O`Reilly Meuia. He is a senioi ieseaich lellow in Astionomy at the Univeisity ol Exetei. As pait ol his woik theie, he is Luiluing a uistiiLuteu peei-to-peei netwoik ol telescopes which, acting autonomously, will ie- actively scheuule oLseivations ol time-ciitical events. NotaLle successes incluue con- tiiLuting to the uetection ol the most uistant oLject yet uiscoveieu, a gamma-iay Luistei at a ieushilt ol S.2. Alasuaii also iuns a small technology consulting Lusiness wiiting Lespoke soltwaie, Luiluing open haiuwaie, anu pioviuing tiaining. He wiites loi O`Reilly Rauai, anu spoiauically wiites in his own Llog, The Daily ACK, aLout things that inteiest him, oi moie lieguently pioviues commentaiy in 1+0 chaiacteis oi less on Twittei. Colophon The animal on the covei ol Basic Scnsors in iOS is a Malay lox-Lat. The covei image is liom Lyuekkei`s Roya| Natura| History. The covei lont is AuoLe ITC Gaiamonu. The text lont is Linotype Biika; the heauing lont is AuoLe Myiiau Conuenseu; anu the coue lont is LucasFont`s TheSansMonoConuenseu.
Mobile App Reverse Engineering Get Started With Discovering, Analyzing, and Exploring The Internals of Android and iOS Apps (Abhinav Mishra) (Z-Library)