it 7a

ankitar
chapter12book.pdf

Getting Started with MonoTouch and Mono for Android

Developing in the mobile space can be a daunting task for developers. You have to fi gure out which platforms you should support for your app, purchase the hardware, and join the developer programs for each platform, so the last thing you may want to do is to learn a new programming language.

In 2009 Miguel de Icaza, with a team of other developers, released version 1.0 of the MonoTouch framework. MonoTouch enabled .NET developers to create iOS applications in C# and then deploy to iOS hardware. After the initial launch of the MonoTouch framework, Apple modifi ed the iTunes terms of service to allow only apps that were created using Objective-C into the market, a decision that was quickly reversed.

Although short lived, this edict from Apple is a fact that many developers keep in the back of their mind, knowing that Apple can change the terms of service again at any time. The bright side of this policy was that it was only for apps being deployed to the iOS store; if you created an app for internal company use that was deployed using an ad-hoc method, you were still free to use whatever non-Objective-C framework you liked.

THE MONO FRAMEWORK MonoTouch and Mono for Android rely on the Mono Framework to function. Mono is a cross-platform open source implementation of the .NET Framework. The Mono project is led by Miguel de Icaza, with the sponsorship of his company Xamarin. The Mono project was started in 2001, with version 1.0 released in 2004. Throughout the years of development, a team of open source developers worked to keep parity with the C# and libraries within the .NET Framework. One of the most impressive development projects I have seen was when the Mono project released Moonlight, the Mono implementation of Silverlight, within 24 hours of Microsoft releasing Silverlight to the developer community at the Mix conference in 2007.

12

c12.indd 343c12.indd 343 28/07/12 6:09 PM28/07/12 6:09 PM

344 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

The Mono project focuses on providing:

" An open source Common Language Infrastructure (CLI) implementation: ECMA-335 is the open standard developed by Microsoft that describes the core of the .NET Framework. The Mono CLI provides a runtime environment for code that has been compiled to Common Intermediate Language (CIL).

" A C# compiler: ECMA-334 defi nes the open standard of the C# language. The Mono C# compiler is responsible for compiling C# code in the Common Intermediate Language that the CLI run time executes.

" An open development stack: The Mono project strives to provide tools that are both useful and easy for developers to use. At the forefront is the MonoDevelop IDE along with various other tools for linking, and other core libraries specifi c to UNIX environments such as the GTK# library used for GUIs.

The current Mono C# compiler provides a complete feature set for C# 1, 2, and 3, with partial support for C# 4.

MonoTouch MonoTouch is a set of tools that enables a developer to build iOS applications using their existing knowledge of the .NET Framework. The MonoTouch tools provide a combination of the core .NET Framework features along with APIs provided in the iOS SDK. The MonoTouch team has spent a great deal of time trying to provide an interface with names that match the corresponding iOS feature, in an effort to make the MonoTouch API very similar to the iOS SDK without sacrifi cing conventions that .NET developers are accustomed to.

Although MonoTouch is based on the open source Mono project, MonoTouch is a commercial product, which is licensed on a developer basis. For up-to-date licensing info, visit the Xamarin store website at https://store.xamarin.com/.

The Microsoft .NET Framework languages (Visual Basic, C#, F#) are interpreted languages that compile to Common Intermediate Language (CIL), and then are just-in-time (JIT) compiled, meaning in the normal uses of the .NET Framework, your code isn’t truly compiled until run time.

Interpreted code/JIT compilation is not supported within iOS and is blocked via the terms of service as well as functionality within the iOS kernel. This means that a different solution is needed for the Mono framework to work within iOS.

MonoTouch is delivered as a static compiler that turns .NET code into static byte code. MonoTouch apps are compiled using ahead-of-time (AOT) compilation (static compilation), which allows all code that is normally JITed to be generated from CIL to a single native binary that can then be signed, just like a C compiler would generate static byte code. This method loses some of the dynamic functionality of .NET, but features such as generics are still supported.

Linking Because libraries cannot be reused in iOS, every time your app is installed on a device, the Mono Framework is bundled inside your app as well. When your MonoTouch app is compiled, a process runs that analyzes which portions of the Mono framework you are actually using, and creates a

c12.indd 344c12.indd 344 28/07/12 6:09 PM28/07/12 6:09 PM

The Mono Framework ! 345

custom version of the Mono Framework ARM CPU architecture, with only the functionality your app is using, and then links this version into your app. What this means is that if you have fi ve different MonoTouch apps installed on your iOS device, each app will have its own version of the Mono Framework. The fact that the Mono Framework needs to be installed increases the size of the app over a natively created app, but this is fully dependent on how much of the Mono Framework is being utilized. In most cases, the size increase of the app is trivial.

The linker is integrated into MonoTouch and the MonoDevelop IDE, so you do not need to worry about doing anything extra.

Performance Both Objective-C and the Mono Framework’s AOT compiler use the same low-level virtual machine (LLVM) for generating and optimizing the binary code, so there should be no performance difference using MonoTouch as opposed to Objective-C. Because portions of the Mono Framework are compiled into the fi nal assembly, the apps may be larger.

Mono for Android Mono for Android is the sibling product of MonoTouch. Mono for Android allows .NET developers to create apps for the Android operating system using a set of tools they are familiar with. With Mono for Android, developers can create Android applications within Visual Studio or the MonoDevelop IDE.

Mono for Android 1.0 was released in April 2011, and is much younger then the MonoTouch framework but is a viable alternative to native Android development.

The Android operating system is a Linux-based system where Android apps run on top of a virtual machine named Dalvik. Mono for Android apps do not run within Dalvik, but within Mono, which runs side-by-side with Dalvik. Mono for Android developers access features in the Android operating system by calling .NET APIs through Mono, or by classes exposed in the Android namespace provided for Mono for Android. This provides a bridge into the Java APIs that are exposed by Dalvik.

Both Mono and Dalvik run on top of the Linux kernel and expose API functionality to developers to access the operating system. Figure 12-1 shows the various components of a Mono for Android app and their interaction with the Mono framework and Dalvik.

FIGURE 12!1: Mono for Android architecture

c12.indd 345c12.indd 345 28/07/12 6:09 PM28/07/12 6:09 PM

346 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Performance When it comes to performance, research suggests that Mono’s JIT compiling is faster than Dalvik’s (http://www.koushikdutta.com/2009/01/dalvik-vs-mono.html). In our experience with Mono for Android, both native and Mono for Android apps performed similarly. But to be fair, the apps we have created are not complex, and usually just display data retrieved from a web service.

Assemblies Just as with Silverlight, MonoTouch and Mono for Android are subsets of assemblies included in the desktop .NET Framework, basically hybrids of .NET 4.0 and the Silverlight 2 API profi le. MonoTouch/Mono for Android are extended subsets of Silverlight and the desktop .NET assemblies to aid in your iOS development. It’s important to note that MonoTouch/Mono for Android are not

Linking Very similar to how the linker in MonoTouch works, Mono for Android creates a custom static version of the Mono Framework that is distributed with your Mono for Android app. It’s important to note that the default debug releases of your Mono for Android app will not use the linker and a shared runtime package will be installed. Although this makes repeated deploying much quicker, it’s not a true test of your app, because turning on linking may have some unintended side effects. Figure 12-2 shows the build settings for a Mono for Android project in MonoDevelop. Notice the Linker Behavior setting for the Debug confi guration. To enable linking, simply uncheck the Use Shared Mono Runtime setting and select Link All Assemblies.

FIGURE 12!2: Linker settings

c12.indd 346c12.indd 346 28/07/12 6:09 PM28/07/12 6:09 PM

The Mono Framework ! 347

ABI compatible with assemblies compiled for a different profi le, such as Silverlight or the desktop .NET Framework. Assemblies you want you use in your MonoTouch/Mono for Android app must be recompiled with the MonoTouch/Mono for Android profi le, just as if you were using these assemblies in a Silverlight app.

Why MonoTouch/Mono for Android? The true power of these frameworks comes with the ability to share code. As we have stressed in previous chapters of this book, UI is very important to the mobile app experience, and you should not try to plan on a single solution that works on both iOS and Android. However, a great deal of business logic can be abstracted and shared very easily between both your iOS implementation and your Android implementation.

As you become more experienced with a programming language, it becomes easier to follow patterns that have been identifi ed as “good” programming practice. I know from fi rsthand experience that the fi rst time I develop a project in a new language, it does not meet the quality I hold to other code bases with languages I have more experience with. With that being said, using MonoTouch and Mono for Android enable you to use a language where you already know the best practices, and let you focus on developing a great app.

Do not re-create the wheel and keep business logic outside of the UI. There is a set of rules that we as developers should follow, but if you are unfamiliar with a framework or programming language, following these rules is easier said than done. With MonoTouch and Mono for Android the expectation is that you are already familiar with .NET and C#, so you are able to take your existing knowledge and start developing platform-specifi c apps without leaning a new framework.

Downsides As you may have noticed when it comes to mobile development, nothing is black and white. You can perform the exact same task in multiple ways, but many of them come with a downside. Developing with MonoTouch and Mono for Android is no different.

Waiting for Improvements When Apple or Google have a press conference to promote the latest and greatest features contained in their respective mobile operating systems, in most situations, it is at that time you can update the SDKs and start working with the new great features if you are working with a native app. When you have selected MonoTouch or Mono for Android as your development platform, you must wait until Xamarin includes these new features in the MonoTouch/Mono for Android SDK.

Xamarin has a fraction of the developers on staff that Apple or Google have to perform development and testing of new features. Although Xamarian strives to keep feature parity complete, sometimes this process takes a bit longer than we as users of the framework would like. Because of the close interaction with xCode for the user interface development, when changes to xCode happen, it tends to take Xamarin a while to develop a product that works correctly. The release of xCode 4 left MonoTouch developers using an older version of the IDE for almost a year until a solution was delivered.

c12.indd 347c12.indd 347 28/07/12 6:09 PM28/07/12 6:09 PM

348 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Apple Confusion With developer certifi cates and provisioning profi les, the hoops a developer has to jump through just to get an app installed on a device may make you start to lose your hair. Although the process of provisioning profi les and certifi cates can be a pain in the neck, xCode and other Apple tools have been created to help make this chore a bit easier—whereas the tools contained within MonoDevelop will make you lose even more hair. It’s not that they don’t function within MonoDevelop, but they are not very user-friendly, and to a new developer on the iOS platform it can be overwhelming.

Xamarin Mobile With sharing code being one of the most appealing reasons to use MonoTouch and Mono for Android, the Xamarin team has taken the platform one step forward with the Xamarin Mobile library. This library provides tools to write device-specifi c functionality once. For example, MonoTouch requires a different set of APIs for getting a contact than Mono for Android does, because they both try to adhere to the native API naming conventions as much as possible. Xamaran Mobile provides a single API that allows you to return the contacts for either iOS or Android. The following code examples show how Xamarin Mobile can be useful.

To get a list of contacts in MonoTouch, you need to use the ABAddress object:

ABAddressBook addressBook = new ABAddressBook(); ABPerson[] contacts = iPhoneAddressBook.GetPeople();

Licensing Both MonoTouch and Mono for Android are commercial products and currently require developers to purchase a license for each. The evaluation version of both MonoTouch and Mono for Android enable developers to create apps and deploy to the simulator/emulator only; a fully licensed version is required to deploy to a device.

When a license is purchased, the key is entered within the IDE, and activation occurs over the Internet. The downside occurs if Xamarian goes out of business. What is the “escape” plan if you have to reinstall your machine, and activate the framework when the activation server no longer exists? You are putting the fate of a great deal of development resources in the hands of an external resource. Sure, you can argue the same fact about PhoneGap or Titanium, but because they are open source the projects can persist after corporation backing loses interest.

As a developer you may not initially think that this could be an issue. Before Xamarian obtained the rights for MonoTouch, the MonoTouch project was in this exact state of limbo, and we were burned on a project. With a newly installed machine, and no way to activate the MonoTouch license we had paid for, there was no way to make changes to an app that had been in the fi eld for about a year. Luckily the app was small, and we were able to rewrite it natively for iOS. The client received their updates, but we lost time rewriting the app.

c12.indd 348c12.indd 348 28/07/12 6:09 PM28/07/12 6:09 PM

The Mono Framework ! 349

With a fundamental understanding of how the Mono framework, MonoTouch, Mono for Android, and Xamarin Mobile interact with one another, you can move on to setting up a development environment.

foreach (ABPerson item in contacts) { // do something with the contact }

In Mono for Android, you need to use the ManagedQuery object to get the contacts:

var contacts = ManagedQuery(ContactsContract.Contacts.ContentUri, null, null, null, null);

foreach (Contact contact in contacts) { // do something with the contact }

Xamarin Mobile uses a new AddressBook object that returns the contacts for either iOS or Android:

var book = new AddressBook ();

foreach (Contact contact in book) { // do something with the contact }

Xamarin Mobile is currently very early in development and is focusing only on the areas shown in Figure 12-3.

FIGURE 12!3: Xamarian Mobile features

c12.indd 349c12.indd 349 28/07/12 6:09 PM28/07/12 6:09 PM

350 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

GETTING THE TOOLS YOU NEED The leadership for the Mono project is all open source advocates, and as such many of the tools required for creating mobile apps based on Mono are open source. Some companies, usually larger companies, may have strict policies about not allowing open source projects into production code. Often these polices stem from the licenses that some open source projects use, or management not willing to trust that a community-funded project will be able to succeed because if the company has issues with the product, oftentimes there is no one call to ask for support.

This chapter shows examples created within Mac OS X, and makes mention of when a particular tool can be installed within Windows as well

Mono Framework Installing the Mono Framework is a relatively simple process. The Mono Framework is required for the remaining tools in this chapter to be installed. To fi nd the latest version of Mono, navigate to http://www.go-mono.com/mono-downloads/download.html and install the latest stable version for your platform. The examples in this chapter are for Mac OS X because MonoTouch is supported only on Mac OS X, but if you are working on a Windows machine, you will be able to work with Mono for Android. After the Mono Framework is installed, you can check the version by executing Mono --version in a terminal session. The output of this command lists version information as shown in Figure 12-4.

MonoDevelop MonoDevelop is an open source IDE supported under the Mono project. In 2003 developers forked another open source IDE named Sharp Develop into the MonoDevelop IDE. MonoDevelop has a large open source community following, with updates being published frequently.

MonoDevelop is supported on multiple platforms, with Mac OS X and Windows included. To get started with MonoDevelop, simply download the version for your platform from the download page (http://monodevelop.com/Download) and follow the install instructions. MonoDevelop is dependent on the Mono Framework, and if you have not already installed the Mono Framework, you will be prompted to do so.

After MonoDevelop has been installed, you should be able to start the product and have a screen that looks similar to Figure 12-5.

FIGURE 12!4: Mono Framework version from terminal

c12.indd 350c12.indd 350 28/07/12 6:09 PM28/07/12 6:09 PM

Getting the Tools You Need ! 351

Mono/MonoDevelop follow many of the same conventions that .NET and Visual Studio follow. Class fi les belong to project fi les and project fi les belong to solutions. If you have worked with Visual Studio in the past, you should feel right at home with this product.

The MonoDevelop IDE is used to create solutions written in various languages that can be run on the CLR. This means there is support for a great number of languages/frameworks ranging from ASP.NET MVC to Silverlight (Moonlight on Mono). MonoDevelop is the IDE that you use to create both Android and iOS applications with Mono for this chapter.

MonoTouch The MonoTouch toolset has a very close relationship to xCode and the iOS SDK. Because of this close-knit relationship, MonoTouch can be run only on a Mac and cannot be installed on a Windows machine. This means that before you start to install MonoTouch, you should ensure that you have the iOS SDK and xCode installed. This was discussed in depth in Chapter 7.

MonoTouch is a commercial product offered through Xamarin and currently is licensed to developers, meaning that if you have a team of fi ve developers working on a MonoTouch app, you will need to purchase fi ve licenses from Xamarin. A full version of MonoTouch enables developers to deploy, build, and run MonoTouch apps on physical iOS devices. An unlicensed version enables developers to build and run MonoTouch apps on the iOS Simulator.

FIGURE 12!5: MonoDevelop start screen

c12.indd 351c12.indd 351 28/07/12 6:09 PM28/07/12 6:09 PM

352 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Mono for Android Mono for Android has a few options in regards to platforms and IDEs. Mono for Android can be run on either Mac OS X or Windows. If you decide on the Windows option you can use either MonoDevelop or Visual Studio to create Android apps. Whether you decide on Mac OS X or Windows, you can download Mono for Android from http://xamarin.com/trial. The prerequisites are similar to MonoTouch (Mono Framework, GTK+, MonoDevelop) with the addition of the Android SDK. Both the Mac OS X and Windows versions of Mono for Android check for the prerequisites and assist you with installing them if they are missing. After you have installed Mono for Android and started MonoDevelop, you should be able to create one of the various Mono for Android project types as shown in Figure 12-7.

To get started with MonoTouch, you must install the MonoDevelop IDE. After MonoDevelop has been installed, you can download MonoTouch from http://xamarin.com/trial and install it using the installer. The installer is straightforward — it’s simply a matter of clicking the Next button a few times. If for some reason a prerequisite for the install is missing, the MonoTouch installer will prompt you to install the missing prerequisite. After the install is complete and you restart MonoDevelop, you should be able to create one of the various MonoTouch project types from the New Solution dialog box as shown in Figure 12-6.

FIGURE 12!6: MonoTouch projects in MonoDevelop

c12.indd 352c12.indd 352 28/07/12 6:09 PM28/07/12 6:09 PM

Getting to Know MonoDevelop ! 353

Visual Studio Support If you are familiar with Visual Studio, and plan to go down this development path, it’s important to note that Visual Studio Express is not supported because of its lack of support for plug-ins. After you have installed Mono for Android, as mentioned previously, you will then need to install the Mono Tools for Visual Studio, which you can fi nd at http://mono-tools.com/download/. This enables you to use Visual Studio to create solutions targeted at the Mono Framework, and in this case Mono for Android projects.

The examples in this chapter have been created using MonoDevelop on Mac OS X, but should function the same within Visual Studio in Windows.

GETTING TO KNOW MONODEVELOP Xamarin is working to deliver a fully integrated solution for developers with knowledge of .NET to create apps for iOS and Android. It put a great deal of effort, along with other open source developers, to contribute to the IDE where MonoTouch and Mono for Android apps are created. The integration of MonoTouch and Mono for Android was very well thought out, and if you are already familiar with MonoDevelop it will be intuitive on how these products fi t together.

MonoDevelop is not bloated full of features that most developers will never use. Its simple user interface enables developers to rapidly fi nd tools they need when they are unfamiliar with the product.

FIGURE 12!7: Mono for Android projects in MonoDevelop

c12.indd 353c12.indd 353 28/07/12 6:09 PM28/07/12 6:09 PM

354 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

MonoDevelop provides tools to Step Over, Step Into, and Step Out on the Debug toolbar shown in Figure 12-9.

Locals The locals window shows you a list of all of the variables that are currently within scope of your current breakpoint, and enables you to view details about each variable. Figure 12-10 shows the locals window with an object named fullLeagueData that has a count of 908 items. If you wanted to see more information about the

Debugging It can be extremely frustrating to hunt down bugs in your application, and having well-developed debugging tools that are integrated into the IDE is very useful when trying to resolve issues in your app quickly. No matter what IDE you are working with, the teams that develop the IDEs are constantly working to make debugging better for developers, and MonoDevelop is no exception.

MonoDevelop contains GUI debugging tools that are consistent with other IDEs such as xCode and Visual Studio. With a close relationship to the .NET Framework, the debugging experience is more like Visual Studio than any other product.

Breakpoints You can set breakpoints by clicking in the gutter next to the line number as shown in Figure 12-8. When you are debugging your app, and the breakpoint has been reached, the line will be highlighted.

FIGURE 12!8: Breakpoints within MonoDevelop

FIGURE 12!9: MonoDevelop Debug toolbar

c12.indd 354c12.indd 354 28/07/12 6:09 PM28/07/12 6:09 PM

Getting to Know MonoDevelop ! 355

Output The Application Output section provides important information about the execution of the app, as well as displays any log messages you may add in your code. Figure 12-12 shows the application output of an MonoTouch application that logged information received from a web service.

items in the fullLeagueData object, you could click the array next the variable name and drill into the data contained within.

Call Stack When hunting for bugs, it’s useful to follow the execution path of a particular feature, in hopes of fi nding the issue. Figure 12-11 shows the Call Stack window within MonoDevelop.

FIGURE 12!10: Locals window in MonoDevelop

FIGURE 12!11: Call Stack window in MonoDevelop

FIGURE 12!12: Application Output window in MonoDevelop

MonoTouch Specifi cs When you install MonoTouch, new tools are added to the MonoDevelop IDE that will aid in your creation of iOS apps. These tools are specifi c to iOS apps and provide a range of functionality, such as creating a new iOS project type, as shown in Figure 12-13, to deploying your newly created app to a physical iOS device.

c12.indd 355c12.indd 355 28/07/12 6:09 PM28/07/12 6:09 PM

356 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

iOS Simulator Build confi gurations allow developers to create different build settings for different build scenarios. Every newly created MonoTouch app preconfi gures four different build confi gurations, two for deploying to the iOS simulator and two for deploying to a physical device. Figure 12-14 shows the build confi gurations for a MonoTouch iPhone-only app.

When the iOS simulator is selected as an option in the build confi guration, MonoDevelop/MonoTouch will launch the iOS simulator that was installed when the iOS SDK/xCode was installed and push your app to the simulator for you to test.

Interface Builder Interface Builder is the tool included with xCode that enables developers to create user interfaces for iOS applications. Interface Builder provides tools with which a developer can lay out the interface, and also map the controls to the events/functions that will be called. Interface Builder can open storyboard or XIB fi les. To work with Interface Builder from MonoDevelop, simply click your storyboard or XIB fi le and Interface Builder will be launched.

This interaction between MonoDevelop and xCode/Interface Builder can be somewhat fragile. Behind the scenes, MonoDevelop generates a temporary xCode project that contains stubbed- out Objective-C functions that match the C# classes, which allow the classes to be accessed from Interface Builder and synchronized back to MonoDevelop.

Mono for Android Specifi cs When Mono for Android is installed, a set of tools specifi c to working with the Android platform is installed, and linked within the MonoDevelop IDE. The most notable of these tools are the tools pertaining to the Android emulator. MonoDevelop can deploy your newly created Mono

FIGURE 12!13: MonoTouch project types

FIGURE 12!14: MonoTouch build confi gurations

c12.indd 356c12.indd 356 28/07/12 6:09 PM28/07/12 6:09 PM

Mono Projects ! 357

It’s important to note that the trial version of Mono for Android allows apps to be deployed only to the emulator. A full license is required if you want to deploy to a physical device.

With the development environments installed and the basics of debugging covered, you can now examine what exactly makes up a MonoTouch and Mono for Android project with regard to fi les and code.

MONO PROJECTS The developers on both the MonoTouch and Mono for Android projects have spent a great deal of time making the development experience as similar to using the recommended native tools as possible. Core programming concepts from iOS will transfer to MonoTouch, as will concepts from

for Android app to a physical Android device or an emulator.

The communication between MonoDevelop and the Android emulators is another one of those “fragile” areas. It’s best to use the tools within MonoDevelop to start the emulators. By default the debug build confi guration deploys your Mono for Android app to an emulator. The screen in Figure 12-15 is presented, which allows you select or create an AVD. If you are unfamiliar with the AVD concept, please see Chapter 6.

The list of AVDs enumerated in MonoDevelop is the same list of AVDs enumerated in the Eclipse AVD Manager as shown in Figure 12-16.

FIGURE 12!15: Android emulator selection

FIGURE 12!16: Eclipse AVD Manager

c12.indd 357c12.indd 357 28/07/12 6:09 PM28/07/12 6:09 PM

358 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Android. Chapters 6 and 7 cover these core concepts and will be important for you to understand before jumping into learning MonoTouch and MonoDevelop. Understanding how to write apps using the “iOS way” and the “Android way” will help you interface with the MonoTouch and Mono for Android frameworks, as well as research issues when you encounter them.

Anatomy of a MonoTouch App The MonoTouch structure shown in Figure 12-17 represents a newly created tabbed application type. If you have gone through Chapter 7, this structure should look very familiar. As with native iOS apps, MonoTouch apps use an MVC design pattern keeping UI and business logic separated. The following is a list of fi les and their function for a newly created MonoTouch tabbed application type.

" Main.cs: As with most other C programs, the execution of C# applications start from the main() function, which is located in the main.cs fi le.

" AppDelegate.cs: The AppDelegate receives messages from the application object during the lifetime of your application. The AppDelegate is called from the operating system, and contains events such as didFinishLaunchingWithOptions, which iOS would be interested in knowing about.

" ViewController.cs: The view controller classes contain the business logic that is passed to the UI views.

" ViewController_iPhone.xib: ViewController XIB fi les contain the user interface for the MonoTouch app.

" ViewController_iPad.xib: When a universal iOS app is created, .xib fi les are created for both iPhone and iPad. These fi les contain the UI specifi c to the iPad.

" Info.plist: This plist fi le contains confi guration settings that are specifi c to the app.

The example MonoTouch project in Figure 12-17 shows the user interface created in XIB fi les. Chapter 7 discussed creating iOS user interfaces using the Storyboard concept. MonoTouch also provides project types to create Storyboards in addition to XIB fi les.

Project Options To “polish” an iOS application and make it ready for deployment, numerous settings such as setting the provisioning profi le and device orientation are extremely important in the deployment process, but seem to be hidden within MonoTouch and the MonoDevelop IDE. If you fi nd yourself looking for a setting and can’t seem to fi nd it, it could be hidden under the project Options setting, which you can fi nd by right-clicking the project and selecting Options as shown in Figure 12-18.

FIGURE 12!17: MonoTouch project structure

c12.indd 358c12.indd 358 28/07/12 6:09 PM28/07/12 6:09 PM

Mono Projects ! 359

iOS Signing Options In our opinion, one of most diffi cult concepts of iOS for new developers is the concept of certifi cates and provisioning profi les. Figure 12-20 shows the iOS signing options that enable you to relate both a certifi cate and a provisioning profi le to your MonoTouch app. Certifi cates and provisioning profi les

Build Options Figure 12-19 shows the build options for the iOS project. Options on this dialog box enable you to select which iOS SDK your app will run on. This dialog box also contains advanced features, such as the linker behavior. Earlier in this chapter we mentioned that all MonoTouch apps include a custom-built version of the Mono Framework, containing only features used in the related app. By default, debug versions running on the simulator do not link the assemblies, therefore the entire Mono Framework is included. This is because the time it takes to link the assemblies is greater than the time it takes to just include the entire framework with the app, which means making debugging much faster.

FIGURE 12!18: MonoTouch project options

FIGURE 12!19: MonoTouch build settings

c12.indd 359c12.indd 359 28/07/12 6:09 PM28/07/12 6:09 PM

360 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Application Settings Figure 12-21 shows the application settings dialog box. This dialog box enables you to set values specifi c to the application, such as application name, version, and supported orientations.

are still installed using the tools within xCode, and will show up automatically in this interface to use in your app.

FIGURE 12!20: MonoTouch signing settings

FIGURE 12!21: MonoTouch application settings

c12.indd 360c12.indd 360 28/07/12 6:09 PM28/07/12 6:09 PM

Mono Projects ! 361

Anatomy of a Mono for Android App The structure in Figure 12-22 represents a newly created Mono for Android application. If you have read through Chapter 6, this structure should look very familiar.

The following is a list of fi les and their function for a newly created Mono for Android application.

" Assets: The Assets directory contains assets such as sound fi les or other nonimage assets your Mono for Android app may use.

" Drawable: The Drawable directory contains images that will be used throughout your Mono for Android application.

" Layout: The Layout directory contains the user interface XML fi les that are used to render the UI on Mono for Android apps.

" Values: As with the convention that native Android apps use, the Mono for Android framework has a great deal of tools built in for localization of apps. The values for each localization schema are stored in the Values directory.

" Activity: The convention for an Activity is the same in Mono for Android as it is with native Android apps written in Java. The convention is that each activity should reside in its own class, which inherits from the Android Activity type. In the example in Figure 12-22, there is only one activity.

Project Options Mono for Android behaves similarly to MonoTouch when it comes to linking development builds, with a few exceptions. By default debug builds do not link the Mono framework. The Mono Framework is installed as a separate library named Mono Shared Runtime for debug builds. Release builds link to a custom-built Mono Framework build containing only the features that your app uses. For debug builds, these settings can be changed using the build settings as shown in Figure 12-23.

FIGURE 12!22: Mono for Android project structure

FIGURE 12!23: Mono for Android linker settings

c12.indd 361c12.indd 361 28/07/12 6:09 PM28/07/12 6:09 PM

362 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

The intention of this section was to give you an idea of the project structure, and basic interaction between the UI and code. To build upon this, you will now tackle a more complex native MonoTouch and Mono for Android app.

BUILDING THE DERBY APP WITH MONO The idea of the Derby App is to build the same app over all of the mobile platforms covered in this book. The MonoTouch and Mono for Android versions are very similar to the other versions that you have built thus far.

The requirements are to list the roster from the Lansing Derby Vixens roller derby team as the primary function, and then list all the roller derby teams in the world with the ability to see their team rosters.

MonoTouch For the iOS version of the Derby App, you fi rst need to create an iPhone Tabbed MonoTouch application as shown in Figure 12-25. The Tabbed application type provides a template that contains two views linked to a tab controller that you can use to start your project. The iPhone

Certain features of Android apps require permission from the user before the app can gain access to those features. Before users install your app on their mobile devices, they will be prompted with a list of features that your app will be using, providing the opportunity for the user to opt not to install your app because of a particular feature. In the Mono for Android app, to enable the features that your app is going to use, you must use the Mono for Android Project Options dialog box as shown in Figure 12-24.

FIGURE 12!24: Mono for Android permissions

c12.indd 362c12.indd 362 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 363

User Interface When it boils down to it, the Derby App does not contain a complex user interface. All of the screens are simply lists of data. When the user interface is simple, creating the controls within code is oftentimes an option. For the MonoTouch Derby App, the UITableView controls are created and added programmatically.

To get started, rename the fi rst view code and XIB fi le from FirstViewController to VixensController. For the code fi les, it’s best to right-click the class name and select the Rename option from the Refactor menu as shown in Figure 12-26. This ensures that all of the constructors and places that the class is initiated are changed as well.

With the fi rst ViewController renamed, your project should look similar to the project shown in Figure 12-27.

project type was selected because the only interface to the Derby App that has been shown has been a mobile phone interface, not a tablet interface. The Storyboard option was not selected, just to provide additional examples of how to work with user interfaces within iOS and Interface Builder.

FIGURE 12!25: Tabbed MonoTouch iPhone app creation

FIGURE 12!26: Rename refactor within MonoDevelop

c12.indd 363c12.indd 363 28/07/12 6:09 PM28/07/12 6:09 PM

364 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Creating the Vixen Table View Just as with a native iOS app created in Objective-C, the ViewDidLoad event is fi red right after the View has loaded. Within the VixensController, this is where the table view that contains the list of all the Lansing Derby Vixens will be created.

Creating a UI Table view is as simple as:

" Creating a new instance of the UITableView object.

" Setting the dimensions and where in the view it will be rendered.

" Adding the newly created table view as a subview to the view (in this case the Vixens View) you are working with.

The following code shows this process.

public override void ViewDidLoad () { base.ViewDidLoad (); UITableView tableView = new UITableView(); tableView.Frame = new RectangleF (0, 0, this.View.Frame.Width,this.View.Frame.Height); this.View.AddSubview(tableView); }

Populating the Vixens Table View After the table view has been created, the data that will populate the view needs to be received. To do this, I have created a helper class named Network that contains static helper functions that will retrieve the data needed to populate the table views throughout the Derby App.

To get the roster of a team, the GetRoster function is called with the team name of the data you are looking for. You have a few different methods within .NET to choose when it comes to mapping a JSON response to an object. The following example simply loops through each of the JSON items returned and manually builds the DerbyName object:

public static List<DerbyName> GetRoster(string leagueName) { List<DerbyName> tmpRtn = new List<DerbyName>(); String requestURL = “http://derbynames.gravityworksdesign.com /DerbyNamesService.svc /DerbyNames?$filter=League%20eq%20’” + leagueName + “’”;

HttpWebResponse response = GetServiceResponse(requestURL); JsonObject fullJsonObject = (JsonObject)JsonObject.Load(response.GetResponseStream());

var rosterData = fullJsonObject[“d”];

foreach (JsonObject singleEntry in rosterData) { tmpRtn.Add(new DerbyName(singleEntry[“DerbyNameId”],

FIGURE 12!27: First view renamed

c12.indd 364c12.indd 364 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 365

singleEntry[“Name”],singleEntry[“Number”] ,singleEntry[“League”])); }

return tmpRtn; }

private static HttpWebResponse GetServiceResponse (string url) { HttpWebResponse tmpRtn; var request = (HttpWebRequest) WebRequest.Create (url);

tmpRtn = (HttpWebResponse) request.GetResponse ();

return tmpRtn; }

The data that is returned is a list of DerbyName name objects for the team name that was passed in; in this case, “Lansing Derby Vixens.”

After the data has been retrieved, you need to set the DataSource property on the TableView that will display the data. In this case, set the DataSource to a new TableViewDataSource object (which you will create in the future), passing it a list of strings that contains the names of the Lansing Derby Vixens. You can do this by adding the following code to the ViewDidLoad event:

public override void ViewDidLoad () { base.ViewDidLoad (); UITableView tableView; string teamName = “Lansing Derby Vixens”; List<DerbyName> fullRosterData = Network.GetRoster(teamName); List<string> data = new List<string>(); fullRosterData.ForEach(derbyName => data.Add(derbyName.Name));

tableView = new UITableView(); tableView.DataSource = new TableViewDataSource(data); tableView.Frame = new RectangleF (0, 0, this.View.Frame.Width,this.View.Frame.Height); this.View.AddSubview(tableView); }

To fully bind the data to the table view, you need to implement a few more functions. Create these functions in a new class named TableViewDataSource, which was bound to the data source of the table view.

The TableViewDataSource class contains a constructor that contains the data that will be bound to the TableView, in this case a list of strings:

public TableViewDataSource (List<string> list) { this.list = list; }

c12.indd 365c12.indd 365 28/07/12 6:09 PM28/07/12 6:09 PM

366 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

For the table view to know how many rows it needs to select, you must implement the RowsInSection method. In this case, you just return the count of the number of items in the list object, which is the list of strings that you populated when the view loaded:

public override int RowsInSection (UITableView tableview, int section) { return list.Count; }

The magic really happens in the GetCell method. This method is called for the number of times that was returned in the RowsInSection. In your code, create a new cell, get the data for the correct position in the list object, and then return the cell you created, which will be added to the table:

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) { UITableViewCell cell = tableView.DequeueReusableCell (kCellIdentifier);

if (cell == null) { cell = new UITableViewCell (UITableViewCellStyle.Default,kCellIdentifier); }

cell.TextLabel.Text = list[indexPath.Row]; return cell; }

When complete, the TableViewDataSource class contains two methods and one constructor:

private class TableViewDataSource : UITableViewDataSource { static NSString kCellIdentifier = new NSString (“DerbyName”); private List<string> list;

public TableViewDataSource (List<string> list) { this.list = list; }

public override int RowsInSection (UITableView tableview, int section) { return list.Count; }

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath) { UITableViewCell cell = tableView.DequeueReusableCell (kCellIdentifier); if (cell == null) { cell = new UITableViewCell ( UITableViewCellStyle.Default, kCellIdentifier);

c12.indd 366c12.indd 366 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 367

}

cell.TextLabel.Text = list[indexPath.Row]; return cell; } }

With the table view data wired, you should be able to run the app, (by pressing the run button in the toolbar) and view the Derby Vixen roster as shown in Figure 12-28.

Leagues/Team Name The Leagues tab lists all of the roller derby leagues in a TableView. The name of this controller is LeagueController. Creating the Leagues tab is very similar to the Vixens tab, with two exceptions. The fi rst is the function that is called to obtain the data that is displayed in the list. Because this is a list of leagues, you will call the GetLeagueData function found in the network class. This function returns a list of League objects, returned from the Derby service.

public static List<League> GetLeagueData() { List<League> tmpRtn = new List<League>(); string requestURL = “http://derbynames.gravityworksdesign.com /DerbyNamesService.svc/Leagues”;

HttpWebResponse response = GetServiceResponse(requestURL); JsonObject fullJsonObject = (JsonObject)JsonObject.Load(response.GetResponseStream()); var leagueData = fullJsonObject[“d”];

foreach (JsonObject singleEntry in leagueData) { tmpRtn.Add(new League(singleEntry[“LeagueId”],singleEntry[“LeagueName”])); }

return tmpRtn; }

The second difference between the views is that the League Roster screen that lists the team members for the selected league should appear when a cell is touched on the leagues view. To accomplish this, within the LeaguesController code fi le, create a new delegate that derives from UITableViewDelegate. The RowSelected event is wired up inside this delegate, which simply creates a new LeagueRoster view (which you have not created yet), sets the team name you want to load, and then pushes the view to the iOS navigation stack to make the LeagueRoster view show.

private class TableViewDelegate : UITableViewDelegate { LeaguesController leagueController; private List<string> list;

FIGURE 12!28: Derby Vixens roster rendering in Table View

c12.indd 367c12.indd 367 28/07/12 6:09 PM28/07/12 6:09 PM

368 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

public TableViewDelegate(List<string> list, LeaguesController controller) { this.leagueController = controller; this.list = list; }

public override void RowSelected (UITableView tableView, NSIndexPath indexPath) { LeagueRoster roster = new LeagueRoster(); roster.TeamName = list[indexPath.Row];

leagueController.NavigationController.PushViewController(roster,true); } }

League Roster The LeagueRoster view is shown when a user selects a league/team from the team name page. The name of this view is LeagueRoster. This view is almost identical to the Vixens view with one exception. To know which league/team you are loading the roster for the name needs to be passed into this view. You can do this by adding a property named TeamName to the LeagueRoster class:

public string TeamName { get; set; }

The GetRoster function within the ViewDidLoad event uses the TeamName property instead of the hard-coded “Lansing Derby Vixens” value to retrieve the roster for the team name set in the TeamName property:

public override void ViewDidLoad () { base.ViewDidLoad (); UITableView tableView;

List<DerbyName> fullRosterData = Network.GetRoster(this.TeamName); List<string> data = new List<string>(); fullRosterData.ForEach(derbyName => data.Add(derbyName.Name));

tableView = new UITableView(); tableView.DataSource = new TableViewDataSource(data); tableView.Frame = new RectangleF (0, 0,this.View.Frame.Width, this.View.Frame.Height);

this.View.AddSubview(tableView); }

Figure 12-29 shows the roster view for a selected team.

Mono for Android For the Android version of the Derby App, you fi rst need to create a new Mono for Android application as shown in Figure 12-30. This will provide a simple Android app to which you will then be able to add your specifi c derby logic. FIGURE 12!29: Roster

View for team

c12.indd 368c12.indd 368 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 369

This version of the Derby App is going to use a few Android features that were introduced with Android version 3.0, Gingerbread. To be on the safe side, for this project you will want to target the latest Android SDK. You will want to make sure that the Android project options have the minimum API level set to 14 for Android 4.0 as shown in Figure 12-31.

FIGURE 12!30: Creating a new Mono for Android project

FIGURE 12!31: Setting the minimum SDK to the latest version

c12.indd 369c12.indd 369 28/07/12 6:09 PM28/07/12 6:09 PM

370 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

User Interface As with Android apps that are created using Eclipse and Java, the user interface XML fi les for Mono for Android apps are located under the Resources # Layouts directory of the project. For the Derby app you are going to have one main view that contains two tabs that will load the interface using a concept called a fragment. A fragment is simply a chunk of user interface logic with its own life cycle. The following lists the fi les required for the Derby App user interface:

" Main.axml: The Main layout fi le for the Mono for Android Derby app contains a linear layout and a frame layout. The frame layout is used as a container where the fragments will be loaded:

<?xml version=”1.0” encoding=”utf-8”?> <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android” android:orientation=”vertical” android:layout_width=”fill_parent” android:layout_height=”fill_parent”> <FrameLayout android:id=”@+id/fragmentContainer” android:layout_width=”match_parent” android:layout_height=”0dip” android:layout_weight=”1” /> </LinearLayout>

" Tab.axml: Each tab that is created for the Derby app will use Tab.axml for the interface. The tab’s user interface is simply a list view that will render the data:

<ListView xmlns:android=”http://schemas.android.com/apk/res/android” android:id=”@+id/DerbyData” android:layout_width=”wrap_content” android:layout_height=”wrap_content” />

" List_item.axml: Remember from Chapter 6 that each item that is rendered in a list view will have a layout fi le to specify how the data will be rendered in the list view. For the Mono for Android Derby app, just a TextView control is used to render the data. If you wanted to get fancy and add a team icon or player photo, this layout would be modifi ed to accomplish this:

<?xml version=”1.0” encoding=”utf-8”?> <TextView xmlns:android=”http://schemas.android.com/apk/res/android” android:layout_width=”fill_parent” android:layout_height=”fill_parent” />

With the layout fi les completed, you can add the code that is required to display the UI. In the OnCreate method of the Main.cs fi le, the navigation mode of the action must be set to Tabs, which will allow for a tabbed interface to be rendered. Calls to custom methods named AddVixenTab and AddLeagueTab add the fragments that will fi nish creating the interaction of the tab and the main layout:

c12.indd 370c12.indd 370 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 371

protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle);

SetContentView (Resource.Layout.Main); this.ActionBar.NavigationMode = ActionBarNavigationMode.Tabs; AddVixenTab (“Vixens”); AddLeagueTab (“Teams”); }

To add the tabs to the Action Bar, fi rst create an ActionBar.New tab with the text that will be rendered on the screen:

var tab = this.ActionBar.NewTab (); tab.SetText (tabText);

After the tab has been created, you need to wire the TabSelected event to load the user interface of the tab that was selected. In this case the Vixen Tab was selected, therefore you should remove the LeagueTab from focus and display a new Vixen Tab to the user using fragments.

tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) { m_vixenTab = new VixenTab(); e.FragmentTransaction.Add (Resource.Id.fragmentContainer, m_vixenTab); e.FragmentTransaction.Remove(m_leagueTab); };

After the TabSelected event has been wired, you simply need to add the newly created ActionBar .Tab to the ActionBar of the Derby App:

this.ActionBar.AddTab (tab);

Creating the tabs for both the Vixens and the Leagues/Teams names is similar, with the only exception of what is rendered in the tab (VixenTab or LeagueTab). The following code shows the completed logic for adding both the Vixens and Leagues tabs:

private void AddVixenTab (string tabText) { var tab = this.ActionBar.NewTab (); tab.SetText (tabText); tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) { m_vixenTab = new VixenTab(); e.FragmentTransaction.Add (Resource.Id.fragmentContainer, m_vixenTab);

e.FragmentTransaction.Remove(m_leagueTab); }; this.ActionBar.AddTab (tab); }

c12.indd 371c12.indd 371 28/07/12 6:09 PM28/07/12 6:09 PM

372 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

private void AddLeagueTab (string tabText) { var tab = this.ActionBar.NewTab (); tab.SetText (tabText); tab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e) { m_leagueTab = new LeagueTab(); e.FragmentTransaction.Add (Resource.Id.fragmentContainer, m_leagueTab);

e.FragmentTransaction.Remove(m_vixenTab); }; this.ActionBar.AddTab (tab); }

Getting The Vixens Roster With the user interface complete, you can now complete the logic to render the data on the screen for the Vixens tab. The user interface that will be infl ated for the Vixens tab is the Tab.axml. If you remember, this layout fi le contains only a ListView control:

var view = inflater.Inflate (Resource.Layout.tab, container, false);

To get the roster for the Lansing Derby Vixens, you call the static GetRoster function found within the Network class. This code is identical to the logic that was created for the MonoTouch app:

List<DerbyName> fullDerbyNameData = Network.GetRoster(teamName);

After the user interface has been infl ated and the data has been received, you can bind the data to the ListView:

derbyData.Adapter = new ArrayAdapter<string> (container.Context, Resource.Layout.list_item, data.ToArray());

The following code shows the entire OnCreateView function for the Vixens tab:

public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { base.OnCreateView (inflater, container, savedInstanceState); var view = inflater.Inflate (Resource.Layout.tab, container, false); var derbyData = view.FindViewById<ListView> (Resource.Id.DerbyData); string teamName = “Lansing Derby Vixens”; List<DerbyName> fullDerbyNameData = Network.GetRoster(teamName); List<string> data = new List<string>(); fullDerbyNameData.ForEach(derbyName => data.Add(derbyName.Name)); derbyData.Adapter = new ArrayAdapter<string> (container.Context, Resource.Layout.list_item, data.ToArray()); return view; }

c12.indd 372c12.indd 372 28/07/12 6:09 PM28/07/12 6:09 PM

Building the Derby App with Mono ! 373

Getting the Leagues and TeamName The logic for creating the Leagues tab is similar to the logic used for creating the Vixens tab. First you call the static function GetLeagues found within the Network class to retrieve a list of leagues. Again this code is identical to the logic used in the MonoTouch Derby App to retrieve the leagues.

Also, the ItemClick event on the derbyData list view has been wired so that when it is clicked, a new activity is started that will display the roster for the team that was selected. To accomplish this, you create a new Intent, and save the TeamName as an extra that is pushed to the newly created activity:

derbyData.ItemClick += delegate (object sender, ItemEventArgs args) { string teamName = ((TextView)args.View).Text; Intent rosterList = new Intent(container.Context, typeof(LeagueRoster)); rosterList.PutExtra(“TeamName”, teamName); this.StartActivity(rosterList); };

The entire OnCreateView function for the Leagues tab is shown here:

public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { base.OnCreateView (inflater, container, savedInstanceState); var view = inflater.Inflate (Resource.Layout.tab, container, false); var derbyData = view.FindViewById<ListView> (Resource.Id.DerbyData); List<League> fullLeagueData = Network.GetLeagueData(); List<string> data = new List<string>(); fullLeagueData.ForEach(league => data.Add(league.LeagueName)); derbyData.Adapter = new ArrayAdapter<string> (container.Context, Resource.Layout.list_item, data.ToArray()); derbyData.ItemClick += delegate (object sender, ItemEventArgs args) { string teamName = ((TextView)args.View).Text; Intent rosterList = new Intent(container.Context, typeof(LeagueRoster)); rosterList.PutExtra(“TeamName”, teamName); this.StartActivity(rosterList); }; return view; }

Getting The Team Roster The pattern of pushing data to a list view should be starting to look very familiar to you by now. The team roster view again is the same concept. The LeagueRoster class inherits from ListActivity so there is no need to infl ate the user interface that contains the ListView control.

c12.indd 373c12.indd 373 28/07/12 6:09 PM28/07/12 6:09 PM

374 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

Also, to load the team roster, you need to get the TeamName that was passed into the Activity. You can do this by calling the GetStringExtra method found within the Intent. In this case, if one is not passed in, you default to “Lansing Derby Vixens”:

string teamName = Intent.GetStringExtra(“TeamName”) ?? “Lansing Derby Vixens”;

The entire onCreate method for the LeagueRoster class is as follows:

protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); string teamName = Intent.GetStringExtra(“TeamName”) ?? “Lansing Derby Vixens”; List<DerbyName> fullRosterData = Network.GetRoster(teamName); List<string> data = new List<string>(); fullRosterData.ForEach(derbyName => data.Add(derbyName.Name)); ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.list_item, data.ToArray()); }

With all of the code in place, the Mono for Android Derby app should look similar to Figure 12-32.

OTHER USEFUL MONOTOUCH/MONO FEATURES

In the two example projects up to this point we have provided the basics for creating MonoTouch and Mono for Android applications that will go out to a web service and render the collected data on the screen. By no means do we feel that we have covered every possible situation you may need to develop a solution for, so we wanted to fi nish this chapter by providing a few more short examples that will help you out when discovering how MonoTouch and Mono for Android work.

Local Storage Even if your application is using a web service for retrieving information, at some point you may need to save information on the device.

MonoTouch plist For apps written in MonoTouch, property lists (plists) are the simplest way to store information on the device. In the Mac world, many applications use the plist format to store

FIGURE 12!32: Mono for Android Derby App

c12.indd 374c12.indd 374 28/07/12 6:09 PM28/07/12 6:09 PM

Other Useful MonoTouch/Mono Features ! 375

application settings, information about the application, and even serialized objects. It’s best to keep the data contained in these fi les simple, though.

Different variable types require different functions to retrieve and get the plist setting. The following example illustrates the different ways to retrieve and then save plist settings within MonoTouch:

var plist = NSUserDefaults.StandardUserDefaults; // get plist item string stringSetting = plist.StringForKey(“StringSetting”); int intSetting = plist.IntForKey(“myIntKey”); bool boolSetting = plist.BoolForKey(“myBoolKey”); // save plist item plist.SetString(“string”, “StringSetting”); plist.SetInt(1, “IntSetting”); plist.SetBool(true, “BoolSetting”); plist.Synchronize();

Mono for Android Shared Preferences For apps written in Mono for Android, shared preferences are the simplest way to store information on the device. The Android framework enables shared preferences to be restricted to a single app, or even shared as world-readable/writable, allowing all apps to access these settings if you choose.

The following code illustrates saving and retrieving shared preferences:

// save shared preference item ISharedPreferences saveSharedPreference = GetPreferences (FileCreationMode.Append); ISharedPreferencesEditor editor = saveSharedPreference.Edit (); editor.PutString (“StringSetting”, “string”); editor.PutInt (“IntSetting”, 1); editor.PutBoolean (“BoolSetting”, false); editor.Commit (); // get shared preference item ISharedPreferences getSharedPreference = GetPreferences (FileCreationMode.Append); string stringSetting = getSharedPreference.GetString (“StringSetting”, “Default Value”);

int intSetting = getSharedPreference.GetInt (“IntSetting”, 1); bool boolSetting = getSharedPreference.GetBoolean (“BoolSetting”, true);

GPS One of the great benefi ts of mobile devices is GPS functionality. Once you are able to get over the hurdles of learning the basic functions within MonoTouch and Mono for Android, working with the GPS functions can be a great deal of fun.

c12.indd 375c12.indd 375 28/07/12 6:09 PM28/07/12 6:09 PM

376 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

MonoTouch GPS For MonoTouch, you can fi nd the GPS functionality in the MonoTouch.CoreLocation namespace. The CLLocationManager is the class you will be using to obtain the GPS information. Keeping with the pattern on MonoTouch trying to match the Objective-C way of doing things, MonoTouch uses the delegate design pattern to handle the location updates. Simply put, GPS in MonoTouch is just a matter of:

" Instantiating a CLLocationManager object.

" Confi guring settings on the CLLocation manager such as accuracy.

" Assigning a delegate that will handle the location updates.

The following code creates the CLLocationManager object, and tells it to start tracking your location. You assign the delegate of the location manager object to an object named LocationDelegate, which is a custom-created class.

CLLocationManager locationManager = new CLLocationManager ();

locationManager.Delegate = new LocationDelegate (); locationManager.StartUpdatingLocation ();

The custom-created LocationDelegate object derives from CLLocationManagerDelegate and will handle location updates when they occur. In this example, you simply write the new location to the console:

public class LocationDelegate : CLLocationManagerDelegate { public LocationDelegate () : base() { } public override void UpdatedLocation (CLLocationManager manager, CLLocation newLocation, CLLocation oldLocation) { Console.WriteLine(newLocation.Speed.ToString () + “meters/s”); Console.WriteLine(newLocation.Coordinate.Longitude.ToString () + “˚”); Console.WriteLine(newLocation.Coordinate.Latitude.ToString () + “˚”); Console.WriteLine(newLocation.Altitude.ToString () + “meters”); } }

Mono for Android GPS Mono for Android provides an interface named ILocationListener located in the Android .Locations namespace that will allow GPS information to be collected from the device:

public class MonoForAndroidOther : Activity,ILocationListener

Before looking at the code, it’s important to note that you must ensure that your app has permission to obtain the level of GPS information you are looking to retrieve. Figure 12-33 shows a Mono for Android app with both ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions set.

c12.indd 376c12.indd 376 28/07/12 6:09 PM28/07/12 6:09 PM

Summary ! 377

With the correct permissions set, you need to create a new LocationManager object when the activity fi rst starts. This object manages the aspects of the location data that is being sent to your app from the operating system. You can set a Criteria object, which contains settings such as Accuracy, on the LocationManager to give you fi ne control of the data that is being sent from the operating system. The RequestLocationUpdates function enables a developer to set how often the GPS data is being sent to your app, which is useful to help conserve battery life.

The following code example creates a new LocationManager with no Accuracy requirements. The last location is also retrieved and written to the console if it exists.

LocationManager locationManager = (LocationManager)GetSystemService(LocationService);

var criteria = new Criteria() { Accuracy = Accuracy.NoRequirement }; string bestProvider = locationManager.GetBestProvider(criteria, true);

Location lastLocation = locationManager.GetLastKnownLocation(bestProvider);

if (lastLocation != null) { Console.WriteLine(“Last location, lat: {0}, long: {1}”, lastLocation.Latitude, lastLocation.Longitude); }

locationManager.RequestLocationUpdates(bestProvider, 5000, 2, this);

When implementing the ILocationListener, the OnLocationChanged event is required. This event is fi red when the location has changed. In the following example, the Latitude and Longitude are written to the console:

void ILocationListener.OnLocationChanged (Location location) { Console.WriteLine(“Location updated, lat: {0}, long: {1}”, location.Latitude, location.Longitude); }

SUMMARY This chapter spent a great deal of time describing the MonoTouch and Mono for Android platform. After reading this chapter, you should be comfortable installing the development tools and getting started developing and debugging your fi rst MonoTouch and Mono for Android app. Every development platform has trade-offs. As discussed in this chapter, the major downside to creating mobile apps with MonoTouch and Mono for Android is that they are third-party commercial

FIGURE 12!33: Android location permission

c12.indd 377c12.indd 377 28/07/12 6:09 PM28/07/12 6:09 PM

378 ! CHAPTER 12 GETTING STARTED WITH MONOTOUCH AND MONO FOR ANDROID

products, which can leave you waiting for updates to the standard device SDKs and out of luck if the company goes out of business.

If you have a good working understanding of .NET and C#, creating mobile apps in MonoTouch and Mono for Android may be a viable option. If you or your team already has this understanding, you may be able to roll out your mobile app faster and cheaper. However, just understanding .NET is not enough. To develop MonoTouch and Mono for Android apps, a good working knowledge of the key components of an iOS and Android app are required to be successful.

c12.indd 378c12.indd 378 28/07/12 6:09 PM28/07/12 6:09 PM