Tuesday, 30 September 2014

iPhone 6 and 6 Plus LaunchScreen.storyboard for Xamarin

Following on from the previous post about adding launch images for iPhone 6 and 6 Plus, here are the instructions for adding a LaunchScreen.storyboard file instead of multiple fixed-size images. Apple's documentation recommends this method over using the static images. I used these instructions for replacing launch images with storyboards as a reference.

Configuring a LaunchScreen like this will automatically scale up your app for iPhone 6 and iPhone 6 Plus devices. You might also want to consider adding @3x retina images for iPhone 6 Plus support.

1. Add a new Storyboard to your project and call it LaunchScreen.storyboard.

2. Drag a UIViewController in and design your launch screen. I chose a black background with some white centered text - it looks like this (use the VIEW AS option to preview in different sizes):
3. Open the iPhone application Project Options and scroll down to the iPhone Launch Images section. There is a new Launch Screen dropdown (currently in Beta) that will automatically be populated with the available storyboards and xibs in your project. Choose the storyboard you just added.
3a. This creates the following key in your Info.plist (just FYI):
 <key>UILaunchStoryboardName</key>
 <string>LaunchScreen</string>

4. When you build the app, appropriate launch images will be generated for your app. Here's a shot of the emulator starting up showing the launch image for iPhone 6:

I've updated my Xamarin.Forms Todo sample, the code and storyboard are available on github.

UPDATE: Gerry reminded me about Marco's experience where adding a LaunchImage.storyboard file causes iOS to ignore the UIDeviceFamily setting in Info.plist (which specifies iPhone/iPod, iPad, or Universal app) and upscale iPhone-only apps to full iPad screen size (potentially making your app look really weird!). This behavior still appears to occur on the simulator, so test before you launch :)




Monday, 22 September 2014

iPhone 6 and 6 Plus Launch Images for Xamarin

I was initially stumped by how to get my Xamarin.iOS and Xamarin.Forms apps to size correctly on the iPhone 6 and iPhone 6 Plus. Thanks to this StackOverflow question & answer I have a solution - reposting here because the solution that works best for me right now is only the 3rd most popular answer there.

Simply create two new default images (this is for portrait only, but landscape will become obvious later):

Default-667h@2x.png for iPhone 6; dimensions 752x1334

Default-736h@3x.png for iPhone 6 Plus; dimensions 1242x2208

and place them in the application root or the Resources folder. Notice the filename format is similar to the Default-568h@2x.png image that Apple introduced for the iPhone 5 screen.

Now edit the source of your Info.plist file (open in a text editor so you can type XML directly) and add the following UILaunchImages key:

<key>UILaunchImages</key>
<array>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>7.0</string>
<key>UILaunchImageName</key>
<string>Default-568h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{320, 568}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>8.0</string>
<key>UILaunchImageName</key>
<string>Default-667h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{375, 667}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>8.0</string>
<key>UILaunchImageName</key>
<string>Default-736h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{414, 736}</string>
</dict>
</array>
If you wish to support landscape images, add matching keys with Default-Landscape-???h filenames and specify the correct orientation and size.

Note that this is not Apple's preferred way of indicating support for the screen sizes. Their Launch Images doc says:

You use a launch XIB or storyboard file to indicate that your app runs on iPhone 6 Plus or iPhone 6.

which requires you to create a Storyboard or XIB using size classes. More on how to do that in future, or head back to that StackOverflow post!

p.s. this iPhone 6 Screens Demystified post by PaintCode is awesome!

Sunday, 29 September 2013

Android TextToSpeech API with Xamarin: it talks too!

A recent post covered Apple's new text-to-speech API in iOS 7, but forgot to mention that Android has actually had this capability for a while! It's really easy to add text-to-speech to a Xamarin.Android app: just implement TextToSpeech.IOnInitListener (which is a single method: OnInit) then create a new TextToSpeech instance:

speaker = new TextToSpeech (this, this);

and call Speak:

void Speak(string text) {
   var p = new Dictionary ();
   speaker.Speak (text, QueueMode.Flush, p);
}

The TaskyPro sample code has been updated so that both the iOS and Android apps have a Speak button. The Android app looks like this:

Check out this cool TtsSetup sample for Xamarin (via StackOverflow) for more details on how to customize the Android TextToSpeech API.

Friday, 27 September 2013

Built-in Barcode Scanning with iOS7 and Xamarin: MonkeyScan!

Another new iOS 7 feature is built-in support for barcode-scanning via the AVFoundation AVCaptureDevice API. Back in 2012 I threw together MonkeyScan using Windows Azure Services and the ZXing barcode scanning library. For iOS 7 I've updated the code to use the Azure Mobile Services Component and the new iOS 7 barcode scanning API instead.

The app looks like this when scanning a PassKit pass:

The code that sets up an AVCaptureDevice for 'metadata capture' (as opposed to capturing an image or video, I guess :) is shown below:

bool SetupCaptureSession () {
   session = new AVCaptureSession();
   AVCaptureDevice device = 
      AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
   NSError error = null;
   AVCaptureDeviceInput input = 
      AVCaptureDeviceInput.FromDevice(device, out error);

   if (input == null)
      Console.WriteLine("Error: " + error); 
   else
      session.AddInput(input);

   AVCaptureMetadataOutput output = new AVCaptureMetadataOutput();
   var dg = new CaptureDelegate(this);
   output.SetDelegate(dg, MonoTouch.CoreFoundation.DispatchQueue.MainQueue);
   session.AddOutput(output); // MUST add output before setting metadata types!

   output.MetadataObjectTypes = new NSString[] 
      {AVMetadataObject.TypeQRCode, AVMetadataObject.TypeAztecCode};

   AVCaptureVideoPreviewLayer previewLayer = new AVCaptureVideoPreviewLayer(session);
   previewLayer.Frame = new RectangleF(0, 0, 320, 290);
   previewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill.ToString();
   View.Layer.AddSublayer (previewLayer);

   session.StartRunning();
   return true;
}

You can specify specific barcodes to recognize or use output.AvailableMetadataObjectTypes to process all supported types.

...and it speaks!
Since the app now requires iOS 7, it can also use the new AVSpeechSynthesizer to speak the scan result as well (see previous post).

if (valid && !reentry) {
   View.BackgroundColor = UIColor.Green;
   Speak ("Please enter");
} else if (valid && reentry) {
   View.BackgroundColor = UIColor.Orange;
   Speak ("Welcome back");
} else {
   View.BackgroundColor = UIColor.Red;
   Speak ("Denied!");
}

The MonkeyScan github repo has been updated with this code.

Thursday, 26 September 2013

iOS SpeechSynthesizer API with Xamarin: it talks!

Mike posted a neat code example today on adding the new iOS 7 AVSpeechSynthensizer API to a Xamarin app.

It's so easy, I added speech synthesis to the this TaskBoard to-do list example in about 5 lines of code. Now the app can read the to-do item back to you :) just by adding this code:

if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0)) {
   SpeakButton.TouchUpInside += (sender, e) => {    // requires iOS 7
      Speak (TitleText.Text + ". " + NotesText.Text);
   };
}

and

void Speak (string text) {
   var speechSynthesizer = new AVSpeechSynthesizer ();

   var speechUtterance = new AVSpeechUtterance (text) {
      Rate = AVSpeechUtterance.MaximumSpeechRate/4,
      Voice = AVSpeechSynthesisVoice.FromLanguage ("en-AU"),
      Volume = 0.5f,
      PitchMultiplier = 1.0f
   };

   speechSynthesizer.SpeakUtterance (speechUtterance);
}

The UI now looks like this: touch the Speak button to hear the text read back to you.

Wednesday, 10 July 2013

New Dropbox API one day, on Xamarin the next

Long-time Xamarin customers know that there is a history of delivering updates same day when the native platforms (iOS and Android, for example) are upgraded. Today there was another little surprise - the new Dropbox Datastore API that was announced at DBX yesterday was made available via a Xamarin Component today!

Think of it as a cross-platform iCloud-like key-value store ~ same kind of stuff you can do with Parse or even Azure Mobile Services.

Check out the Xamarin Blog for all the details and a cute sample app called MonkeyBox.

But wait, there's more!
In the past I've posted about porting a small "To Do List" application to various different platforms, including Azure (iOS, Android, Mac and more) twice as well as an iCloud version for iOS.

Here's the same basic code using the new Dropbox Datastore API (just iOS, for now...):

Here's a direct link to the code on github... to use just download the solution (which includes the Xamarin Dropbox Component) and:

  1. Visit the Dropbox App Console to get your access credentials set-up.
  2. Add the App key and App secret to the AppDelegate.cs in the project.
  3. Add a Custom URL Type to the advanced Info.plist settings (replacing the identifier and also YOUR_APP_KEY with the correct credential value) like this

When the app is up-and-running, you can 'browse datastores' from the Dropbox App Console and see the data update on the server in real-time!

In only a few lines of code you can use a cloud-based data store simply and easily, across multiple platforms and devices! Load up the app on a couple of iOS devices (and/or the iOS Simulator) and watch the magic in action :)

Tuesday, 15 January 2013

Xamarin for Java Developers

Last night I was given the opportunity to present Xamarin's Mono for Android to the East Bay Google Developer Group. It was a lot of fun, with plenty of the audience asking a lot of great questions and generally being curious about how C# can be used to build Android apps. Here are the slides from the talk - please drop me a line with any feedback or questions!

One topical question was "what does using Xamarin and C# offer existing Android Java developers?". I have a couple of thoughts which are listed below (in no particular order):

Learn a new language!
The days of specializing in a single language throughout your career (or even throughout the year!) are over. Once upon a time it was COBOL all the way down, and you could argue that it's still enough to just know C/C++. But it's no longer the norm ~ developers want to grow and learn, and use the best tool for the job (whether it's Perl, PHP, Java, Ruby, C#, F#, Javascript, TypeScript, Go, or whatever).

It can be daunting though, to start from scratch and learn a new IDE, framework and syntax - which is why I think C# is a great progression for Java devs. The two languages are obviously related - there is a lot of common syntax and equivalent keywords that make it easy to get proficient quickly. They're both strongly typed, so the IDE and compiler can really help you learn. Then once you know the C# basics, a whole world of new APIs open up to you: LINQ, the .NET framework's serialization and web service features, Parallel Task Library and async support, reactive extensions, and more.

It also introduces you to another IDE (Visual Studio is a great tool, as is Xamarin's free MonoDevelop IDE), which in turn can encourage you to further explore other languages and platforms (suddenly it's a small leap to work on Windows Phone, or try F#). Using the free trial you can easily get productive in C# and Android development without any up-front cost: you can run your apps on the Android emulator, and choose to work on either Windows or Mac with MonoDevelop.

Cross-platform development!
There are a lot of Java developers who are already proficient with the Android SDK and have published successful apps to Google Play, or Amazon, or Samsung app stores; and there's another group of corporate/enterprise developers building apps for internal/extranet use that were designed for Android. When these developers ask "why Xamarin?", I never say "throw away everything you've done and re-write in C#!" -- that'd be crazy ;-)

But what happens when you want to take these apps cross-platform, either to make more money on the iOS and Mac App Stores or to better support a corporate BYOD policy which means your internal apps need to run on iOS and Windows? You can choose to learn Objective-C to write for iOS and C# for Windows... or take the opportunity provided by Xamarin to use C# for all the non-Java platforms and reduce the amount of code you have to support and re-write by half!

Following on from the first point, I think learning C# is a much smaller leap for a Java developer than Objective-C; and once you've done so you can work on either iOS apps using Xamarin's MonoTouch or Windows Phone, Windows 8 and Windows RT tablet apps! You might like C# so much that you do go back and re-write your Java, or at least start building a hybrid that shares some Java and C# code...

Xamarin does Android well too :)
If Java developers do fall in love with C# then they also find that Xamarin does Android just as well as anyone (probably better!). Our MonoDevelop IDE (and our integration with Visual Studio) means you get an awesome coding experience (autocomplete/intellisense/code completion, debugging, refactoring, source control integration, etc) as well as a drag-and-drop UI designer. You be the judge of whether it's a better experience than Eclipse :)

Fin
In summary, why not? As a Java developer you have a lot to gain and nothing to lose by giving C# a try. A whole world of new platforms, tools and frameworks become available with a very low barrier to entry. Try it - you just might like it ;-)