April 23, 2014

Getting Fit With Xamarin Apps

By

My StepCounter for iOSEvery day Xamarins are getting fit cycling, running, planking, rock climbing, and just about every other activity you can think of. We carry around our mobile devices with us every where we go and a few of us felt that they should be our fitness companions that rest in our pocket during these activities. A little over a month ago fellow Xamarin, Mike James, released My StepCounter for iOS. This is an elegant pedometer that takes advantage of the iPhone 5s’ built in M7 chip and the new Core Motion APIs in iOS 7. Best of all Mike also open sourced the entire project on GitHub for anyone to try out the source code for themselves.

My StepCounter AppIconToday, two new Xamarins are pleased to announce their fitness apps for Android. James Montemagno took the challenge of taking Mike’s My StepCounter and bringing it to Android using the latest Android 4.4 KitKat low power step sensor APIs. James combined this new API with animations and an ADO.NET database to take My StepCounter to the next level. Today, he announced that he has open sourced the project on GitHub and the app is available to download on Google Play.


My StepCounter for Android My StepCounter for Android

Xamarin Starter CompatibleMy StepCounter on both iOS and Android join a library of apps that were built to be Starter Edition Compatible. Starter Edition is our free tier, which allows anyone to get a taste of mobile development in C# by writing small apps which can be deployed to devices and published to app stores.

Bikr IconBikr AnimationsMaybe you prefer cycling over walking, well Jérémie Laval has you covered with Bikr. Bikr was built out of a passion for cycling and takes advantage of the latest Google Play Services Component to track your mileage while cycling on a daily, weekly, and monthly basis. In addition to tracking, Jérémie has also crafted some lovely animations to show you your progress. You can find Bikr available right now on Google Play and Jérémie is pleased to announce that he has open sourced Bikr for you to get your hands on.

Now that we have showed you a few of our apps we want you to show us your apps! Head over to our Community Forums where several of you have already been sharing the amazing apps that you have been creating with Xamarin.

Show Us Your Apps!

We can’t wait to see what you create with Xamarin.

TwitterFacebookGoogle+LinkedInEmail
April 22, 2014

Tips & Tricks for Highly Performing Android ListViews

By

I have been working with Xamarin.Android for a long time now and one question I get asked quiet often is how to optimize the Android ListView. Xamarin apps are native apps, which means that out of the box your app will take advantage of all of the optimizations that come with these views in the framework; however, when Google implemented the ListView they left out a few additional optimizations that developers can take advantage of to ensure a great user experience. Let’s first look at how the ListView and their adapters actually work:

Cell Reuse in Android ListView Adapters

What we see here is that Android is optimized for cell reuse. It will never take the number of cells that are displayed and cycle through them, so as your user scrolls through the list and a cell goes off the screen it is put into a recycle bin and then put back on top to be reused again. Let’s look at the standard code out of the box when creating an adapter and then optimize it:

First I will create a simple item for my adapter. It consists of two TextViews and one ImageView.

A simple android list adapter cell

BaseAdapter

For this example I have created a new Adapter and inherited from BaseAdapter. When I implement the GetView method, I could simply inflate the view, find the controls, and set the properties on them:

public override View GetView (int position, View convertView, ViewGroup parent)
{
  var view = activity.LayoutInflater.Inflate (Resource.Layout.OptimizedItem, null);
  var textView1 = view.FindViewById<TextView> (Resource.Id.textView1);
  var textView2 = view.FindViewById<TextView> (Resource.Id.textView2);
  var imageView = view.FindViewById<ImageView> (Resource.Id.imageView);
  textView1.Text = Names [position];
  textView2.Text = Descriptions [position];
  imageView.SetImageResource (Names [position].ToLower().Contains ("xamarin") ?
				   Resource.Drawable.hexagongreen :
				   Resource.Drawable.hexagopurple);
  return view;
}

There are a few issues with this implementation, which is that we are inflating the view and locating the controls each time GetView gets called. So let’s fix that.

Take Advantage of ConvertView

The first optimization we will want to make is to take advantage of the convertView that is passed into this method. In the official documentation for GetView it tells us exactly what the convertView is: “The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view.”

This means that if the convertView is null then we should inflate the view else we can simply fine the controls on view and set them.

public override View GetView (int position, View convertView, ViewGroup parent)
{
  var view = convertView;
  if(view == null) {
    view = activity.LayoutInflater.Inflate (Resource.Layout.OptimizedItem, null);
  }
  var textView1 = view.FindViewById<TextView> (Resource.Id.textView1);
  var textView2 = view.FindViewById<TextView> (Resource.Id.textView2);
  var imageView = view.FindViewById<ImageView> (Resource.Id.imageView);
  textView1.Text = Names [position];
  textView2.Text = Descriptions [position];
  imageView.SetImageResource (Names [position].ToLower().Contains ("xamarin") ?
				   Resource.Drawable.hexagongreen :
				   Resource.Drawable.hexagopurple);
  return view;
}

Now we will only inflate the view when necessary. This immediately leads to increased performance of our ListView, but we can do even better!

Implement a ViewHolder

The second issue I noted was that we are having to locate the controls with FindViewById every single time GetView is called, which can lead to performance issues. The way to get around having to use FindViewById is to implement a “ViewHolder” design pattern.

We will create a ViewHolder class to store all of the controls that are inside of the view so we can access them immediately without the need to use FindViewById each time. The first thing we will do is create a class to store the information:

private class MyViewHolder : Java.Lang.Object
{
  public TextView Name { get; set; }
  public TextView Description { get; set; }
  public ImageView Image { get; set; }
}

You might be wondering why we are inheriting from Java.Lang.Object, well the reason for this is because each view has a Tag property, that can be used to store information. The Tag property is of type Java.Lang.Object, so that forces us to inherit from it. Now that we have the ViewHolder setup we can finish the optimization by populating it, storing it inside the view, and accessing the controls from the holder instead of calling FindViewById:

public override View GetView (int position, View convertView, ViewGroup parent)
{
  MyViewHolder holder;
  var view = convertView;
  if(view != null)
    holder = view.Tag as MyViewHolder;
  if (holder == null) {
    holder = new MyViewHolder ();
    view = activity.LayoutInflater.Inflate (Resource.Layout.OptimizedItem, null);
    holder.Name = view.FindViewById<TextView> (Resource.Id.textView1);
    holder.Description = view.FindViewById<TextView> (Resource.Id.textView2);
    holder.Image = view.FindViewById<ImageView> (Resource.Id.imageView);
    view.Tag = holder;
  }
  holder.Name.Text = Names [position];
  holder.Description.Text = Descriptions [position];
  holder.Image.SetImageResource (Names [position].ToLower().Contains ("xamarin") ?
				 Resource.Drawable.hexagongreen :
				 Resource.Drawable.hexagopurple);
  return view;
}

There you have it, with just a few quick changes you will have your Adapters fully optimized to create the best user experience possible for your app. A few other notes, while I only mentioned the ListView these same optimizations can be used on your adapters for GridViews as well. Additionally, it is recommended to inherit from BaseAdapter instead of using an ArrayAdapter when exposing C# objects to avoid unnecessary bridge interaction when working in Xamarin.Android.

Discuss this blog post in the Xamarin Forums

TwitterFacebookGoogle+LinkedInEmail
April 17, 2014

Easy In App Purchases for iOS

By

Xamarin.iOS makes it easy to use Apple’s StoreKit API to include In App Purchasing in our iOS mobile applications. However, there’s quite a bit of repetitive code that has to be created for every app that includes it.

That’s where the new Xamarin.InAppPurchase component can help!

Xamarin.InAppPurchase in Use

Using Xamarin.InAppPurchase, we can easily and quickly add iTunes App Store In App Purchasing of products, features or subscriptions to our iOS mobile applications. All without any of the repetitive code required when calling StoreKit directly.

Working with Product Identifiers

By decorating our Product Identifiers with specific keywords, we can have Xamarin.InAppPuchase automatically handle things such as the product type, subscription duration, consumable quantities and downloading of hosted content from the iTunes App Store.

For example, we can use product.nonconsumable to define a non-consumable product, gold.coins.consumable_x25 a consumable package of 25 gold coins, magazine.subscription.duration1month an auto renewing monthly subscription and antivirus.nonrenewingsubscription.duration6months a non-renewing six month subscription.

So let’s take a look at how easy it is to get a list of available In App Products from the iTunes App Store with Xamarin.InAppPurchase by using the following code:

using Xamarin.InAppPurchase;
using Xamarin.InAppPurchase.Utilities;
...
public InAppPurchaseManager PurchaseManager = new InAppPurchaseManager ();
...
// Ask the iTunes App Store to return information about available In App Products for sale
PurchaseManager.QueryInventory (new string[] {
"product.nonconsumable",
"gold.coins.consumable_x25",
"newsletter.freesubscription",
"magazine.subscription.duration1month",
"antivirus.nonrenewingsubscription.duration6months",
"content.nonconsumable.downloadable",
});

After this code runs, the PurchaseManager will contain a list of any valid products with all of the localized information read from the iTunes App Store, ready for us to display to the end user.

When the user is ready to buy a given item, we can use the following code to start the purchase process with the iTunes App Store:

// Ask iTunes App Store to purchase product
PurchaseManager.BuyProduct (Product);

We can then monitor several of the events exposed by the PurchaseManager to update the app’s UI or activate new content or features. At any time we can ask if a given product has been purchased using:

// Was the feature purchased?
if (PurchaseManager.ProductPurchased("my.nonconsumabe.feature")) {
...
}

In addition, Xamarin.InAppPurchase will automatically track our consumable product quantities and subscription expiration dates and provides methods to work with them easily.

Secure Automatic Persistence

The Xamarin.InAppPurchase component includes ways to automatically and securely persist the user’s purchased products. This information can be stored either to the app’s user preferences, a local file, iCloud, or our own custom persistence methods.

Now, let’s look at restoring previous purchase history that has been automatically saved by the Xamarin.InAppPurchase component. We’ll add the following code before our call to QueryInventory above:

// Setup automatic purchase persistence and load any previous purchases
PurchaseManager.automaticPersistenceType = InAppPurchasePersistenceType.LocalFile;
PurchaseManager.PersistenceFilename = "AtomicData";
PurchaseManager.shuffleProductsOnPersistence = false;
PurchaseManager.RestoreProducts ();

With this code in place the Xamarin.InAppPurchase component automatically saves any changes to the user’s purchased products and restores that history when our iOS app starts.

Simulating the iTunes App Store

There are several situations that can arise when working with In App Purchases, many of which can be hard to test for. The Xamarin.InAppPurchase component provides the ability to simulate interaction with the iTunes App Store so we can fully test out our application. This helps to ensure and provide a smooth, issue free In App Purchase experience for our users.

Xamarin.InAppPurchase running in simulation

When running in the simulation mode, decorate your product identifiers with specific keywords to test such things as invalid product IDs, failed purchases, hosted content download, etc. You can even test products before they are added to iTunes Connect and can test In App Purchases inside the iOS Simulator on a Mac.

Let’s look at how easy it is to run the Xamarin.InAppPurchase component in the simulation mode. We’ll modify our code above to look like the following:

// Initialize the purchase manager
PurchaseManager.simulateiTunesAppStore = true;
...
// Ask the iTunes App Store to return information about available In App Products for sale
PurchaseManager.QueryInventory (new string[] {
    "product.nonconsumable",
    "feature.nonconsumable",
    "feature.nonconsumable.fail",
    "gold.coins.consumable_x25",
    "gold.coins.consumable_x50",
    "gold.coins.consumable_x100",
    "newsletter.freesubscription",
    "magazine.subscription.duration1month",
    "antivirus.nonrenewingsubscription.duration6months",
    "antivirus.nonrenewingsubscription.duration1year",
    "product.nonconsumable.invalid",
    "content.nonconsumable.downloadable",
    "content.nonconsumable.downloadfail",
    "content.nonconsumable.downloadupdate"
});
...
// Setup the list of simulated purchases to restore when doing a simulated restore of purchases
// from the iTunes App Store
PurchaseManager.simulatedRestoredPurchaseProducts = "product.nonconsumable,antivirus.nonrenewingsubscription.duration6months,content.nonconsumable.downloadable";

Now we can run our iOS mobile app and test interactions such as the purchasing of a product failing, downloading of hosted content failing halfway through, or any other event that can happen with In App Purchases.

For more details about the Xamarin.InAppPurchase component and to get a full demo iOS application built using it on the Xamarin Component Store.

TwitterFacebookGoogle+LinkedInEmail
April 16, 2014

Epic Evolve Sessions

By

Last year, Xamarin Evolve 2013 hosted over 80 training and conference sessions on a vast array of topics. This year will be even bigger. Join us in October for Xamarin Evolve 2014, with a full extra day to make room for even more amazing sessions. If you didn’t get to attend last years conference or just want to catch up on the great sessions that were presented you can watch online right now. Here are just a few of our favorites from Xamarin Evolve 2013 that you don’t want to miss:

How C# Saved My Marriage, Enhanced My Career, and Made Me an Inch Taller

with Scott Hanselman

Multiplatformism: Lessons Learned Bringing Bastion to Six New Platforms

with Andrew Wang

Getting the Most from Xamarin Studio

with Michael Hutchinson

Push Notifications with PushSharp

with Jonathan Dick

Buttons are a Hack

with Josh Clark

If you enjoyed these sessions, we have all the videos from Xamarin Evolve 2013 online. And you definitely don’t want to miss Xamarin Evolve 2014 in October — two full days of training from Xamarin University followed by three days live sessions from Xamarin and Industry experts. Don’t wait, Register for Evolve 2014 today!

TwitterFacebookGoogle+LinkedInEmail
April 15, 2014

C# Meetups featuring Google Glass, Bluetooth LE & More

By

Community growth continues to be explosive with new Mobile .NET developer groups starting all over the world. This month, we have already seen the inaugural meeting for a new group in Paris, France, and we are pleased to announced two new groups in Tampa Bay, FL and Madison, WI! So, April isn’t over yet as it packed full meetups happing everywhere on vast topics from MvvmCross, Intro to Xamarin, and Bluetooth LE!

Mobile .NET Developers Meetups April 2014

Here are some upcoming Xamarin developer group meetups:

New Group: Tampa Bay Xamarin User Group usa flag

  • Tampa Bay, FL: Wednesday, April 16th 7:00PM
  • First TBXUG Meeting – Intro to Xamarin

Boston Mobile C# Developers Group usa flag

  • Cambridge, MA: Thursday, April 17th 6:30PM
  • Developing for Google GlassChris Hardy, Xamarin

.NET BC canada flag

  • Vancouver, BC: Tuesday, April 22nd 6:00PM
  • Cross Platform Mobile Development for the C# Developer with XamarinJames Montemagno, Xamarin

New Group: Madison Mobile .NET Developers Group us

  • Madison, WI: Wednesday, April 23rd 5:30PM
  • Introduction to Xamarin

Dutch Mobile .NET Developers Group Netherlands flag

  • Aalsmeer, Netherlands: Thursday, April 24th 6:00PM
  • Responsive design and Bluetooth LE

Vancouver .NET Mobile Developers Group Canada

  • Vancouver, BC: Thursday, April 24th 6:30PM
  • Mobile Development Techniques using C# and MvvMCross

Detroit Mobile .Net Users Group us

  • Southfield, MI: Monday, April 28th 6:00PM
  • Build / Xamarin Recap, Humanitarian Toolbox

Sydney Mobile .Net Developers Group Australia Flag

  • Sydney, Australia: Tuesday, April 29th 6:30PM
  • Build 2014 and Cross Platform Visual State Management

If you don’t see your city listed above, don’t worry as new events and developer group meetups are being added frequently on the Xamarin Events forum.

If you are interested in starting a developer group in your city we are here to help you get started. We have tips and trick on staring a developer group, a brand new introduction to Xamarin slide deck, and of course our community sponsorship program to get you on your way. We also want to hear from you so please feel free to send us an email or tweet @XamarinHQ so we can help spread the word and continue to grow the Xamarin community.

TwitterFacebookGoogle+LinkedInEmail
April 10, 2014

Xamarin Evolve 2014 Registration Now Open

By

Untitled-1We are very excited to announce the opening of registration for Xamarin Evolve 2014, our worldwide developer conference! Join us and fellow developers from October 6-10 in Atlanta, Georgia for the largest cross-platform mobile development event of the year!

Even Bigger!

This year, we’re doubling capacity and adding an extra day of conference sessions to make room for more great content covering mobile development with C#, Visual Studio, and Xamarin Test Cloud. Evolve sessions will cover a range of topics, including game-changing Xamarin product announcements by Nat and Miguel, best practices in mobile user experience design, advanced cross-platform techniques, memory management, real world app case studies from leading companies, secure data integration, lightning talks and so much more.

World-Class Training

Xamarin University LogoAttend two days of training from Xamarin University spanning all topics from mobile development fundamentals to advanced areas such as security and code-sharing strategies.

Learn from Mobile Experts

Over the course of three days you will have the chance to attend an immense amount of live sessions covering all areas of mobile development by industry leaders and experts. The entire Xamarin engineering team will be on-hand for one-on-one mobile coaching to answer questions, debug code, and provide advance.

Xamarin Evolve Welcomes Top Sponsor, Microsoft

We are also delighted to announce today that Microsoft will be joining Evolve 2014 again as our sole Platinum Sponsor. In recent months, Xamarin and Microsoft have partnered globally to help developers build great apps with C#, Visual Studio, and Portable Class Libraries, and this past week, Xamarin joined with Microsoft to launch the .NET Foundation. Together, Xamarin and Microsoft bring C# to 2.6 billion devices, and together we will make Xamarin Evolve 2014 an event you won’t forget.

MicrosoftSponsorEvolve2014

Registration Now Open

Tickets for Xamarin Evolve 2014 our second worldwide developer conference, are officially available for purchase today.

Register Now

Team Xamarin

TwitterFacebookGoogle+LinkedInEmail
April 9, 2014

Swipe To Refresh added to Android

By

Swipe-to-Refresh animation

Google recently released an update to the Android support library bringing in an exciting new standard implementation of a pattern that they have been progressively introducing through applications such as GMail or Google Now.

This pattern, called swipe-to-refresh, uses an upward pull user feedback to inform the app that a data refresh is requested. This complete another common pattern, infinite scrolling, that instead use a downward movement to load more data.

We have updated our component to expose the new SwipeRefreshLayout class that implements the pattern. To make use of it, simply wrap in your existing Xamarin.Android app layout.

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/refresher"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>

Setting up the SwipeRefreshLayout instance is pretty easy from code. You simply have to define a color scheme and a callback that is invoked when an update operation is requested by the user.

refresher = FindViewById<SwipeRefreshLayout> (Resource.Id.refresher);
refresher.SetColorScheme (Resource.Color.xam_dark_blue,
                          Resource.Color.xam_purple,
                          Resource.Color.xam_gray,
                          Resource.Color.xam_green);
refresher.Refresh += async delegate {
	await forum.FetchItems (clear: true);
	refresher.Refreshing = false;
};

The color scheme can be any set of color or the same color. In any case, the first parameter is also used as the initial feedback bar background.

We have also added a dedicated sample that shows how this code can be integrated in a complete scenario, including a complex layout utilizing fragments.

TwitterFacebookGoogle+LinkedInEmail

OpenSSL “Heartbleed” Update

By

You might have read by now that details of the “Heartbleed” OpenSSL vulnerability were published earlier this week. For those that don’t already know, OpenSSL is a popular, general purpose cryptography library in wide use across the internet. Like nearly every company on the internet, we immediately took audit of our systems, and uncovered some systems using a vulnerable version of OpenSSL. We immediately began updating all Xamarin services that were affected, and as of Tuesday afternoon, no Xamarin systems are subject to this vulnerability.

We have also reissued all HTTPS certificates for all xamarin.com domains with new encryption keys, and have had the previous versions revoked by our issuer, which was also completed Tuesday evening. At this point, we believe that it is extremely unlikely that any of our systems were compromised before we patched OpenSSL; however, for an additional layer of security, we recommend that you take the following steps to safeguard your Xamarin account — especially if you used the same password for your Xamarin account as on other accounts hosted elsewhere:

  1. Sign out of your Xamarin account and then sign back in (you’ll want to do this in the IDE as well)
  2. Change your Xamarin account password

At Xamarin we are committed to your security and privacy. We are continuing to track the issue closely and will keep you up to date if anything new is discovered. For more information on this OpenSSL vulnerability visit www.heartbleed.com

TwitterFacebookGoogle+LinkedInEmail

C#, iOS, and Android Take Center Stage at Build

By

It was an exciting week for .NET developers with a slew of announcements at this years Build conference in San Francisco.

Microsoft Build Sign

The most anticipated Build session of the week hands down was Miguel’s “Go Mobile with C# and Xamarin”, where over 1,500 developers packed the main hall for a chance to see Miguel talk on the transformation of mobile development. The audience loves seeing his live coding session where he used iOS’ CoreImage and Twitter integration to add Sepia filter to an image and tweet it out to the world!

Packed house at Miguel de Icaza's build talk

Continuing to wow the crowd, Miguel unveiled our brand new Xamarin T-shirt Store app enabling developers to try out Xamarin to build their first app to order their very own limited edition C# shirt that he was rocking on stage.

A major highlight of the week was when C#’s lead architect, Anders Hejlsberg, open sourced the .NET Compiler Platform, Roslyn, live on stage. This marked a major milestone allowing developers to gain access to a plethora of information that compilers have about the code we write each day. Immediately after Anders open sourced Roslyn, our own Miguel de Icaza hit the stage to showcase the power of an open sourced Roslyn by compiling code with a modified version of Roslyn running on Mono inside of Xamarin Studio on a Mac!

If Roslyn wasn’t enough, Xamarin took part in the official launch of the .NET Foundation. This new foundation will foster open development, collaboration and community engagement on the .NET platform. Xamarin initial contribution consists of six open source .NET Projects including Mailkit, Mimekit, System.Drawing, and more! We are excited to join other community leaders including Laurent Bugnion, Niels Hartvig, Paul Betts, and other to aid in advancing .NET open source projects..NET Foundation

The excitement for Xamarin, C#, and mobile apps continued throughout the week with an always packed Xamarin booth. Thousands of developers got to chat and get a hands on demo of creating beautiful Android and iOS apps in C#.

Packed Xamarin booth at //Build/

Build wouldn’t be complete without an epic Xamarin party, and this year was no different. Our friends .NET joined us to co-host a mega party in downtown San Francisco. Thousands of developers packed in to get face time with Nat, Miguel, Joseph, and the rest of the Xamarin crew at a party that is not to be forgotten! We want to thank everyone that was able to stop by the party and booth.

Xamarin Build Event at Mezzanine

If you thought that Build was epic, you will absolutely want to join us for Xamarin Evolve, the largest mobile developer conference of the year. Tickets go on sale on April 10th, so make sure to visit the official Evolve website to sign up for details.

TwitterFacebookGoogle+LinkedInEmail
April 8, 2014

Native Printing with Android

By

The latest version of Android, KitKat, adds long-awaited printing support to the platform. Android applications can now provide low-level control of print jobs, in addition to print integration for applications incorporating web content. This makes KitKat particularly well-suited to hybrid applications built with Xamarin using Razor templates.

Android KitKat Printing

Printing with a WebView

First let’s look at the easy to use print support offered through the WebView control.

Printing requires 3 steps:

  1. In an Activity, get a reference to the PrintManager system service.
  2. Create an instance of a class that inherits from PrintDocumentAdapter.
  3. Call the PrintManager‘s Print method, passing it the print adapter.

The PrintDocumentAdapter is an abstract class that provides a contract to implement for supplying print content. For web content, the WebView class includes a PrintDocumentAdapter, making printing HTML from a WebView incredibly easy to do:

The following example shows a WebView built using the Android WebView template, which uses Razor as an HTML templating engine:

Android Printing from a Xamarin Razor Template

Although printing can be done using any WebView, integrating printing with Razor and this project template makes it really easy to build a hybrid application that can leverage native features such as KitKat printing.

Printing from the WebView with C# is as simple as adding these 2 lines of code in the activity:

var printMgr = (PrintManager)GetSystemService(Context.PrintService);
printMgr.Print("Razor HMTL Hybrid", webView.CreatePrintDocumentAdapter(), null);

When we call Print Android presents a system dialog, allowing the user to choose the print destination, as shown below:

Android Print Dialog

Custom Print Adapter

To print from native Android views, taking low-level control of the print layout, we can implement our own PrintDocumentAdapter.

For example, let’s say we would like to print the layout from the following screen:

Android Print Activity Low Level

In our implementation of PrintDocumentAdapter, the required methods to implement are:

  • OnLayout – Allows laying out print content based on the PrintAttributes.
  • OnWrite – Allows writing a PDF file with content to print.

In OnLayout, we create a PrintDocumentInfo instance, which contains metadata about the document being printed.

public override void OnLayout (PrintAttributes oldAttributes, PrintAttributes newAttributes,
                               CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
  document = new PrintedPdfDocument (context, newAttributes);
  CalculateScale (newAttributes);
  var printInfo = new PrintDocumentInfo
    .Builder ("MyPrint.pdf")
    .SetContentType (PrintContentType.Document)
    .SetPageCount (1)
    .Build ();
  callback.OnLayoutFinished (printInfo, true);
}

In OnWrite, we implement the code to draw printed content and write it to the output stream to be printed.

public override void OnWrite (PageRange[] pages, ParcelFileDescriptor destination,
                              CancellationSignal cancellationSignal, WriteResultCallback callback)
{
  PrintedPdfDocument.Page page = document.StartPage (0);
  page.Canvas.Scale (scale, scale);
  view.Draw (page.Canvas);
  document.FinishPage (page);
  WritePrintedPdfDoc (destination);
  document.Close ();
  document.Dispose ();
  callback.OnWriteFinished (pages);
}

Printing with our custom adapter is just like using the WebView‘s adapter. Simply pass an instance of the custom adapter, called GenericPrintAdapter in this case, to the PrintManager‘s Print method:

var printManager = (PrintManager)GetSystemService (Context.PrintService);
var content = FindViewById<LinearLayout> (Resource.Id.linearLayout1);
var printAdapter = new GenericPrintAdapter (this, content);
printManager.Print ("MyPrintJob", printAdapter, null);

When the user clicks print, the same system dialog is displayed. In addition to a local printer, you can select Google Cloud Print or print to a PDF file, resulting in the print shown below:

Android Printed to PDF

The printing support added to KitKat is a much welcome feature that is easy to get started with. You can download the code used in this post from my GitHub repo.

Discuss this post in the Xamarin forums.

TwitterFacebookGoogle+LinkedInEmail