Mono for Android

What's New In Android 4.1 (Jelly Bean)?

With the new version comes a flurry of changes, ranging from a significant performance overhaul under the hood, to plenty of new APIs made available to application developers.

Google recently unleashed the latest version of its mobile operating system under the name Jelly Bean, continuing its dessert-themed naming scheme. There's no question that this release is a major one for Android. With the new version comes a flurry of changes, ranging from a significant performance overhaul under the hood, to plenty of new APIs made available to application developers.

True to form, Xamarin released full support for Jelly Bean in Mono for Android without missing a beat. In this article we'll take a look at some of the highlights of what's new in Jelly Bean, along with examples of how to use some of the new APIs.

Project Butter
In the past, Android was notorious for feeling sluggish for users, especially when compared to a certain competing mobile operating system known for a smooth user experience. To address that, Jelly Bean includes the efforts of what Google dubbed "Project Butter", which had the goal of making all aspects of Android buttery smooth.

To do this, Google made a lot of improvements under the hood to ensure graphics are always able to run at high speeds. In Jelly Bean, the CPU and graphical pipelines are able to run in parallel, with the graphics being triple-buffered to run consistently at very high frame rates. The end result is the first version of Android to date that truly provides a smooth user experience.

In addition to the internal improvements, the SDK now also includes a tool called systrace. This tool gathers information directly from the underlying Linux kernel and surfaces them for developers. You can use systrace to help diagnose performance problems in your applications, and make sure that users of your app have the best experience possible.

Smart App Updates
In prior versions of Android, updating an application to a new version would essentially require downloading the entire app all over again. If an application was very large, this could take a long time depending on the device's connection, and could also potentially cost the user money if he or she is on a metered network.

In Jelly Bean, Google made the app update process smarter. Instead of shipping the entire app over the wire again on an update, Google Play will now only transfer the bits that have changed. The best part is it's handled automatically by Google Play and Android, so you don't need to do anything to take advantage of this. According to Google, a smart app update is only about one-third the size of a full update, on average.

Notifications
Those last two features are great, but let's start digging into some of the new APIs made available to developers. One of Android's signature features over the years has been its notifications system, which gets even better in this release. Starting in Jelly Bean, you can do a lot more with your application's notifications.

Notifications can now be much larger than before, up to 256dp in height. To go along with that, new templates can control how your notifications will look and behave:

  • BigTextStyle. This includes a multiline TextView object.
  • BigInboxStyle. This is used to display a list of messages, such as an email inbox.
  • BigPictureStyle. This features visual content, such as a large image.

You can also create your own notification styles using any View you want, so you can truly customize things according to your needs. Notifications can now include up to three actions as well, which are displayed below the content; they allow the user to interact with your application in different ways directly from the notification, before they even open your application up again.

Another great aspect of the notification system is that it's very easy to use. Consider the following example:

var sendEmailIntent = new Intent(this, typeof(SendEmailActivity));
	sendEmailIntent.PutExtra("ReplyTo", email.Id);

	var pendingSendEmailIntent = PendingIntent.GetActivity(this, ReplyMailRequestCode, 
    sendEmailIntent, PendingIntentFlags.UpdateCurrent);

	var builder = new Notification.Builder(this)
					.SetContentTitle("You have new mail")
					.SetSmallIcon(Android.Resource.Drawable.IcDialogEmail)
					.AddAction(Android.Resource.Drawable.IcMenuSend, "Reply", 
                                        pendingSendEmailIntent);
					
	var notification = new Notification.InboxStyle(builder)
						.AddLine("Twitter: You have new followers")
						.SetSummaryText("+2 more")
						.Build();

	var notificationService = (NotificationManager) GetSystemService(NotificationService);

	notificationService.Notify(MailNotificationId, notification);

The notification system provides a nice fluent API for building a notification, as seen here: we build up a notification that a mail app might show when new mail's arrived. It includes a sample email subject, and also provides the option to reply to the email right in the notification. Tapping on this action will launch an activity called SendEmailActivity, passing in the ID of the email so the activity would know which mail is being replied to.  The resulting notification should look something like Figure 1.


[Click on image for larger view.]
Figure 1. An example of a new Notification in Android 4.1 (Jelly Bean).
Activity Launch Animations
You can now customize the animations used when launching a new activity by using the new ActivityOptions helper class. There are various types of animations you can use:

  • MakeScaleUpAnimation(). Scales up the new activity window from a starting position and size that you specify. This is the animation the Android home screen uses when launching an application.
  • MakeThumbnailScaleUpAnimation(). Scales up the new activity window from a position and thumbnail image you specify. This is the animation Android's Recent Apps window uses when selecting an application.
  • MakeCustomAnimation(). Allows you to create your own animations for both the new activity being launched, as well as the current activity being stopped.

Let's say you wanted to start a new activity within your application, and instead of using the default animation you wanted it to expand outwards from the center of the screen. Using the new APIs, this becomes very easy to define:

var view = Window.DecorView.RootView;
	var options = ActivityOptions.MakeScaleUpAnimation(view, 
view.Width / 2, view.Height / 2, 0, 0);
	
	var intent = new Intent(this, typeof(MyActivity));
	StartActivity(intent, options.ToBundle());

What this code says is that, using the window's root view, define a scale-up animation starting at the center of the screen with an initial height and width of zero. With that defined, its ToBundle() method allows it to be passed into the call to StartActivity(), instructing Android to use the animation when launching the activity.

Android Beam
Android Beam allows applications to take advantage of a device's NFC (Near Field Communications) capabilities. While Beam existed prior to Jelly Bean, it did receive some improvements. One is that Beam now supports transferring large payloads, such as images or music, over Bluetooth.

The best part is that this switch is made automatically by Android as long as you're using the new API methods. This means you don't actually need to change your code at all to achieve higher transfer rates when sending large files through Beam.

Here's some example code that checks if NFC is available on the device, and starts the process of pushing a list of URIs across using Beam:

var nfcAdapter = NfcAdapter.GetDefaultAdapter(this);

	// if nfcAdapter is null, NFC is not available on this device
	if (nfcAdapter != null)
	{
		nfcAdapter.SetBeamPushUris(new Android.Net.Uri[] { /* ... */ }, this);
	}
Network Service Discovery
Android now supports multicast DNS-based service discovery, which allows you to look for and connect to different services over WiFi. These services can include other mobile devices, printers, cameras, media players and many other network devices.

To get started in discovering network services, first create a class that implements the NsdManager.IDiscoveryListener interface:

public class ServiceDiscoveryListener : Java.Lang.Object, NsdManager.IDiscoveryListener
	{
		private readonly Context _context;

		public ServiceDiscoveryListener (Context context)
		{
			_context = context;
		}

		public void OnServiceFound(NsdServiceInfo serviceInfo)
		{
			Toast
				.MakeText(_context, "Found Service: " + serviceInfo.ServiceName, 
                                ToastLength.Long)
				.Show();
		}	

		public void OnDiscoveryStarted(string serviceType) { }	
		public void OnDiscoveryStopped(string serviceType) { }
		public void OnServiceLost(NsdServiceInfo serviceInfo) { }
		public void OnStartDiscoveryFailed(string serviceType, NsdFailure errorCode) { }
		public void OnStopDiscoveryFailed(string serviceType, NsdFailure errorCode) { }
	}

As you can see, there are many different callback methods that give you access to different events, such as when discovery has started, stopped, failed or succeeded. In this example we just tap into when a service was found and display a simple toast message on the screen.

Now that the listener is defined, it's very simple to use in an activity to start discovering services. For example, this will start looking for network printers:

var discoveryService = (NsdManager)GetSystemService (NsdService); 
	var listener = new ServiceDiscoveryListener(this);
	discoveryService.DiscoverServices("_ipp._tcp", 
        NsdProtocol.DnsSd, listener);

Network Usage
There's a new property available on ConnectivityManager called IsActiveNetworkMetered that lets you to check if the device is currently connected to a metered network.

If your application's about to perform an operation that will use a lot of data, it could be expensive for a user on a metered network. This method warns the user and allows them to choose whether or not to perform the operation. Using this property requires that your application has the ACCESS_NETWORK_STATE permission.

var connectivityManager = (ConnectivityManager) GetSystemService (ConnectivityService);

	if (connectivityManager.IsActiveNetworkMetered) 
	{
		// user is on a metered network, make sure they really want to download this file
	}

This article has covered just a few Jelly Bean's new features. It's a major release for Android, and does a lot to allow the platform to thrive and truly compete in today's mobile arena.

About the Author

Greg Shackles, Microsoft MVP, Xamarin MVP, is a Principal Engineer at Olo. He hosts the Gone Mobile podcast, organizes the NYC Mobile .NET Developers Group, and wrote Mobile Development with C# (O'Reilly). Greg is obsessed with heavy metal, baseball, and craft beer (he’s an aspiring home brewer). Contact him at Twitter @gshackles.

comments powered by Disqus

Featured

Subscribe on YouTube