0% found this document useful (0 votes)
876 views1,410 pages

Document - Tutorial Xamarin

Uploaded by

Cepi Supriadi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
876 views1,410 pages

Document - Tutorial Xamarin

Uploaded by

Cepi Supriadi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1410

Contents

Xamarin.Android
Getting Started
Setup and Installation
Windows Installation
Android SDK Setup
Android Emulator Setup
Hardware Acceleration
Device Manager
Device Properties
Troubleshooting
Android Device Setup
Microsoft OpenJDK Preview
Hello, Android
Part 1: Quickstart
Part 2: Deep Dive
Hello, Android Multiscreen
Part 1: Quickstart
Part 2: Deep Dive
Xamarin for Java Developers
Application Fundamentals
Accessibility
Android API Levels
Android Resources
Android Resource Basics
Default Resources
Alternate Resources
Creating Resources for Varying Screens
Application Localization and String Resources
Using Android Assets
Fonts
Activity Lifecycle
Walkthrough - Saving the Activity state
Android Services
Creating a Service
Bound Services
Intent Services
Started Services
Foreground Services
Out of Process Services
Service Notifications
Broadcast Receivers
Localization
Permissions
Graphics and Animation
CPU Architectures
Handling Rotation
Audio
Notifications
Local Notifications
Local Notifications Walkthrough
Touch
Touch in Android
Walkthrough – Using Touch in Android
Multi-Touch Tracking
HttpClient Stack and SSL/TLS
Writing Responsive Apps
User Interface
Android Designer
Using the Android Designer
Designer Basics
Resource Qualifiers and Visualization Options
Alternative Layout Views
Material Design Features
Material Theme
User Profile
Splash Screen
Layouts
LinearLayout
RelativeLayout
TableLayout
RecyclerView
Parts and Functionality
RecyclerView Example
Extending the Example
ListView
ListView Parts and Functionality
Populating a ListView With Data
Customizing a ListView's Appearance
Using CursorAdapters
Using a ContentProvider
ListView and the Activity Lifecycle
GridView
GridLayout
Tabbed Layouts
Navigation Tabs with the ActionBar
Controls
ActionBar
Auto Complete
Buttons
Radio Button
Toggle Button
CheckBox
Custom Button
Calendar
CardView
EditText
Gallery
Navigation Bar
Pickers
Date Picker
Time Picker
Popup Menu
Spinner
Switch
TextureView
Toolbar
Replacing the Action Bar
Adding a Second Toolbar
Toolbar Compatibility
ViewPager
ViewPager with Views
ViewPager with Fragments
WebView
Platform Features
Android Beam
Android Manifest
File Access with Xamarin.Android
External Storage
Fingerprint Authentication
Getting Started
Scanning for Fingerprints
Creating the CryptoObject
Responding to Authentication Callbacks
Guidance & Summary
Enrolling a Fingerprint
Android Job Scheduler
Firebase Job Dispatcher
Fragments
Implementing Fragments
Fragments Walkthrough - Part 1
Fragments Walkthrough - Part 2
Creating a Fragment
Managing Fragments
Specialized Fragment Classes
Providing Backwards Compatibility
App Linking
Android 8 Oreo
Android 7 Nougat
Android 6 Marshmallow
Android 5 Lollipop
Android 4.4 KitKat
Android 4.1 Jelly Bean
Android 4.0 Ice Cream Sandwich
Content Providers
How it Works
Using the Contacts ContentProvider
Creating a Custom ContentProvider
Maps and Location
Location
Maps
Maps Application
Maps API
Obtaining a Google Maps API Key
Using Android.Speech
Java Integration
Android Callable Wrappers
Working With JNI
Porting Java to C#
Binding a Java Library
Binding a .JAR
Binding an .AAR
Binding an Eclipse Library Project
Customizing Bindings
Java Bindings Metadata
Naming Parameters with Javadoc
Troubleshooting Bindings
Using Native Libraries
Renderscript
Xamarin.Essentials
Getting Started
Accelerometer
App Information
Battery
Clipboard
Compass
Connectivity
Data Transfer
Device Display Information
Device Information
Email
File System Helpers
Flashlight
Geocoding
Geolocation
Gyroscope
Magnetometer
Main Thread
Open Browser
Orientation Sensor
Phone Dialer
Power
Preferences
Screen Lock
Secure Storage
SMS
Text-to-Speech
Version Tracking
Vibrate
Troubleshooting
Data and Cloud Services
Azure Active Directory
Getting Started
Step 1. Register
Step 2. Configure
Accessing the Graph API
Azure Mobile Apps
Data Access
Introduction
Configuration
Using SQLite.NET ORM
Using ADO.NET
Using Data in an App
Google Messaging
Firebase Cloud Messaging
FCM Notifications Walkthrough
Google Cloud Messaging
GCM Notifications Walkthrough
Web Services
Walkthrough - Working with WCF
Deployment and Testing
App Package Size
Building Apps
Build Process
Building ABI-Specific APKs
Command Line Emulator
Debugging
Debug on the Emulator
Debug on a Device
Android Debug Log
Debuggable Attribute
Environment
GDB
Custom Linker Settings
Multi-core devices
Performance
Profiling
Preparing for Release
ProGuard
Signing the APK
Manually Signing the APK
Finding Your Keystore Signature
Publishing an App
Publishing to Google Play
Google Licensing Services
APK Expansion Files
Manually Uploading the APK
Publishing to Amazon
Publishing Independently
Install as System App
Advanced Concepts and Internals
Architecture
Available Assemblies
API Design
Garbage Collection
Limitations
Troubleshooting
Troubleshooting Tips
Frequently Asked Questions
Which Android SDK packages should I install?
Where can I set my Android SDK locations?
How do I update the Java Development Kit (JDK) version?
Can I use Java Development Kit (JDK) version 9?
How can I manually install the Android Support libraries required by the
Xamarin.Android.Support packages?
How do I install Google Play Services in an emulator?
What USB drivers do I need to debug Android on Windows?
Is it possible to connect to Android emulators running on a Mac from a Windows
VM?
How do I automate an Android NUnit Test project?
How do I enable Intellisense in Android .axml files?
Why can't my Android release build connect to the Internet?
Smarter Xamarin Android Support v4 / v13 NuGet Packages
How do I resolve a PathTooLongException?
What version of Xamarin.Android added Lollipop support?
Android.Support.v7.AppCompat - No resource found that matches the given
name: attr 'android:actionModeShareDrawable'
Adjusting Java memory parameters for the Android designer
My Android Resource.designer.cs file will not update
Resolving Library Installation Errors
Changes to the Android SDK Tooling
Xamarin.Android Errors Reference
Wear
Getting Started
Introduction to Android Wear
Setup & Installation
Hello, Wear
User Interface
Controls
GridViewPager
Platform Features
Creating a Watch Face
Screen Sizes
Deployment & Testing
Debug on an Emulator
Debug on a Wear Device
Packaging
Release Notes
Samples
Getting Started Series
5/2/2018 • 2 minutes to read • Edit Online

Setup and Installation


Get Xamarin.Android set up and running in Visual Studio. This section covers downloading, installation, emulator
configuration, device provisioning, and more.

Hello, Android
In this two-part guide, you'll build your first Xamarin.Android application using Visual Studio, and you'll develop an
understanding of the fundamentals of Android application development with Xamarin. Along the way, this guide
introduces you to the tools, concepts, and steps required to build and deploy a Xamarin.Android application.

Hello, Android Multiscreen


In this two-part guide, you'll expand the application created in Hello, Android so that it implements a second
screen. Along the way, you will be introduced to the basic Android Application Building Blocks and dive deeper into
Android architecture as you develop a better understanding of Android application structure and functionality.

Xamarin for Java Developers


This article provides an introduction to C# programming for Java developers, focusing primarily on the C#
language features that Java developers will encounter while learning about Xamarin.Android app development.

Xamarin University Video


Building Your First Android App with Xamarin for Visual Studio, by Xamarin University
Setup and Installation
7/25/2018 • 2 minutes to read • Edit Online

The topics in this section explain how to install and configure Xamarin.Android to work with Visual Studio on
Windows and macOS, how to use the Android SDK Manager to download and install Android SDK tools and
components that are required for building and testing your app, how to configure the Android emulator for
debugging, and how to connect a physical Android device to your development computer for debugging and final
testing your app.

Windows Installation
This guide walks you through the installation steps and configuration details required to install Xamarin.Android
on Windows. By the end of this article, you will have a working Xamarin.Android installation integrated into Visual
Studio, and you'll be ready to start building your first Xamarin.Android application.

Mac Installation
This article walks you through the installation steps and configuration details required to install Xamarin.Android
on a Mac. By the end of this article, you will have a working Xamarin.Android installation integrated into Visual
Studio for Mac, and you'll be ready to start building your first Xamarin.Android application.

Android SDK Setup


Visual Studio includes an Android SDK Manager that replaces Google's standalone Android SDK Manager. This
article explains how to use the SDK Manager to download Android SDK tools, platforms, and other components
that you need for developing Xamarin.Android apps.

Android Emulator Setup


These articles explain how to setup the Android Emulator for testing and debugging Xamarin.Android
applications.

Android Device Setup


This article explains how to setup a physical Android device and connect it to a development computer so that the
device may be used to run and debug Xamarin.Android applications.

Microsoft OpenJDK Preview


This guide describes the steps for switching to the preview release of Microsoft's distribution of the OpenJDK.
Windows Installation
6/27/2018 • 5 minutes to read • Edit Online

This guide describes the steps for installing Xamarin.Android for Visual Studio on Windows, and it explains how to
configure Xamarin.Android for building your first Xamarin.Android application.

Overview
Because Xamarin is now included with all editions of Visual Studio at no extra cost and does not require a separate
license, you can use the Visual Studio installer to download and install Xamarin.Android tools. (The manual
installation and licensing steps that were required for earlier versions of Xamarin.Android are no longer necessary.)
In this guide, you will learn the following:
How to configure custom locations for the Java Development Kit, Android SDK, and Android NDK.
How to launch the Android SDK Manager to download and install additional Android SDK components.
How to prepare an Android device or emulator for debugging and testing.
How to create your first Xamarin.Android app project.
By the end of this guide, you will have a working Xamarin.Android installation integrated into Visual Studio, and
you will be ready to start building your first Xamarin.Android application.

Installation
For detailed information on installing Xamarin for use with Visual Studio on Windows, see the Windows Install
guide.

Configuration
Xamarin.Android uses the Java Development Kit (JDK) and the Android SDK to build apps. During installation, the
Visual Studio installer places these tools in their default locations and configures the development environment
with the appropriate path configuration. You can view and change these locations by clicking Tools > Options >
Xamarin > Android Settings:
For most users these default locations will work without further changes. However, you may wish to configure
Visual Studio with custom locations for these tools (for example, if you have installed the Java JDK, Android SDK,
or NDK in a different location). Click Change next to a path that you want to change, then navigate to the new
location.
Xamarin.Android uses JDK 8, which is required if you are developing for API level 24 or greater (JDK 8 also
supports API levels earlier than 24). You can continue to use JDK 7 if you are developing specifically for API level
23 or earlier.

IMPORTANT
Xamarin.Android does not support JDK 9.

Android SDK Manager


Android uses multiple Android API level settings to determine your app's compatibility across the various versions
of Android (for more information about Android API levels, see Understanding Android API Levels). Depending
on what Android API level(s) you want to target, you may need to download and install additional Android SDK
components. In addition, you may need to install optional tools and emulator images provided in the Android SDK.
To do this, use the Android SDK Manager. You can launch the Android SDK Manager by clicking Tools >
Android > Android SDK Manager:
By default, Visual Studio installs the Google Android SDK Manager:

You can use the Google Android SDK Manager to install versions of the Android SDK Tools package up to version
25.2.3. However, if you need to use a later version of the Android SDK Tools package, you must install the Xamarin
Android SDK Manager plugin for Visual Studio (available from the Visual Studio Marketplace). This is necessary
because Google's standalone SDK Manager was deprecated in version 25.2.3 of the Android SDK Tools package.
For more information about using the Xamarin Android SDK Manager, see Android SDK Setup.
Android Emulator
The Android Emulator can be helpful tool to develop and test a Xamarin.Android app. For example, a physical
device such as a tablet may not be readily available during development, or a developer may want to run some
integration tests on their computer before committing code.
Emulating an Android device on a computer involves the following components:
Google Android Emulator – This is an emulator based on QEMU that creates a virtualized device running on
the developer's workstation.
An Emulator Image – An emulator image is a template or a specification of the hardware and operating
system that is meant to be virtualized. For example, one emulator image would identify the hardware
requirements for a Nexus 5X running Android 7.0 with Google Play Services installed. Another emulator image
might specific a 10" table running Android 6.0.
Android Virtual Device (AVD ) – An Android Virtual Device is an emulated Android device created from an
emulator image. When running and testing Android apps, Xamarin.Android will start the Android Emulator,
starting a specific AVD, install the APK, and then run the app.
A significant improvement in performance when developing on x86 based computers can be achieved by using
special emulator images that are optimized for x86 architecture and one of two virtualization technologies:
1. Microsoft's Hyper-V – Available on computers running the Windows 10 April Update.
2. Intel's Hardware Accelerated Execution Manager (HAXM ) – Available on x86 computers running OS X, macOS,
or older version of Windows.
For more information about the Android Emulator, Hyper-V, and HAXM, please see Hardware Acceleration for
Emulator Performance guide.
NOTE
On older versions of Windows, HAXM is not compatible with Hyper-V. In this scenario it is necessary to either disable Hyper-
V or to use the slower emulator images that do not have the x86 optimizations.

Android Device
If you have a physical Android device to use for testing, this is a good time to set it up for development use. See
Set Up Device for Development to configure your Android device for development, then connect it to your
computer for running and debugging Xamarin.Android applications.

Create an Application
Now that you have installed Xamarin.Android, you can launch Visual Studio create a new project. Click File > New
> Project to begin creating your app:

In the New Project dialog, select Android under Templates and click Android App in the right pane. Enter a
name for your app (in the screenshot below, the app is called MyApp), then click OK:

That's it! Now you are ready to use Xamarin.Android to create Android applications!

Summary
In this article, you learned how to set up and install the Xamarin.Android platform on Windows, how to (optionally)
configure Visual Studio with custom Java JDK and Android SDK installation locations, how to launch the SDK
Manager to install additional Android SDK components, how to setup an Android device or emulator, and how to
start building your first application.
The next step is to have a look at the Hello, Android tutorials to learn how to create a working Xamarin.Android
app.

Related Links
Download Visual Studio
Installing Visual Studio Tools for Xamarin
System Requirements
Android SDK Setup
Android Emulator Setup
Set Up Device For Development
Run Apps on the Android Emulator
Setting up the Android SDK for Xamarin.Android
7/10/2018 • 8 minutes to read • Edit Online

Visual Studio includes an Android SDK Manager that you use to download Android SDK tools, platforms, and
other components that you need for developing Xamarin.Android apps.

Overview
This guide explains how to use the Xamarin Android SDK Manager in Visual Studio and Visual Studio for Mac.

NOTE
This guide applies only to Visual Studio 2017 and Visual Studio for Mac.

The Xamarin Android SDK Manager (installed as part of the Mobile development with .NET workload) helps
you download the latest Android components that you need for developing your Xamarin.Android app. It
replaces Google's standalone SDK Manager, which has been deprecated.
Visual Studio
Visual Studio for Mac

Requirements
To use the Xamarin Android SDK Manager, you will need the following:
Visual Studio 2017 (Community, Professional, or Enterprise edition). Visual Studio 2017 version 15.7 or
later is required.
Visual Studio Tools for Xamarin version 4.10.0 or later.
The Xamarin Android SDK Manager is not compatible with Visual Studio 2015. Users of Visual Studio 2015
should use the SDK Manager tools provided by Google in the Android SDK.
The Xamarin Android SDK Manager also requires the Java Development Kit (which is automatically installed
with Xamarin.Android). Xamarin.Android uses JDK 8, which is required if you are developing for API level 24 or
greater (JDK 8 also supports API levels earlier than 24). You can continue to use JDK 7 if you are developing
specifically for API level 23 or earlier.

IMPORTANT
Xamarin.Android does not support JDK 9.

SDK Manager
To start the SDK Manager in Visual Studio, click Tools > Android > Android SDK Manager:
The Xamarin Android SDK Manager opens in the Android SDKs and Tools screen. This screen has two tabs
– Platforms and Tools:

The Android SDKs and Tools screen is described in more detail in the following sections.
Android SDK Location
The Android SDK location is configured at the top of the Android SDKs and Tools screen, as seen in the
previous image. This location must be configured correctly before the Platforms and Tools tabs will function
properly. You may need to set the location of the Android SDK for one or more of the following reasons:
1. The Xamarin SDK Manager was unable to locate the Android SDK.
2. You have installed the Android SDK in a alternate (non-default) location.
To set the location of the Android SDK, click the … button to the far right of Android SDK Location. This opens
the Browse For Folder dialog to use for navigating to the location of the Android SDK. In the following
screenshot, the Android SDK under Program Files (x86)\Android is being selected:
When you click OK, the Xamarin Android SDK Manager will manage the Android SDK that is installed at the
selected location.
Tools Tab
The Tools tab displays a list of tools and extras. Use this tab to install the Android SDK tools, platform tools, and
build tools. Also, you can install the Android Emulator, the low -level debugger (LLDB ), the NDK, HAXM
acceleration, and Google Play libraries.
For example, to download the Google Android Emulator package, click the check mark next to Android
Emulator and click the Apply Changes button:

A dialog may be shown with the message, Some components can be updated. Do you want to update them
now? Click Yes. Next, a License acceptance dialog is shown:
Click Accept if you accept the Terms and Conditions. At the bottom of the window, a progress bar indicates
download and installation progress. After the installation completes, the Tools tab will show that the selected
tools and extras were installed.
Platforms Tab
The Platforms tab displays a list of platform SDK versions along with other resources (like system images) for
each platform.
This screen lists the Android version (such as Android 7.0), the code name (Nougat), the API level (such as 24),
and the status (Installed if the platform is installed). You use the Platforms tab to install components for the
Android API level that you want to target (for more information about Android versions and API levels, see
Understanding Android API Levels).
If all components of a platform are installed, a checkmark appears next to the platform name. If not all
components of a platform are installed, the box for that platform is filled.
You can expand a platform to see its components (and which components are installed) by clicking the + box to
the left of the platform. Click - to unexpand the component listing for a platform.
To add another platform to the SDK, click the box next to the platform until the checkmark appears to install all of
its components, then click Apply Changes:
To install only the SDK click the box next to the platform once. You can then select any individual components
that you need:

Notice that the number of components to install appears next to the Apply Changes button. In the above
example, six components are ready to install. After you click the Apply Changes button, you will see the License
Acceptance screen:
Click Accept if you accept the Terms and Conditions. You may see this dialog more than one time when there are
multiple components to install. At the bottom of the window, a progress bar will indicate download and
installation progress. When the download and installation process completes (this can take many minutes,
depending on how many components need to be downloaded), the added components are marked with a
checkmark and listed as Installed.

Summary
This guide explained how to install and use the Xamarin Android SDK Manager tool in Visual Studio and Visual
Studio for Mac.

Related Links
Changes to the Android SDK Tooling
Understanding Android API levels
sdkmanager
avdmanager
Android Emulator Setup
6/25/2018 • 2 minutes to read • Edit Online

This guide explain how to prepare the Android Emulator for testing your app.

Overview
The Android Emulator can be run in a variety of configurations to simulate different devices. Each configuration is
called a virtual device. When you deploy and test your app on the emulator, you select a pre-configured or custom
virtual device that simulates a physical Android device such as a Nexus or Pixel phone.
The sections listed below describe how to accelerate the Android emulator for maximum performance, how to use
the Android Device Manager to create and customize virtual devices, and how to customize the profile properties
of a virtual device. In addition, a troubleshooting section explains common emulator problems and workarounds.

Sections
Hardware Acceleration for Emulator Performance
How to prepare your computer for maximum Android Emulator performance. Because the Android Emulator can
be prohibitively slow without hardware acceleration, we recommend that you enable hardware acceleration on
your computer before you use the emulator.
Managing Virtual Devices with the Android Device Manager
How to use the Android Device Manager to create and customize virtual devices.
Editing Android Virtual Device Properties
How to use the Android Device Manager to edit the profile properties of a virtual device.
Android Emulator Troubleshooting
In this article, the most common warning messages and issues that occur while running the Android Emulator are
described, along with workarounds and tips.
After you have configured the Android Emulator, see Debugging on the Android Emulator for information about
how to launch the emulator and use it for testing and debugging your app.

NOTE
As of Android SDK Tools version 26.0.1 and later, Google has removed support for existing AVD/SDK managers in favor of
their new CLI (Command Line Interface) tools. Because of this deprecation change, Xamarin SDK/Device Managers are now
used instead of Google SDK/Device Managers for Android Tools 26.0.1 and later. For more information about the Xamarin
SDK Manager, see Setting up the Android SDK for Xamarin.Android.
Hardware Acceleration for Emulator Performance
6/27/2018 • 6 minutes to read • Edit Online

This article explains how to use your computer's hardware acceleration features to maximize Android Emulator
performance.

Overview
Visual Studio makes it easier for developers to test and debug their Xamarin.Android applications by using the
Android Emulator in situations where an Android device is unavailable or impractical. However, the Android
emulator runs too slowly if hardware acceleration is not available on the computer that runs it. You can drastically
improve the performance of the Android emulator by using special virtual device images that target x86 hardware
in conjunction with one of two virtualization technologies:
1. Microsoft's Hyper-V and the Hypervisor Platform. Hyper-V is a virtualization feature of Windows that
makes it possible to run virtualized computer systems on a physical host computer. This is the
recommended virtualization technology to use for accelerating the Android Emulator. To learn more about
Hyper-V, see Hyper-V on Windows 10.
2. Intel's Hardware Accelerated Execution Manager (HAXM ). HAXM is a virtualization engine for
computers running Intel CPUs. This is the recommended virtualization engine for computers that are
unable to run Hyper-V.
The Android Emulator will automatically make use of hardware acceleration if the following criteria are met:
Hardware acceleration is available and enabled on the development computer.
The emulator is running an emulator image specifically created for an x86-based virtual device.
For information about launching and debugging with the Android Emulator, see Debugging on the Android
Emulator.

Hyper-V
Visual Studio
Visual Studio for Mac

NOTE
Hyper-V support is currently in Preview.

Developers who are using Windows 10 (April 2018 Update or later) are strongly encouraged to use Microsoft's
Hyper-V to accelerate the Android Emulator. To use the Android Emulator with Hyper-V:
1. Update to Windows 10 April 2018 Update (build 1803) or later. To verify which version of Windows is
running, click in the Cortana search bar and type About. Select About your PC in the search results. Scroll
down in the About dialog to the Windows specifications section. The Version should be at least 1803:
2. Enable the Windows Hypervisor Platform. In the Cortana Search bar, type Turn Windows features
on or off. Scroll down in the Windows Features dialog and ensure that Windows Hypervisor Platform
is enabled:

Enabling Windows Hypervisor Platform automatically enables Hyper-V. It is a good idea to restart
Windows after making this change.
3. Install Visual Studio 15.8 Preview 1 or later. This version of Visual Studio provides IDE support for
running the Android Emulator with Hyper-V.
4. Install the Android Emulator package 27.2.7 or later. To install this package, navigate to Tools >
Android > Android SDK Manager in Visual Studio. Select the Tools tab and ensure that the Android
Emulator version is at least 27.2.7. Also ensure that the Android SDK Tools version is 26.1.1 or later:
5. If the emulator version is at least 27.2.7 but less than 27.3.1, the following workaround is required to use
Hyper-V:
a. In the C:\Users\username\.android folder, create a file called advancedFeatures.ini (if it doesn't
already exist).
b. Add the following line to advancedFeatures.ini:

WindowsHypervisorPlatform = on

Known Issues
If you are unable to update to emulator version 27.2.7 or later after updating to a Visual Studio preview,
you may have to directly install the preview installer to enable newer emulator versions.
Performance may be reduced when using certain Intel and AMD -based processors.
Android application may take an abnormal amount of time to load on deployment.
MMIO access error may intermittently prevent a boot of the Android emulator. Restarting the emulator
should resolve this.

HAXM
HAXM is a hardware-assisted virtualization engine (hypervisor) that uses Intel Virtualization Technology (VT) to
speed up Android app emulation on a host machine. Using HAXM in conjunction with Android x86 emulator
images provided by Intel allows for faster Android emulation on VT-enabled systems.
If you are developing on a machine with an Intel CPU that has VT capabilities, you can take advantage of HAXM
to greatly speed up the Android Emulator (if you're not sure whether your CPU supports VT, see Does My
Processor Supports Intel Virtualization Technology?).

NOTE
You can't run a VM-accelerated emulator inside another VM, such as a VM hosted by VirtualBox, VMWare, or Docker. You
must run the Android emulator directly on your system hardware.

Before using the Android Emulator for the first time, it's a good idea to verify that HAXM is installed and available
for the Android Emulator to use.
Verifying HAXM Installation
You can check to see if HAXM is available by viewing the Starting Android Emulator window while the
emulator starts. To start the Android Emulator, do the following:
Visual Studio
Visual Studio for Mac
1. Launch the Android Device Manager by clicking Tools > Android > Android Device Manager:

2. If you see a Performance Warning dialog similar to the following, then HAXM is not yet installed or
configured properly on your computer:

If a Performance Warning dialog like this is shown, see Performance Warnings to identify the cause and
resolve the underlying problem.
3. Select an x86 image (for example, VisualStudio_android-23_x86_phone) and click Start:

4. Watch for the Starting Android Emulator dialog window while the emulator starts up. If HAXM is
installed, you will see the message, HAX is working and emulator runs in fast virt mode as shown in
this screenshot:

If you do not see this message, then HAXM is probably not installed. For example, here is a screenshot of a
message you may see if HAXM is not available:

If HAXM is not available on your computer, use the steps in the next section to install HAXM.
Installing HAXM
If the emulator does not start, HAXM may have to be installed manually. HAXM install packages for both
Windows and macOS are available from the Intel Hardware Accelerated Execution Manager page. Use the
following steps to download and install HAXM manually:
Visual Studio
Visual Studio for Mac
1. From the Intel website, download the latest HAXM virtualization engine installer for Windows. The
advantage of downloading the HAXM installer directly from the Intel website is that you can be assured of
using the latest version.
Alternately, you can use the SDK Manager to download the HAXM installer (In the SDK Manager, click
Tools > Extras > Intel x86 Emulator Accelerator (HAXM installer)). The Android SDK normally
downloads the HAXM installer to the following location:
C:\Program Files (x86)\Android\android-
sdk\extras\intel\Hardware_Accelerated_Execution_Manager
Note that the SDK Manager does not install HAXM, it merely downloads the HAXM installer to the above
location; you still have to launch it manually.
2. Run intelhaxm -android.exe to start the HAXM installer. Accept the default values in the installer dialogs:
Hardware Acceleration and AMD CPUs
Because the Android emulator currently supports AMD hardware acceleration only on Linux, hardware
acceleration is not available for AMD -based computers running Windows.

Related Links
Run Apps on the Android Emulator
Managing Virtual Devices with the Android Device
Manager
6/25/2018 • 12 minutes to read • Edit Online

This article explains how to use the Android Device Manager to create and configure Android Virtual Devices
(AVDs) that emulate physical Android devices. You can use these virtual devices to run and test your app without
having to rely on a physical device.

Overview
After you have verified that hardware acceleration is enabled (as described in Hardware Acceleration for Emulator
Performance), the next step is to use the Android Device Manager (also referred to as the Xamarin Android
Device Manager) to create virtual devices that you can use to test and debug your app.
Visual Studio
Visual Studio for Mac
This article explains how to use the Android Device Manager to create, duplicate, customize, and launch Android
virtual devices.

You use the Android Device Manager to create and configure Android Virtual Devices (AVDs) that run in the
Android Emulator. Each AVD is an emulator configuration that simulates a physical Android device. This makes it
possible to run and test your app in a variety of configurations that simulate different physical Android devices.

Requirements
To use the Android Device Manager, you will need the following:
Visual Studio 2017 version 15.7 or later is required. Visual Studio Community, Professional, and Enterprise
editions are supported.
Visual Studio Tools for Xamarin version 4.9 or later.
The Android SDK must be installed (see Setting up the Android SDK for Xamarin.Android), and SDK tools
version 26.1.1 or later must be installed as explained in the next section. Be sure to install the Android SDK
at the following location (if it is not already installed): C:\Program Files (x86)\Android\android-sdk.

Launching the Device Manager


Launch the Android Device Manager from the Tools menu by clicking Tools > Android > Android Device
Manager:

If you see the following error dialog on launch, see Android Emulator Troubleshooting for workaround
instructions:

Before you can use the Android Device Manager, you must install Android SDK tools version 26.1.1 or later. If
Android SDK tools 26.1.1 or later is not installed, you may see this error dialog on launch:

If you see this error dialog, click Open SDK Manager to open the Android SDK Manager. In the Android SDK
Manager, click the Tools tab and install the following:
Android SDK Tools 26.1.1 or later
Android SDK Platform -Tools 27.0.1 or later
Android SDK Build-Tools 27.0.3 or later
These packages should be shown with Installed status as seen in the following screenshot:
After these packages are installed, you can close the SDK Manager and re-launch the Android Device Manager.

Main Screen
When you first launch the Android Device Manager, it presents a screen that displays all currently-configured
virtual devices. For each device, the Name, Operating System (Android API Level), CPU, Memory size, and
screen resolution are displayed:

When you click a device in the list, the Start button appears on the right. You can click the Start button to launch
the emulator with this virtual device:
After the emulator starts with the selected virtual device, the Start button changes to a Stop button that you can
use to halt the emulator:

New Device
To create a new device, click the New button (located in the upper right-hand area of the screen):

Clicking New launches the New Device screen:


To configure a new device in the New Device screen, use the following steps:
1. Select a physical device to emulate by clicking the Device pull-down menu:

2. Select a system image to use with this virtual device by clicking the System image pull-down menu. This
menu lists the installed system device manager images under Installed. The Download section lists
system device manager images that are currently unavailable on your development computer but can be
automatically installed:
3. Give the device a new name. In the following example, the new device is named Nexus 5 API 25:

4. Edit any properties that you need to modify. To make changes to properties, see Editing Android Virtual
Device Properties.
5. Add any additional properties that you need to explicitly set. The New Device screen lists only the most
commonly-modified properties, but you can click the Add Property pull-down menu (in the bottom left-
hand corner) to add additional properties. In the following example, the hw.lcd.backlight property is being
added:

6. Click the Create button (lower right-hand corner) to create the new device:
7. You might get a License Acceptance screen. Click Accept if you agree to the license terms:

8. The Android Device Manager adds the new device to the list of installed virtual devices while displaying a
Creating progress indicator during device creation:

9. When the creation process is complete, the new device is shown in the list of installed virtual devices with a
Start button, ready to launch:

Edit Device
To edit an existing virtual device, select the device and click the Edit button (located in the upper right-hand corner
of the screen):
Clicking Edit launches the Device Editor for the selected virtual device:

The Device Editor screen lists the properties of the virtual device in the first column, with the corresponding
values of each property in the second column. When you select a property, a detailed description of that property
is displayed on the right.
For example, in the following screenshot the hw.lcd.density property is being changed from 420 to 240:
After you have made the necessary configuration changes, click the Save button. For more information about
changing virtual device properties, see Editing Android Virtual Device Properties.
Additional Options
Additional options for working with devices are available from the … menu in the upper right-hand corner:

The additional options menu contains the following items:


Duplicate and Edit – Duplicates the currently-selected device and opens it in the New Device screen
with a different unique name. For example, selecting VisualStudio_android-23_x86_phone and clicking
Duplicate and Edit appends a counter to the name:
Reveal in Explorer – Opens a Windows Explorer window in the folder that holds the files for the virtual
device. For example, selecting Nexus 5X API 25 and clicking Reveal in Explorer opens a window like the
following:

Factory Reset – Resets the selected device to its default settings, erasing any user changes made to the
internal state of the device while it was running (this also erases the current Quick Boot snapshot, if any).
This change does not alter modifications that you make to the virtual device during creation and editing. A
dialog box will appear with the reminder that this reset cannot be undone. Click Wipe user data to confirm
the reset.
Delete – Permanently deletes the selected virtual device. A dialog box will appear with the reminder that
deleting a device cannot be undone. Click Delete if you are certain that you want to delete the device.

Troubleshooting
The following sections explain how to diagnose and work around problems that may occur when using the
Android Device Manager to configure virtual devices.
Visual Studio
Visual Studio for Mac
Android SDK in Non-Standard Location
Typically, the Android SDK is installed at the following location:
C:\Program Files (x86)\Android\android-sdk
If the SDK is not installed at this location, you may get this error when you launch the Android Device Manager:
To work around this problem, do the following:
1. From the Windows desktop, navigate to
C:\Users\username\AppData\Roaming\XamarinDeviceManager:

2. Double-click to open one of the log files and locate the Config file path. For example:

3. Navigate to this location and double-click user.config to open it.


4. In user.config, locate the <UserSettings> element and add an AndroidSdkPath attribute to it. Set this
attribute to the path where the Android SDK is installed on your computer and save the file. For example,
<UserSettings> would look like the following if the Android SDK was installed at
C:\Programs\Android\SDK:

<UserSettings SdkLibLastWriteTimeUtcTicks="636409365200000000" AndroidSdkPath="C:\Programs\Android\SDK"


/>

After making this change to user.config, you should be able to launch the Android Device Manager.
Snapshot disables WiFi on Android Oreo
If you have an AVD configured for Android Oreo with simulated Wi-Fi access, restarting the AVD after a snapshot
may cause Wi-Fi access to become disabled.
To work around this problem,
1. Select the AVD in the Android Device Manager.
2. From the additional options menu, click Reveal in Explorer.
3. Navigate to snapshots > default_boot.
4. Delete the snapshot.pb file:

5. Restart the AVD.


After these changes are made, the AVD will restart in a state that allows Wi-Fi to work again.
Generating a Bug Report
Visual Studio
Visual Studio for Mac
If you find a problem with the Android Device Manager that cannot be resolved using the above troubleshooting
tips, please file a bug report by right-clicking the title bar and selecting Generate Bug Report:

Summary
This guide introduced the Android Device Manager available in Visual Studio for Mac and Visual Studio Tools for
Xamarin. It explained essential features such as starting and stopping the Android emulator, selecting an Android
virtual device (AVD ) to run, creating new virtual devices, and how to edit a virtual device. It explained how to edit
profile hardware properties for further customization, and it provided troubleshooting tips for common problems.

Related Links
Changes to the Android SDK Tooling
Debugging on the Android Emulator
SDK Tools Release Notes (Google)
avdmanager
sdkmanager
Editing Android Virtual Device Properties
6/4/2018 • 15 minutes to read • Edit Online

This article explains how to use the Android Device Manager to edit the profile properties of an Android virtual
device.
Visual Studio
Visual Studio for Mac
The Android Device Manager supports the editing of individual Android virtual device profile properties. The
New Device and Device Edit screens list the properties of the virtual device in the first column, with the
corresponding values of each property in the second column (as seen in this example):

When you select a property, a detailed description of that property is displayed on the right. You can modify
hardware profile properties and AVD properties. Hardware profile properties (such as hw.ramSize and
hw.accelerometer ) describe the physical characteristics of the emulated device. These characteristics include
screen size, the amount of available RAM, whether or not an accelerometer is present. AVD properties specify the
operation of the AVD when it runs. For example, AVD properties can be configured to specify how the AVD uses
your development computer's graphics card for rendering.
You can change properties by using the following guidelines:
To change a boolean property, click the check mark to the right of the boolean property:

To change an enum (enumerated) property, click the down-arrow to the right of the property and choose a
new value.
To change a string or integer property, double-click the current string or integer setting in the value column
and enter a new value.

The following table provides a detailed explanation of the properties listed in the New Device and Device
Editor screens:

PROPERTY DESCRIPTION OPTIONS

abi.type ABI type – Specifies the ABI x86, x86_64, armeabi-v7a, arm64-v8a
(application binary interface) type of
the emulated device. The x86 option is
for the instruction set commonly
referred to as "x86" or "IA-32." The
x86_64 option is for the 64-bit x86
instruction set. The armeabi-v7a
option is for the ARM instruction set
with v7-a ARM extensions. The arm64-
v8a option is for the ARM instruction
set that supports AArch64.

disk.cachePartition Cache partition – Determines whether yes, no


the emulated device will use a /cache
partition on the device. The /cache
partition (which is initially empty) is the
location where Android stores
frequently accessed data and app
components. If set to no, the emulator
will not use a /cache partition and the
other disk.cache settings will be
ignored.

disk.cachePartition.path Cache partition path – Specifies a


cache partition image file on your
development computer. The emulator
will use this file for the /cache
partition. Enter an absolute path or a
path relative to the emulator's data
directory. If not set, the emulator
creates an empty temporary file called
cache.img on your development
computer. If the file does not exist, it is
created as an empty file. This option is
ignored if disk.cachePartition is set
to no.
PROPERTY DESCRIPTION OPTIONS

disk.cachePartition.size Cache partition size – The size of the


cache partition file (in megabytes).
Normally you do not need to set this
option unless the app will be
downloading very large files that are
larger than the default cache size of 66
megabytes. This option is ignored if
disk.cachePartition is set to no.

disk.dataPartition.initPath Initial path to the data partition –


Specifies the initial contents of the data
partition. After wiping user data, the
emulator copies the contents of the
specified file to user data (by default,
userdata-qemu.img) instead of using
userdata.img as the initial version.

disk.dataPartition.path Path to the data partition – Specifies


the user data partition file. To configure
a persistent user data file, enter a
filename and a path on your
development computer. If the file
doesn't exist, the emulator creates an
image from the default file
userdata.img, stores it in the filename
specified by
disk.dataPartition.path , and
persists user data to it when the
emulator shuts down. If you don't
specify a path, the default file is named
userdata-qemu.img. The special value
causes the emulator to create and use
a temporary file. If
disk.dataPartition.initPath is set,
its content will be copied to the
disk.dataPartition.path file at boot-time.
Note that this option cannot be left
blank.

disk.dataPartition.size Data partition size – Specifies the size


of the user data partition in megabytes.

disk.ramdisk.path Ramdisk path – Path to the boot


partition (ramdisk) image. The ramdisk
image is a subset of the system image
that is loaded by the kernel before the
system image is mounted. The ramdisk
image typically contains boot-time
binaries and initialization scripts. If this
option is not specified, the default is
ramdisk.img in the emulator system
directory.
PROPERTY DESCRIPTION OPTIONS

disk.snapStorage.path Snapshot storage path – Path to the


snapshot storage file where all
snapshots are stored. All snapshots
made during execution will be saved to
this file. Only snapshots that are saved
to this file can be restored during the
emulator run. If this option is not
specified, the default is snapshots.img
in the emulator data directory.

disk.systemPartition.initPath System partition init path – Path to


the read-only copy of the system
image file; specifically, the partition
containing the system libraries and
data corresponding to the API level and
any variant. If this path is not specified,
the default is system.img in the
emulator system directory.

disk.systemPartition.path System partition path – Path to the


read/write system partition image. If
this path is not set, a temporary file will
be created and initialized from the
contents of the file specified by
disk.systemPartition.initPath .

disk.systemPartition.size System partition size – The ideal size


of the system partition (in megabytes).
The size is ignored if the actual system
partition image is larger than this
setting; otherwise, it specifies the
maximum size that the system partition
file can grow to.

hw.accelerometer Accelerometer – Determines whether yes, no


the emulated device contains an
accelerometer sensor. The
accelerometer helps the device
determine orientation (used for auto-
rotation). The accelerometer reports
the acceleration of the device along
three sensor axes.

hw.audioInput Audio recording support – yes, no


Determines whether the emulated
device can record audio.

hw.audioOutput Audio playback support – yes, no


Determines whether the emulated
device can play audio.

hw.battery Battery support – Determines yes, no


whether the emulated device can run
on a battery.

hw.camera Camera support – Determines yes, no


whether the emulated device has a
camera.
PROPERTY DESCRIPTION OPTIONS

hw.camera.back Back-facing camera – Configures the emulated, none, webcam0


back-facing camera (the lens faces away
from the user). If you are using a
webcam on your development
computer to simulate the back-facing
camera on the emulated device, this
value must be set to webcamn, where n
selects the webcam (if you have only
one webcam, choose webcam0). If set
to emulated, the emulator simulates
the camera in software. To disable the
back-facing camera, set this value to
none. If you enable the back-facing
camera, be sure to also enable
hw.camera .

hw.camera.front Front-facing camera – Configures the emulated, none, webcam0


front-facing camera (the lens faces
towards the user). If you are using a
webcam on your development
computer to simulate the front-facing
camera on the emulated device, this
value must be set to webcamn, where n
selects the webcam (if you have only
one webcam, choose webcam0). If set
to emulated, the emulator simulates a
camera in software. To disable the
front-facing camera, set this value to
none. If you enable the front-facing
camera, be sure to also enable
hw.camera .

hw.camera.maxHorizontalPixels Maximum horizontal camera pixels


– Configures the maximum horizontal
resolution of the emulated device's
camera (in pixels).

hw.camera.maxVerticalPixels Maximum vertical camera pixels –


Configures the maximum vertical
resolution of the emulated device's
camera (in pixels).

hw.cpu.arch CPU architecture – The CPU x86, x86_64, arm, arm64


architecture to be emulated by the
virtual device. If you are using Intel
HAXM for hardware acceleration, select
x86 for a 32-bit CPU. Select x86_64 for
a 64-bit HAXM-accelerated device. (Be
sure to install the corresponding Intel
x86 system image in the SDK Manager:
for example, Intel x86 Atom or Intel x86
Atom_64.) To simulate an ARM CPU,
select arm for 32-bit or select arm64
for a 64-bit ARM CPU. Keep in mind
that ARM-based virtual devices will run
much slower than those that are x86-
based because hardware acceleration is
not available for ARM.
PROPERTY DESCRIPTION OPTIONS

hw.cpu.model CPU model – This value is normally left


unset (it will be set to a value that is
derived from hw.cpu.arch if it is not
explicitly set). However, it can be set to
an emulator-specific string for
experimental use.

hw.dPad DPad keys – Determines whether the yes, no


emulated device supports directional
pad (DPad) keys. A DPad typically has
four keys to indicate directional control.

hw.gps GPS support – Determines whether yes, no


the emulated device has a GPS (Global
Positioning System) receiver.

hw.gpu.enabled GPU emulation – Determines whether yes, no


the emulated device supports GPU
emulation. When enabled, GPU
emulation uses Open GL for Embedded
Systems (OpenGL ES) for rendering
both 2D and 3D graphics on the
screen, and the associated GPU
Emulation Mode setting determines
how the GPU emulation is
implemented.

hw.gpu.mode GPU emulation mode – Determines auto, host, mesa, angle, swiftshader, off
how GPU emulation is implemented by
the emulator. If you select auto, the
emulator will choose hardware and
software acceleration based on your
development computer setup. If you
select host, the emulator will use your
development computer's graphics
processor to perform GPU emulation
for faster rendering. If your GPU is not
compatible with the emulator and you
are on Windows, you can try angle
instead of host. The angle mode uses
DirectX to provide performance similar
to host. If you select mesa, the
emulator will use the Mesa 3D software
library to render graphics. Select mesa
if you have problems rendering via
your development computer's graphics
processor. The swiftshader mode can be
used to render graphics in software
with slightly less performance than
using your computer's GPU. The off
option (disable graphics hardware
emulation) is a deprecated option that
can cause improper rendering for some
items and is therefore not
recommended.
PROPERTY DESCRIPTION OPTIONS

hw.gsmModem GSM modem support – Determines yes, no


whether the emulated device includes a
modem that supports the GSM (Global
System for Mobile Communications)
telephony radio system.

hw.initialOrientation Initial screen orientation – Configures portrait, landscape


the initial orientation of the screen on
the emulated device (portrait or
landscape mode). In portrait mode, the
screen is taller than it is wide. In
landscape mode, the screen is wider
than it is tall. When running the
emulated device, you can change the
orientation if both portrait and
landscape are supported in the device
profile.

hw.keyboard Keyboard support – Determines yes, no


whether the emulated device supports
a QWERTY keyboard.

hw.keyboard.charmap Keyboard charmap name – The


name of the hardware charmap for this
device. NOTE: This should always be the
default qwerty2 unless you have
modified the system image accordingly.
This name is sent to the kernel at boot
time. Using an incorrect name will
result in an unusable virtual device.

hw.keyboard.lid Keyboard lid support – If keyboard yes, no


support is enabled, this setting
determines whether the QWERTY
keyboard can be closed/hidden or
opened/visible. This setting will be
ignored if hw.keyboard is set to false.
NOTE: the default value is false if the
emulated device targets API level 12 or
higher.

hw.lcd.backlight LCD backlight – Determines whether yes, no


an LCD backlight is simulated by the
emulated device.

hw.lcd.density LCD density – The density of the 120, 160, 240, 213, 320
emulated LCD display, measured in
density-independent pixels, or dp (dp is
a virtual pixel unit). When the setting is
160 dp, each dp corresponds to one
physical pixel. At runtime, Android uses
this value to select and scale the
appropriate resources/assets for correct
display rendering.
PROPERTY DESCRIPTION OPTIONS

hw.lcd.depth LCD color depth – The color bit-depth 16, 32


of the emulated framebuffer that holds
the bitmap for driving the LCD display.
This value can be 16 bits (65,536
possible colors) or 32 bits (16,777,216
colors plus transparency). The 32-bit
setting can make the emulator run
slightly slower but with better color
accuracy.

hw.lcd.height LCD pixel height – The number of


pixels that make up the vertical
dimension of the emulated LCD display.

hw.lcd.width LCD pixel width – The number of


pixels that make up the horizontal
dimension of the emulated LCD display.

hw.mainKeys Hardware Back/Home keys – yes, no


Determines whether the emulated
device supports hardware Back and
Home navigation buttons. You can set
this value to yes if the buttons are
implemented only in software. If
hw.mainKeys is set to yes, the
emulator will not display navigation
buttons on the screen, but you can use
the emulator side panel to "press"
these buttons.

hw.ramSize Device RAM Size – The amount of


physical RAM on the emulated device,
in megabytes. The default value will be
computed from the screen size or the
skin version. Increasing the size can
provide faster emulator operation, but
at the expense of demanding more
resources from your development
computer.

hw.screen Touch screen type – Defines the type touch, multi-touch, no-touch
of screen on the emulated device. A
multi-touch screen can track two or
more fingers on the touch interface. A
touch screen can detect only single-
finger touch events. A no-touch screen
does not detect touch events.

hw.sdCard SDCard support – Determines yes, no


whether the emulated device supports
insertion and removal of virtual SD
(Secure Digital) cards. The emulator
uses mountable disk images stored on
your development computer to
simulate the partitions of actual SD
card devices (see hw.sdCard.path).
PROPERTY DESCRIPTION OPTIONS

sdcard.size SDCard size – Specifies the size of the


virtual SD card file at the location
specified by hw.sdCard.path .
available on the device (in bytes). If the
size is a simple integer, it specifies the
size in bytes. You can also specify the
size in kilobytes, megabytes, and
gigabytes by appending K, M, or G to
the size. The minimum size is 9M and
the maximum size is 1023G.

hw.sdCard.path SDCard Image Path – Specifies the


filename and path to an SD card
partition image file on your
development computer. For example,
this path could be set to
C:\sd\sdcard.img on Windows.

hw.sensors.magnetic_field Magnetic Field Sensor – Determines yes, no


whether the emulated device supports
a magnetic field sensor. The magnetic
field sensor (also known as
magnetometer) reports the ambient
geomagnetic field as measured along
three sensor axes. Enable this setting
for apps that need access to a compass
reading. For example, a navigation app
might use this sensor to detect which
direction the user faces.

hw.sensors.orientation Orientation Sensor – Determines yes, no


whether the emulated device provides
orientation sensor values. The
orientation sensor measures degrees of
rotation that a device makes around all
three physical axes (x, y, z). Note that
the orientation sensor was deprecated
as of Android 2.2 (API level 8).

hw.sensors.proximity Proximity Sensor – Determines yes, no


whether the emulated device supports
a proximity sensor. This sensor
measures the proximity of an object
relative to the view screen of a device.
This sensor is typically used to
determine whether a handset is being
held up to a person's ear.

hw.sensors.temperature Temperature Sensor – Determines yes, no


whether the emulated device supports
a temperature sensor. This sensor
measures the temperature of the
device in degrees Celsius (°C).
PROPERTY DESCRIPTION OPTIONS

hw.touchScreen Touch-screen support – Determines yes, no


whether the emulated device supports
a touch screen. The touch screen is
used for direct manipulation of objects
on the screen.

hw.trackBall Trackball support – Determines yes, no


whether the emulated device supports
a trackball.

hw.useext4 EXT4 file system support – no


Determines whether the emulated
device uses the Linux EXT4 file system
for partitions. Because the file system
type is now auto-detected, this option
is deprecated and ignored.

kernel.newDeviceNaming Kernel new device naming – Used to autodetect, yes, no


specify whether the kernel requires a
new device naming scheme. This is
typically used with Linux 3.10 kernels
and later. If set to autodetect, the
emulator will automatically detect
whether the kernel requires a new
device naming scheme.

kernel.parameters Kernel parameters – Specifies the


string of Linux kernel boot parameters.
By default, this setting is left blank.

kernel.path Kernel path – Specifies the path to the


Linux kernel. If this path is not specified,
the emulator looks in the emulator
system directory for kernel-ranchu.

kernel.supportsYaffs2 YAFFS2 partition support – autodetect, yes, no


Determines whether the kernel
supports YAFFS2 (Yet Another Flash File
System 2) partitions. Typically, this
applies only to kernels before Linux
3.10. If set to autodetect the emulator
will automatically detect whether the
kernel can mount YAFFS2 file systems.

skin.name Skin name – The name for an Android


emulator skin. A skin is a collection of
files that defines the visual and control
elements of an emulator display; it
describes what the window of the AVD
will look like on your development
computer. A skin describes screen size,
buttons, and the overall design, but it
does not affect the operation of your
app.
PROPERTY DESCRIPTION OPTIONS

skin.path Skin path – Path to the directory that


contains the emulator skin files
specified in skin.name This directory
contains hardware.ini layout files, and
image files for the display elements of
the skin.

skin.dynamic Skin dynamic – Whether or not the no


skin is dynamic. The emulator skin is a
dynamic skin if the emulator is to
construct a skin of a given size based
on a specified width and height.

For more information about these properties, see Hardware Profile Properties.
Android Emulator Troubleshooting
7/17/2018 • 7 minutes to read • Edit Online

In this article, the most common warning messages and issues that occur while configuring and running the
Android Emulator are described, along with workarounds and tips.

Performance Warnings
Visual Studio
Visual Studio for Mac
Beginning with Visual Studio 2017 version 15.4, a performance warning dialog may be displayed when you first
deploy your app to the Android Emulator. These warning dialogs are explained below.
Computer Does Not Contain an Intel Procesor

When this dialog is displayed, your computer does not have an Intel processor, which is required for acceleration
of the Android SDK Emulator. If your computer does not have an Intel processor, we recommend using a physical
Android device for development.
Hyper-V Is Installed or Active

When this dialog is displayed, Hyper-V is installed or active and must be disabled. Disabling Hyper-V explains how
to resolve this issue.
HAXM is Not Installed
This dialog indicates that your computer has an Intel processor, Hyper-V is disabled, but HAXM is not installed.
Installing HAXM describes the steps for installing HAXM.
HAXM Process Not Running

This dialog is displayed if your computer has an Intel processor, Hyper-V is disabled, Intel HAXM is installed, but
the HAXM process is not running. To resolve this issue, open a Command Prompt window and enter the following
command:

sc query intelhaxm

If the HAXM process is running, you should see output similar to the following:

SERVICE_NAME: intelhaxm
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0

If STATE is not set to RUNNING , see How to Use the Intel Hardware Accelerated Execution Manager to resolve the
problem.
Other Failures

This dialog is displayed if your computer has an Intel processor, Hyper-V is disabled, Intel HAXM is installed, the
HAXM process is running, but the emulator fails to start for some unknown reason. To help resolve this error, see
How to Use the Intel Hardware Accelerated Execution Manager.
Disabling Performance Warnings
If you would rather not see performance warnings, you can disable them. In Visual Studio, click Tools > Options
> Xamarin > Android Settings and disable the Warn if AVD acceleration is not supported (HAXM ) option:

Deployment Issues
If you get an error about a failure to install the APK on the emulator or a failure to run the Android Debug Bridge
(adb), verify that the Android SDK can connect to your emulator. To do this, use the following steps:
1. Launch the emulator from the Android Device Manager (select your virtual device and click Start).
2. Open a Command Prompt and go to the folder where adb is installed. For example, on Windows, this
might be at: C:\Program Files (x86)\Android\android-sdk\platform -tools\adb.exe.
3. Type the following command:

adb devices

4. If the emulator is accessible from the Android SDK, the emulator should appear in the list of attached
devices. For example:

List of devices attached


emulator-5554 device

5. If the emulator does not appear in this list, start the Android SDK Manager, apply all updates, then try
launching the emulator again.

HAXM Issues
Visual Studio
Visual Studio for Mac
If the Android Emulator does not start properly, this is often caused by problems with HAXM. HAXM issues are
often the result of conflicts with other virtualization technologies, incorrect settings, or an out of date HAXM driver.
HAXM Virtualization Conflicts
HAXM can conflict with other technologies that use virtualization, such as Hyper-V, Windows Device Guard, and
some antivirus software:
Hyper-V – If you are using a version of Windows before the Windows 10 April 2018 update (build
1803) and Hyper-V is enabled, follow the steps in Disabling Hyper-V.
Device Guard – Device Guard and Credential Guard can prevent Hyper-V from being disabled on
Windows machines. To disable Device Guard and Credential Guard, see Disabling Device Guard.
Antivirus Software – If you are running antivirus software that uses hardware-assisted virtualization (such
as Avast), disable or uninstall this software, reboot, and retry the Android SDK Emulator.
Incorrect BIOS Settings
If you are using HAXM on a Windows PC, HAXM will not work unless virtualization technology (Intel VT-x) is
enabled in the BIOS. If VT-x is disabled, you will get an error similiar to the following when you attempt to start
the Android Emulator:
This computer meets the requirements for HAXM, but Intel Virtualization Technology (VT-x) is not
turned on.
To correct this error, boot the computer into the BIOS, enable both VT-x and SL AT (Second Level Address
Translation), then restart the computer back into Windows.
Disabling Hyper-V
If you are using a version of Windows before the Windows 10 April 2018 Update (build 1803) and Hyper-V is
enabled, you must disable Hyper-V and reboot your computer to install and use HAXM. If you are using
Windows 10 April 2018 Update (build 1803) or later, Android Emulator version 27.2.7 or later can use Hyper-V
(instead of HAXM ) for hardware acceleration, so it is not necessary to disable Hyper-V.
You can disable Hyper-V from the Control Panel by following these steps:
1. In the Windows search box, enter Programs and then click the Programs and Features search result.
2. In the Control Panel Programs and Features dialog, click Turn Windows features on or off:

3. Uncheck Hyper-V and restart the computer:


Alternately, you can use the following Powershell cmdlet to disable Hyper-V:
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Hypervisor

Intel HAXM and Microsoft Hyper-V cannot both be active at the same time. Unfortunately, there is no way to
switch between between Hyper-V and HAXM without restarting your computer.
In some cases, using the above steps will not succeed in disabling Hyper-V if Device Guard and Credential Guard
are enabled. If you are unable to disable Hyper-V (or it seems to be disabled but HAXM installation still fails), use
the steps in the next section to disable Device Guard and Credential Guard.
Disabling Device Guard
Device Guard and Credential Guard can prevent Hyper-V from being disabled on Windows machines. This is
often a problem for domain-joined machines that are configured and controlled by an owning organization. On
Windows 10, use the following steps to see if Device Guard is running:
1. In Windows Search, type System info to start the System Information app.
2. In the System Summary, look to see if Device Guard Virtualization based security is present and is in
the Running state:

If Device Guard is enabled, use the following steps to disable it:


1. Ensure that Hyper-V is disabled (under Turn Windows Features on or off) as described in the previous
section.
2. In the Windows Search Box, type gpedit and select the Edit group policy search result. This launches the
Local Group Policy Editor.
3. In the Local Group Policy Editor, navigate to Computer Configuration > Administrative Templates
> System > Device Guard:

4. Change Turn On Virtualization Based Security to Disabled (as shown above) and exit the Local Group
Policy Editor.
5. In the Windows Search Box, type cmd. When Command Prompt appears in the search results, right-click
Command Prompt and select Run as Administrator.
6. Copy and paste the following commands into the command prompt window (if drive Z: is in use, pick an
unused drive letter to use instead):

mountvol Z: /s
copy %WINDIR%\System32\SecConfig.efi Z:\EFI\Microsoft\Boot\SecConfig.efi /Y
bcdedit /create {0cb3b571-2f2e-4343-a879-d86a476d7215} /d "DebugTool" /application osloader
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} path "\EFI\Microsoft\Boot\SecConfig.efi"
bcdedit /set {bootmgr} bootsequence {0cb3b571-2f2e-4343-a879-d86a476d7215}
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions DISABLE-LSA-ISO,DISABLE-VBS
bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} device partition=Z:
mountvol Z: /d

7. Restart your computer. On the boot screen, you should see a prompt like the following:
Do you want to disable Credential Guard?
Press the indicated key to disable Credential Guard as prompted.
8. After the computer reboots, check again to ensure that Hyper-V is disabled (as described in the previous
steps).
If Hyper-V is still not disabled, the policies of your domain-joined computer may prevent you from disabling
Device Guard or Credential Guard. In this case, you can request an exemption from your domain adminstrator to
allow you to opt out of Credential Guard. Alternately, you can use a computer that is not domain-joined to use
HAXM.
Set Up Device for Development
6/25/2018 • 6 minutes to read • Edit Online

This article will discuss how to setup an Android device and connect it to a computer so that the device may be
used to run and debug Xamarin.Android applications.
By now, you've probably seen your great new application running on the Android emulator, and want to see it
running on your shiny Android device. Here are the steps involved with connecting a device to a computer for
debugging:
1. Enable Debugging on the Device - By default, it will not be possible to debug applications on a Android
device.
2. Install USB Drivers - This step is not necessary for OS X computers. Windows computers may require
the installation of USB drivers.
3. Connect the Device to the Computer - The final step involves connecting the device to the computer by
either USB or WiFi.
Each of these steps will be covered in more detail in the sections below.

Enable Debugging on the Device


It is possible to use any Android device to test an Android application. However the device must be properly
configured before debugging can occur. The steps involved are slightly different, depending on the version of
Android running on the device.
Android 4.0 to Android 4.1
For Android 4.0.x to Android 4.1.x, debugging is enabled by following these steps:
1. Go to the Settings screen.
2. Select Developer options .
3. Check off the USB debugging option.
This screenshot shows the Developer options screen on a device running Android 4.0.3:
Android 4.2 and higher
Starting in Android 4.2 and higher, the Developer options is hidden by default. To make it available, go to
Settings > About phone, and tap the Build number item seven times to reveal the Developer Options tab:

Once the Developer Options tab is available under Settings > System, open it to reveal developer settings:
This is the place to enable developer options such as USB debugging and stay awake mode.

Install USB Drivers


This step is not necessary for OS X. Just connect the device to the the Mac with a USB cable.
It may be necessary to install some extra drivers before a Windows computer will recognize an Android device
connected by USB.

NOTE
These are the steps to set up a Google Nexus device and are provided as a reference. Steps for your specific device may
vary, but will follow a similar pattern. Search the internet for your device if you have trouble.

Run the android.bat application in the [Android SDK install path]\tools directory. By default, the
Xamarin.Android installer will put the Android SDK in following location on a Windows computer:

C:\Users\[username]\AppData\Local\Android\android-sdk

Download the USB Drivers


Google Nexus devices (with the exception of the Galaxy Nexus) require the Google USB Driver. The driver for the
Galaxy Nexus is distributed by Samsung. All other Android devices should use the USB driver from their
respective manufacturer.
Install the Google USB Driver package by starting the Android SDK Manager, and expanding the Extras folder,
as can be seen in the follow screenshot:

Check the Google USB Driver box, and click the Install button. The driver files are downloaded to the following
location:

[Android SDK install path]\extras\google\usb\_driver

The default path for a Xamarin.Android installation is:

C:\Users\[username]\AppData\Local\Android\android-sdk\extras\google\usb_driver
Installing the USB Driver
After the USB drivers are downloaded, it is necessary to install them. To install the drivers on Windows 7:
1. Connect your device to the computer with a USB cable.
2. Right-click on the Computer from your desktop or Windows Explorer, and select Manage .
3. Select Devices in the left pane.
4. Locate and expand Other Devices in the right pane.
5. Right-click the device name and select Update Driver Software . This will launch the Hardware Update
Wizard.
6. Select Browse my computer for driver software and click Next .
7. Click Browse and locate the USB driver folder (the Google USB driver is located in [Android SDK install
path]\extras\google\usb_driver).
8. Click Next to install the driver.
Installing Unverified Drivers in Windows 8
Extra steps may be required to install an unverified driver in Windows 8. The following steps describe how to
install the drivers for a Galaxy Nexus:
1. Access the Windows 8 Advanced Boot Options - This step involves rebooting the computer to access
the Advanced Boot Options. Start up a command line prompt and reboot the computer by using the
following command:

shutdown.exe /r /o

2. Connect the device - Connect the device to the computer


3. Start Device Manager - Run devmgmt.msc; you should see your device listed with a yellow triangle
over it.
4. Install the Device Drivers - Install the device drivers as described above.

Connect the Device to the Computer


The final step is to connect the device to the computer. There are two ways to do so:
USB cable - This is the easiest and most common way. Just plug the USB cable into the device and then
into the computer.
WiFi - It is possible to connect an Android device to a computer without using a USB cable, over WiFi.
This technique requires a bit more effort but could be useful when there is no USB cable or the device is to
far away for a USB cable. Connecting via WiFi will be covered in the next section.
Connecting over WiFi
By default, the Android Debug Bridge (ADB ) is configured to communicate with an Android device via USB. It is
possible to to reconfigure it to use TCP/IP instead of USB. To do this, both the device and the computer must be
on the same WiFi network. To setup your environment to debug over WiF issue these steps from the command
line:
1. Determine the IP address of your Android device. One way to find out the IP address is to look under
Settings > Wi-Fi , and then tap on the WiFi network that the device is connected to. This will bring up a
settings screen showing information about the network connection, similar to what is seen in the
screenshot below:
On some versions of Android the IP address won't be listed there but can be found instead under Settings
> About phone > Status.
2. Connect your Android device to your computer via USB.
3. Next, restart ADB so that it using TCP on port 5555. From a command prompt, type the following
command:

adb tcpip 5555

After this command is issued, your computer will not be able to listen to devices that are connected via
USB.
4. Disconnect the USB cable connecting your device to your computer.
5. Configure ADB so that it will connect to your Android device on the port that was specified in step 1
above:

adb connect 192.168.1.28:5555

Once this command finished the Android device is connected to the computer via WiFi.
When you're done debugging via WiFi, it is possible reset ADB back to USB mode with the following command:

adb usb

It is possible to ask ADB to list the devices that are connected to the computer. Regardless of how the devices are
connected, you can issue the following command at the command prompt to see what is connected:

adb devices

Summary
This article discussed how to configure an Android device for development by enabling debugging on the device.
It also covered how to connect the device to a computer using either USB or WiFi.

Related Links
Android Debug Bridge
Using Hardware Devices
Samsung Driver Downloads
OEM USB Drivers
Google USB Driver
XDA Developers : Windows 8 - ADB/fastboot driver problem solved
Microsoft's OpenJDK Distribution Preview
7/25/2018 • 2 minutes to read • Edit Online

This guide describes the steps for switching to the preview release of Microsoft's distribution of the OpenJDK.

Overview
Beginning with Visual Studio 15.9 and Visual Studio for Mac 7.7, Visual Studio Tools for Xamarin will move from
Oracle’s JDK to a lightweight version of the OpenJDK that is intended solely for Android development:

The benefits of this move are:


You will always have an OpenJDK version that works for Android development.
Downloading JDK 9 or 10 won’t affect the development experience.
Significantly reduced download size and footprint.
No more issues with 3rd party servers and installers.
If you’d like to move to the improved experience sooner, builds of the Microsoft OpenJDK distribution are available
for you to test on both Windows and Mac. The setup process is described below, and you can revert back to the
Oracle JDK at any time.

Download
To get started, download the correct build for your system:
Mac – https://dl.xamarin.com/OpenJDK/mac/microsoft-dist-openjdk-1.8.0.9.zip
Windows x86 – https://dl.xamarin.com/OpenJDK/win32/microsoft-dist-openjdk-1.8.0.9.zip
Windows x64 – https://dl.xamarin.com/OpenJDK/win64/microsoft-dist-openjdk-1.8.0.9.zip

Configure
Unzip to the correct location:
Mac – $HOME/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.9
Windows – C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.9

IMPORTANT
This example uses build 1.8.0.9; however, the version you download may be newer.

Point the IDE to the new JDK:


Mac – Click Tools > SDK Manager > Locations and change the Java SDK (JDK) Location to the full path
of the OpenJDK installation. In the following example, this path is set to
$HOME/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.9.

Windows – Click Tools > Options > Xamarin > Android Settings and change the Java Development Kit
Location to the full path of the OpenJDK installation. In the following example, this path is set to C:\Program
Files\Android\jdk\microsoft_dist_openjdk_1.8.0.9:
Revert
To revert to the Oracle JDK, change the Java SDK location to the previously-used Oracle JDK path and rebuild the
solution. On Mac, you can revert to the Oracle JDK path by clicking Reset to Defaults.
If you have any problems with the Microsoft OpenJDK distribution, please report issues by using the feedback tool
in your IDE so that they can be tracked and corrected quickly.

Known Issues & Planned Fix Dates


The JAVA_HOME environment variable may not be correctly exported to the SDK and the Device Manager. As a
workaround, you can set this environment variable to the location of the OpenJDK on your computer. This is fixed
in the 15.9 Previews.

Summary
In this article, you learned how to configure your IDE to use the preview release of Microsoft's OpenJDK
distribution, which is slated for stable release later in 2018.
Hello, Android
7/25/2018 • 2 minutes to read • Edit Online

In this two -part guide, you will build your first Xamarin.Android application using Visual Studio for Mac or Visual
Studio and develop an understanding of the fundamentals of Android application development with Xamarin.
Along the way, the tools, concepts, and steps required to build and deploy a Xamarin.Android application will be
introduced.

Part 1: Quickstart
In the first part of this guide you'll create an application that translates an alphanumeric phone number entered
by the user into a numeric phone number, and then calls that number.

Part 2: Deep Dive


In the second part of this document, you'll review what was built and develop a fundamental understanding of
how Android applications work.

Related Links
Android Getting Started
Debugging in Visual Studio
Visual Studio for Mac Recipes - Debugging
Hello, Android: Quickstart
7/20/2018 • 14 minutes to read • Edit Online

In this two -part guide, you will build your first Xamarin.Android application (using Visual Studio or Visual Studio
for Mac) and develop an understanding of the fundamentals of Android application development with Xamarin.
Along the way, you will be introduced to the tools, concepts, and steps required to build and deploy a
Xamarin.Android application.

Hello, Android Quickstart


In this walkthrough, you will create an application that translates an alphanumeric phone number (entered by the
user) into a numeric phone number and display the numeric phone number to the user. The final application
looks like this:

Requirements
To follow along with this walkthrough, you will need the following:
Visual Studio
Visual Studio for Mac
Windows 7 or later.
Visual Studio 2015 Professional or later.
This walkthrough assumes that the latest version of Xamarin.Android is installed and running on your platform
of choice. For a guide to installing Xamarin.Android, refer to the Xamarin.Android Installation guides. Before you
get started, please download and unzip the Xamarin App Icons & Launch Screens set.

Configuring Emulators
If you are using the Android emulator, we recommend that you configure the emulator to use hardware
acceleration. Instructions for configuring hardware acceleration are available in Hardware Acceleration for
Emulator Performance.

Walkthrough
Visual Studio
Visual Studio for Mac
Start Visual Studio. Click File > New > Project to create a new project.
In the New Project dialog, click the Android App template. Name the new project Phoneword . Click OK:

In the New Android App dialog, click Blank App and click OK to create the new project:
Creating the Layout
After the new project is created, expand the Resources folder and then the layout folder in the Solution
Explorer. Double-click activity_main.axml to open it in the Android Designer. This is the layout file for the
app's screen:

From the Toolbox (the area on the left), enter text into the search field and drag a Text (Large) widget onto
the design surface (the area in the center):
With the Text (Large) control selected on the design surface, use the Properties pane to change the text
property of the Text (Large) widget to Enter a Phoneword: as shown here:

Drag a Plain Text widget from the Toolbox to the design surface and place it underneath the Text (Large)
widget:

With the Plain Text widget selected on the design surface, use the Properties pane to change the id property
of the Plain Text widget to @+id/PhoneNumberText and change the text property to 1-855-XAMARIN :
Drag a Button from the Toolbox to the design surface and place it underneath the Plain Text widget:

With the Button selected on the design surface, use the Properties pane to change the id property of the
Button to @+id/TranslateButton and change the text property to Translate :

Drag a TextView from the Toolbox to the design surface and place it under the Button widget. Set the id
property of the TextView to @+id/TranslatedPhoneWord and change the text to an empty string:
Save your work by pressing CTRL+S.
Writing Translation Code
The next step is to add some code to translate phone numbers from alphanumeric to numeric. Add a new file to
the project by right-clicking the Phoneword project in the Solution Explorer pane and choosing Add > New
Item... as shown below:

In the Add New Item dialog, select Visual C# > Code > Code File and name the new code file
PhoneTranslator.cs:

This creates a new empty C# class. Insert the following code into this file:
using System.Text;
using System;
namespace Core
{
public static class PhonewordTranslator
{
public static string ToNumber(string raw)
{
if (string.IsNullOrWhiteSpace(raw))
return "";
else
raw = raw.ToUpperInvariant();

var newNumber = new StringBuilder();


foreach (var c in raw)
{
if (" -0123456789".Contains(c))
{
newNumber.Append(c);
}
else
{
var result = TranslateToNumber(c);
if (result != null)
newNumber.Append(result);
}
// otherwise we've skipped a non-numeric char
}
return newNumber.ToString();
}
static bool Contains (this string keyString, char c)
{
return keyString.IndexOf(c) >= 0;
}
static int? TranslateToNumber(char c)
{
if ("ABC".Contains(c))
return 2;
else if ("DEF".Contains(c))
return 3;
else if ("GHI".Contains(c))
return 4;
else if ("JKL".Contains(c))
return 5;
else if ("MNO".Contains(c))
return 6;
else if ("PQRS".Contains(c))
return 7;
else if ("TUV".Contains(c))
return 8;
else if ("WXYZ".Contains(c))
return 9;
return null;
}
}
}

Save the changes to the PhoneTranslator.cs file by clicking File > Save (or by pressing CTRL+S ), then close
the file.
Wiring up the Interface
The next step is to add code to wire up the user interface by inserting backing code into the MainActivity class.
Begin by wiring up the Translate button. In the MainActivity class, find the OnCreate method. The next step is
to add the button code inside OnCreate , below the base.OnCreate(bundle) and
SetContentView (Resource.Layout.Main) calls. First, modify the template code so that the OnCreate method
resembles the following:

using System;
using Android.App;
using Android.Content;
using Android.Widget;
using Android.OS;

namespace Phoneword
{
[Activity (Label = "Phone Word", MainLauncher = true)]
public class MainActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);

// New code will go here


}
}
}

Get a reference to the controls that were created in the layout file via the Android Designer. Add the following
code inside the OnCreate method, after the call to SetContentView :

// Get our UI controls from the loaded layout


EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneWord);
Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);

Add code that responds to user presses of the Translate button. Add the following code to the OnCreate method
(after the lines added in the previous step):

// Add code to translate number


translateButton.Click += (sender, e) =>
{
// Translate user's alphanumeric phone number to numeric
string translatedNumber = Core.PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = string.Empty;
}
else
{
translatedPhoneWord.Text = translatedNumber;
}
};

Save your work by selecting File > Save All (or by pressing CTRL -SHIFT-S ) and build the application by
selecting Build > Rebuild Solution (or by pressing CTRL -SHIFT-B ).
If there are errors, go through the previous steps and correct any mistakes until the application builds
successfully. If you get a build error such as, Resource does not exist in the current context, verify that the
namespace name in MainActivity.cs matches the project name ( Phoneword ) and then completely rebuild the
solution. If you still get build errors, verify that you have installed the latest Xamarin.Android updates.
Setting the Label and App Icon
You should now have a working application – it's time to add the finishing touches! In MainActivity.cs, edit the
Label for the MainActivity . The Label is what Android displays at the top of the screen to let users know
where they are in the application. At the top of the MainActivity class, change the Label to Phone Word as
shown here:

namespace Phoneword
{
[Activity (Label = "Phone Word", MainLauncher = true)]
public class MainActivity : Activity
{
...
}
}

Now it's time to set the application icon. By default, Visual Studio will provide a default icon for the project. Let's
delete these files from the solution, and replace them with a different icon. Expand the Resources folder in the
Solution Pad. Notice that there are five folders that are prefixed with mipmap-, and that each of these folders
contains a single Icon.png file:
It is necessary to delete each of these icon files from the project. Right click on each of Icon.png files, and select
Delete from the context menu:
Click on the Delete button in the dialog.
Next, download and unzip Xamarin App Icons set. This zip file holds the icons for the application. Each icon is
visually identical but at different resolutions it renders correctly on different devices with different screen
densities. The set of files must be copied into the Xamarin.Android project. In Visual Studio, in the Solution
Explorer, right-click the mipmap-hdpi folder and select Add > Existing Items:

From the selection dialog, navigate to the unzipped Xamarin AdApp Icons directory and open the mipmap-hdpi
folder. Select Icon.png and click Add.
Repeat these steps for each of the mipmap- folders until the contents of the mipmap- Xamarin App Icons
folders are copied to their counterpart mipmap- folders in the Phoneword project.
After all the icons are copied to the Xamarin.Android project, open the Project Options dialog by right clicking
on the project in the Solution Pad. Select Build > Android Application and select **@mipmap/icon** from
the Application icon combo box:

Running the App


Finally, test the application by running it on an Android device or emulator and translating a Phoneword:

Congratulations on completing your first Xamarin.Android application! Now it's time to dissect the tools and
skills you have just learned. Next up is the Hello, Android Deep Dive.

Related Links
Xamarin Android App Icons (ZIP )
Phoneword (sample)
Hello, Android: Deep Dive
7/25/2018 • 17 minutes to read • Edit Online

In this two -part guide, you'll build your first Xamarin.Android application and develop an understanding of the
fundamentals of Android application development with Xamarin. Along the way, you will be introduced to the
tools, concepts, and steps required to build and deploy a Xamarin.Android application.

Hello, Android Deep Dive


In the Hello, Android Quickstart, you built and ran your first Xamarin.Android application. Now it's time to
develop a deeper understanding of how Android applications work so that you can build more sophisticated
programs. This guide reviews the steps that you took in the Hello, Android walkthrough so that you can
understand what you did and begin to develop a fundamental understanding of Android application development.
This guide will touch upon the following topics:
Visual Studio
Visual Studio for Mac
Introduction to Visual Studio – Introduction to Visual Studio and creating a new Xamarin.Android
application.
Anatomy of a Xamarin.Android Application - Tour of the essential parts of a Xamarin.Android
application.
App Fundamentals and Architecture Basics – Introduction to Activities, the Android Manifest, and the
general flavor of Android development.
User Interface (UI ) – Creating user interfaces with the Android Designer.
Activities and the Activity Lifecycle – An introduction to the Activity Lifecycle and wiring up the user
interface in code.
Testing, Deployment, and Finishing Touches – Complete your application with advice on testing,
deployment, generating artwork, and more.
This guide helps you develop the skills and knowledge required to build a single-screen Android application. After
you work through it, you should understand the different parts of a Xamarin.Android application and how they fit
together.
Visual Studio
Visual Studio for Mac

Introduction to Visual Studio


Visual Studio is a powerful IDE from Microsoft. It features a fully integrated visual designer, a text editor that
includes refactoring tools, an assembly browser, source code integration, and more. In this guide you'll learn to use
some basic Visual Studio features with the Xamarin plug-in.
Visual Studio organizes code into Solutions and Projects. A Solution is a container that can hold one or more
Projects. A Project can be an application (such as for iOS or Android), a supporting library, a test application, and
more. In the Phoneword app, you added a new Android Project using the Android Application template to the
Phoneword Solution created in the Hello, Android guide.
Anatomy of a Xamarin.Android Application
Visual Studio
Visual Studio for Mac
The following screenshot lists the Solution's contents. This is the Solution Explorer, which contains the directory
structure and all of the files associated with the Solution:

A Solution called Phoneword was created and the Android project Phoneword was placed inside of it.
Look at the items inside the Project to see each folder and its purpose:
Properties – Contains the AndroidManifest.xml file that describes all of the requirements for the
Xamarin.Android application, including name, version number, and permissions. The Properties folder also
houses AssemblyInfo.cs, a .NET assembly metadata file. It is a good practice to fill this file with some basic
information about your application.
References – Contains the assemblies required to build and run the application. If you expand the
References directory, you'll see references to .NET assemblies such as System, System.Core, and
System.Xml, as well as a reference to Xamarin's Mono.Android assembly.
Assets – Contains the files the application needs to run including fonts, local data files, and text files. Files
included here are accessible through the generated Assets class. For more information on Android Assets,
see the Xamarin Using Android Assets guide.
Resources – Contains application resources such as strings, images, and layouts. You can access these
resources in code through the generated Resource class. The Android Resources guide provides more
details about the Resources directory. The application template also includes a concise guide to Resources
in the AboutResources.txt file.
Resources
The Resources directory contains four folders named drawable, layout, mipmap and values, as well as a file
named Resource.designer.cs.
The items are summarized in the table below:
drawable – The drawable directories house drawable resources such as images and bitmaps.
mipmap – The mipmap directory holds drawable files for different launcher icon densities. In the default
template, the drawable directory houses the application icon file, Icon.png.
layout – The layout directory contains Android designer files (.axml) that define the user interface for each
screen or Activity. The template creates a default layout called Main.axml.
values – This directory houses XML files that store simple values such as strings, integers, and colors. The
template creates a file to store string values called Strings.xml.
Resource.designer.cs – Also known as the Resource class, this file is a partial class that holds the unique
IDs assigned to each resource. It is automatically created by the Xamarin.Android tools and is regenerated
as necessary. This file should not be manually edited, as Xamarin.Android will overwrite any manual
changes made to it.

App Fundamentals and Architecture Basics


Android applications do not have a single entry point; that is, there is no single line of code in the application that
the operating system calls to start the application. Instead, an application starts when Android instantiates one of
its classes, during which time Android loads the entire application's process into memory.
This unique feature of Android can be extremely useful when designing complicated applications or interacting
with the Android operating system. However, these options also make Android complex when dealing with a basic
scenario like the Phoneword application. For this reason, exploration of Android architecture is split in two. This
guide dissects an application that uses the most common entry point for an Android app: the first screen. In Hello,
Android Multiscreen, the full complexities of Android architecture are explored as different ways to launch an
application are discussed.
Phoneword Scenario - Starting with an Activity
When you open the Phoneword application for the first time in an emulator or device, the operating system
creates the first Activity. An Activity is a special Android class that corresponds to a single application screen, and
it is responsible for drawing and powering the user interface. When Android creates an application's first Activity,
it loads the entire application:

Since there is no linear progression through an Android application (you can launch the application from several
points), Android has a unique way of keeping track of what classes and files make up an application. In the
Phoneword example, all the parts that make up the application are registered with a special XML file called the
Android Manifest. The role of the Android Manifest is to keep track of an application's contents, properties,
and permissions and to disclose them to the Android operating system. You can think of the Phoneword
application as a single Activity (screen) and a collection of resource and helper files tied together by the Android
Manifest file, as illustrated by the diagram below:
The next few sections explore the relationships between the various parts of the Phoneword application; this
should provide you with a better understanding of the diagram above. This exploration begins with the user
interface as it discusses the Android designer and layout files.

User Interface
Main.axml is the user interface layout file for the first screen in the application. The .axml indicates that this is an
Android designer file (AXML stands for Android XML). The name Main is arbitrary from Android's point of view –
the layout file could have been named something else. When you open Main.axml in the IDE, it brings up the
visual editor for Android layout files called the Android Designer:
Visual Studio
Visual Studio for Mac
In the Phoneword app, the TranslateButton's ID is set to @+id/TranslateButton :
Visual Studio
Visual Studio for Mac

When you set the id property of the TranslateButton, the Android Designer maps the TranslateButton control
to the Resource class and assigns it a resource ID of TranslateButton . This mapping of visual control to class
makes it possible to locate and use the TranslateButton and other controls in app code. This will be covered in
more detail when you break apart the code that powers the controls. All you need to know for now is that the code
representation of a control is linked to the visual representation of the control in the designer via the id property.
Source View
Everything defined on the design surface is translated into XML for Xamarin.Android to use. The Android
Designer provides a source view that contains the XML that was generated from the visual designer. You can view
this XML by switching to the Source panel in the lower left of the designer view, as illustrated by the screenshot
below:
Visual Studio
Visual Studio for Mac

This XML source code should contain the Text (Large), Plain Text, and the two Button elements. For a more in-
depth tour of the Android Designer, refer to the Xamarin Android Designer Overview guide.
The tools and concepts behind the visual part of the user interface have now been covered. Next, it's time to jump
into the code that powers the user interface as Activities and the Activity Lifecycle are explored.

Activities and the Activity Lifecycle


The Activity class contains the code that powers the user interface. The Activity is responsible for responding to
user interaction and creating a dynamic user experience. This section introduces the Activity class, discusses the
Activity Lifecycle, and dissects the code that powers the user interface in the Phoneword application.
Activity Class
The Phoneword application has only one screen (Activity). The class that powers the screen is called
MainActivity and lives in the MainActivity.cs file. The name MainActivity has no special significance in Android
– although the convention is to name the first Activity in an application MainActivity , Android does not care if it is
named something else.
When you open MainActivity.cs, you can see that the MainActivity class is a subclass of the Activity class, and
that the Activity is adorned with the Activity attribute:
[Activity (Label = "Phone Word", MainLauncher = true)]
public class MainActivity : Activity
{
...
}

The Activity Attribute registers the Activity with the Android Manifest; this lets Android know that this class is
part of the Phoneword application managed by this manifest. The Label property sets the text that will be
displayed at the top of the screen.
The MainLauncher property tells Android to display this Activity when the application starts up. This property
becomes important as you add more Activities (screens) to the application as explained in the Hello, Android
Multiscreen guide.
Now that the basics of MainActivity have been covered, it's time to dive deeper into the Activity code by
introducing the Activity Lifecycle.
Activity Lifecycle
In Android, Activities go through different stages of a lifecycle depending on their interactions with the user.
Activities can be created, started and paused, resumed and destroyed, and so on. The Activity class contains
methods that the system calls at certain points in the screen's lifecycle. The following diagram illustrates a typical
life of an Activity as well as some of the corresponding lifecycle methods:
By overriding Activity lifecycle methods, you can control how the Activity loads, how it reacts to the user, and
even what happens after it disappears from the device screen. For example, you can override the lifecycle methods
in the diagram above to perform some important tasks:
OnCreate – Creates views, initializes variables, and performs other prep work that must be done before the
user sees the Activity. This method is called only once when the Activity is loaded into memory.
OnResume – Performs any tasks that must happen every time the Activity returns to the device screen.
OnPause – Performs any tasks that must happen every time the Activity leaves the device screen.
When you add custom code to a lifecycle method in the Activity , you override that lifecycle method's base
implementation. You tap into the existing lifecycle method (which has some code already attached to it), and you
extend that method with your own code. You call the base implementation from inside your method to ensure that
the original code runs before your new code. An example of this is illustrated in the next section.
The Activity Lifecycle is an important and complex part of Android. If you'd like to learn more about Activities
after you finish the Getting Started series, read the Activity Lifecycle guide. In this guide, the next focus is the first
stage of the Activity Lifecycle, OnCreate .
OnCreate
Android calls the Activity 's OnCreate method when it creates the Activity (before the screen is presented to the
user). You can override the OnCreate lifecycle method to create views and prepare your Activity to meet the user:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Set our view from the "main" layout resource


SetContentView (Resource.Layout.Main);
// Additional setup code will go here
}

In the Phoneword app, the first thing to do in OnCreate is load the user interface created in the Android
Designer. To load the UI, call SetContentView and pass it the resource layout name for the layout file: Main.axml .
The layout is located at Resource.Layout.Main :

SetContentView (Resource.Layout.Main);

When MainActivity starts up, it creates a view that is based on the contents of the Main.axml file. Note that the
layout file name is matched to the Activity name – Main.axml is the layout for MainActivity. This isn't required
from Android's point of view, but as you begin to add more screens to the application, you'll find that this naming
convention makes it easier to match the code file to the layout file.
After the layout file is prepared, you can start looking up controls. To look up a control, call FindViewById and pass
in the resource ID of the control:

EditText phoneNumberText = FindViewById<EditText>(Resource.Id.PhoneNumberText);


Button translateButton = FindViewById<Button>(Resource.Id.TranslateButton);
TextView translatedPhoneWord = FindViewById<TextView>(Resource.Id.TranslatedPhoneWord);

Now that you have references to the controls in the layout file, you can start programming them to respond to
user interaction.
Responding to User Interaction
In Android, the Click event listens for the user's touch. In this app, the Click event is handled with a lambda, but
a delegate or a named event handler could be used instead. The final TranslateButton code resembled the
following:

translateButton.Click += (sender, e) =>


{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = string.Empty;
}
else
{
translatedPhoneWord.Text = translatedNumber;
}
};

Testing, Deployment, and Finishing Touches


Both Visual Studio for Mac and Visual Studio provide many options for testing and deploying an application. This
section covers debugging options, demonstrates testing applications on a device, and introduces tools for creating
custom app icons for different screen densities.
Debugging Tools
Issues in application code can be difficult to diagnose. To help diagnose complex code issues, you can Set a
Breakpoint, Step Through Code, or Output Information to the Log Window.
Deploy to a Device
The emulator is a good start for deploying and testing an application, but users will not consume the final app in
an emulator. It's a good practice to test applications on a real device early and often.
Before an Android device can be used for testing applications, it needs to be configured for development. The Set
Up Device for Development guide provides thorough instructions on getting a device ready for development.
Visual Studio
Visual Studio for Mac
After the device is configured, you can deploy to it by plugging it in, selecting it from the Select Device dialog,
and starting the application:

This launches the application on the device:


Set Icons for Different Screen Densities
Android devices come in different screen sizes and resolutions, and not all images look good on all screens. For
example, here is a screenshot of a low -density icon on a high-density Nexus 5. Notice how blurry it is compared to
the surrounding icons:
To account for this, it is good practice to add icons of different resolutions to the Resources folder. Android
provides different versions of the mipmap folder to handle launcher icons of different densities, mdpi for
medium, hdpi for high, and xhdpi, xxhdpi, xxxhdpi for very high density screens. Icons of varying sizes are stored
in the appropriate mipmap- folders:
Visual Studio
Visual Studio for Mac
Android will pick the icon with the appropriate density:

Generate Custom Icons


Not everyone has a designer available to create the custom icons and launch images that an app needs to stand
out. Here are several alternate approaches to generating custom app artwork:
Visual Studio
Visual Studio for Mac
Android Asset Studio – A web-based, in-browser generator for all types of Android icons, with links to
other useful community tools. It works best in Google Chrome.
Visual Studio – You can use this to create a simple icon set for your app directly in the IDE.
Glyphish – High-quality prebuilt icon sets for free download and purchase.
Fiverr – Choose from a variety of designers to create an icon set for you, starting at $5. Can be hit or miss
but a good resource if you need icons designed on the fly.
For more information about icon sizes and requirements, refer to the Android Resources guide.
Visual Studio
Visual Studio for Mac
Summary
Congratulations! You should now have a solid understanding of the components of a Xamarin.Android application
as well as the tools required to create it.
In the next tutorial of the Getting Started series, you will extend your application to handle multiple screens as you
explore more advanced Android architecture and concepts.
Hello, Android Multiscreen
7/25/2018 • 2 minutes to read • Edit Online

In this two -part guide, you expand the Phoneword application that you created in the Hello, Android guide to
handle a second screen. Along the way, this guide will introduce the basic Android Application Building Blocks and
dive deeper into Android architecture as you develop a better understanding of Android application structure and
functionality.

Part 1: Quickstart
In the first part of this guide, you'll add a second screen to the Phoneword application to keep track of the history
of numbers called from the app. The final app will display a second screen that lists the call history.

Part 2: Deep Dive


In the second part of this document, you will review what you've built and discusses architecture, navigation, and
other new Android concepts that are encountered along the way.

Related Links
Android Getting Started
Debugging in Visual Studio
Visual Studio for Mac Recipes - Debugging
Hello, Android Multiscreen: Quickstart
5/1/2018 • 6 minutes to read • Edit Online

This two -part guide expands the Phoneword application to handle a second screen. Along the way, basic Android
Application Building Blocks are introduced with a deeper dive into Android architecture.

Hello, Android Multiscreen Quickstart


In the walkthrough portion of this guide, you'll add a second screen to the Phoneword application to keep track of
the history of numbers translated using the app. The final application will have a second screen that displays the
numbers that were "translated", as illustrated by the screenshot on the right:

The accompanying Deep Dive reviews what was built and discusses architecture, navigation, and other new
Android concepts encountered along the way.

Requirements
Because this guide picks up where Hello, Android leaves off, it requires completion of the Hello, Android
Quickstart. If you would like to jump directly into the walkthrough below, you can download the completed
version of Phoneword (from the Hello, Android Quickstart) and use it to start the walkthrough.

Walkthrough
In this walkthrough you'll add a Translation History screen to the Phoneword application.
Visual Studio
Visual Studio for Mac
Start by opening the Phoneword application in Visual Studio and editing the Main.axml file from the Solution
Explorer.
Updating the Layout
From the Toolbox, drag a Button onto the design surface and place it below the TranslatedPhoneWord
TextView. In the Properties pane, change the button Id to @+id/TranslationHistoryButton

Set the Text property of the button to @string/translationHistory . The Android Designer will interpret this
literally, but you're going to make a few changes so that the button's text shows up correctly:

Expand the values node under the Resources folder in the Solution Explorer and double-click the string
resources file, Strings.xml:
Add the translationHistory string name and value to the Strings.xml file and save it:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="translationHistory">Translation History</string>
<string name="ApplicationName">Phoneword</string>
</resources>

The Translation History button text should update to reflect the new string value:

With the Translation History button selected on the design surface, find the enabled setting in the Properties
pane and set its value to false to disable the button. This will cause the button to become darker on the design
surface:
Creating the Second Activity
Create a second Activity to power the second screen. In the Solution Explorer, right-click the Phoneword
project and choose Add > New Item...:

In the Add New Item dialog, choose Visual C# > Activity and name the Activity file
TranslationHistoryActivity.cs.
Replace the template code in TranslationHistoryActivity.cs with the following:

using System;
using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
namespace Phoneword
{
[Activity(Label = "@string/translationHistory")]
public class TranslationHistoryActivity : ListActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
var phoneNumbers = Intent.Extras.GetStringArrayList("phone_numbers") ?? new string[0];
this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1,
phoneNumbers);
}
}
}
In this class, you're creating a ListActivity and populating it programmatically, so you don't need to create a new
layout file for this Activity. This is discussed in more detail in the Hello, Android Multiscreen Deep Dive.
Adding Translation History Code
This app collects phone numbers (that the user has translated on the first screen) and passes them to the second
screen. The phone numbers are stored as a list of strings. To support lists (and Intents, which are used later), add
the following using directives to the top of MainActivity.cs:

using System.Collections.Generic;
using Android.Content;

Next, create an empty list that can be filled with phone numbers. The MainActivity class will look like this:

[Activity(Label = "Phoneword", MainLauncher = true)]


public class MainActivity : Activity
{
static readonly List<string> phoneNumbers = new List<string>();
...// OnCreate, etc.
}

In the MainActivity class, add the following code to register the Translation History button (place this line after
the translateButton declaration):

Button translationHistoryButton = FindViewById<Button> (Resource.Id.TranslationHistoryButton);

Add the following code to the end of the OnCreate method to wire up the Translation History button:

translationHistoryButton.Click += (sender, e) =>


{
var intent = new Intent(this, typeof(TranslationHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", phoneNumbers);
StartActivity(intent);
};

Update the Translate button to add the phone number to the list of phoneNumbers . The Click handler for the
TranslateHistoryButton should resemble the following code:

// Add code to translate number


string translatedNumber = string.Empty;
translateButton.Click += (sender, e) =>
{
// Translate user's alphanumeric phone number to numeric
translatedNumber = PhonewordTranslator.ToNumber(phoneNumberText.Text);
if (string.IsNullOrWhiteSpace(translatedNumber))
{
translatedPhoneWord.Text = "";
}
else
{
translatedPhoneWord.Text = translatedNumber;
phoneNumbers.Add(translatedNumber);
translationHistoryButton.Enabled = true;
}
};

Save and build the application to make sure there are no errors.
Running the App
Deploy the application to an emulator or device. The following screenshots illustrate the running Phoneword
application:

Congratulations on completing your first multi-screen Xamarin.Android application! Now it's time to dissect the
tools and skills you just learned – next up is the Hello, Android Multiscreen Deep Dive.

Related Links
Xamarin App Icons & Launch Screens (ZIP )
Phoneword (sample)
PhonewordMultiscreen (sample)
Hello, Android Multiscreen: Deep Dive
4/12/2018 • 6 minutes to read • Edit Online

In this two -part guide, the basic Phoneword application (created in the Hello, Android guide) is expanded to
handle a second screen. Along the way, the basic Android Application Building Blocks are introduced. A deeper
dive into Android architecture is included to help you develop a better understanding of Android application
structure and functionality.

Hello, Android Multiscreen Deep Dive


In the Hello, Android Multiscreen Quickstart, you built and ran your first multi-screen Xamarin.Android
application. Now it's time to develop a deeper understanding of Android navigation and architecture so that you
can build more complex applications.
In this guide you will explore more advanced Android architecture as Android Application Building Blocks are
introduced. Android navigation with Intents is explained, and Android hardware navigation options are explored.
New additions to the Phoneword app are dissected as you develop a more holistic view of the application's
relationship with the operating system and other applications.

Android Architecture Basics


In the Hello, Android Deep Dive, you learned that Android applications are unique programs because they lack a
single entry point. Instead, the operating system (or another application) starts any one of the application's
registered Activities, which in turn starts the process for the application. This deep dive into Android architecture
expands your understanding of how Android applications are constructed by introducing the Android Application
Building Blocks and their functions.
Android Application Blocks
An Android application consists of a collection of special Android classes called Application Blocks bundled
together with any number of app resources - images, themes, helper classes, etc. – these are coordinated by an
XML file called the Android Manifest.
Application Blocks form the backbone of Android applications because they allow you to do things you couldn't
normally accomplish with a regular class. The two most important ones are Activities and Services:
Activity – An Activity corresponds to a screen with a user interface, and it is conceptually similar to a web
page in a web application. For example, in a newsfeed application, the login screen would be the first
Activity, the scrollable list of news items would be another Activity, and the details page for each item would
be a third. You can learn more about Activities in the Activity Lifecycle guide.
Service – Android Services support Activities by taking over long-running tasks and running them in the
background. Services don't have a user interface and are used to handle tasks that aren't tied to screens –
for example, playing a song in the background or uploading photos to a server. For more information about
Services, see the Creating Services and Android Services guides.
An Android application may not use all types of Blocks, and often has several Blocks of one type. For example, the
Phoneword application from the Hello, Android Quickstart was composed of just one Activity (screen) and some
resource files. A simple music player app might have several Activities and a Service for playing music when the
app is in the background.
Intents
Another fundamental concept in Android applications is the Intent. Android is designed around the principle of
least privilege – applications have access only to the Blocks they require to work, and they have limited access to
the Blocks that make up the operating system or other applications. Similarly, Blocks are loosely-coupled – they
are designed to have little knowledge of and limited access to other Blocks (even blocks that are part of the same
application).
To communicate, Application Blocks send asynchronous messages called Intents back and forth. Intents contain
information about the receiving Block and sometimes some data. An Intent sent from one App component
triggers something to happen in another App component, binding the two App components and allowing them to
communicate. By sending Intents back and forth, you can get Blocks to coordinate complex actions such as
launching the camera app to take and save, gathering location information, or navigating from one screen to the
next.
AndroidManifest.XML
When you add a Block to the application, it is registered with a special XML file called the Android Manifest. The
Manifest keeps track of all Application Blocks in an application, as well as version requirements, permissions, and
linked libraries – everything that the operating system needs to know for your application to run. The Android
Manifest also works with Activities and Intents to control what actions are appropriate for a given Activity. These
advanced features of the Android Manifest are covered in the Working with the Android Manifest guide.
In the single-screen version of the Phoneword application, only one Activity, one Intent, and the
AndroidManifest.xml were used, alongside additional resources like icons. In the multi-screen version of
Phoneword, an additional Activity was added; it was launched from the first Activity using an Intent. The next
section explores how Intents help to create navigation in Android applications.

Android Navigation
Intents were used to navigate between screens. It's time to dive into this code to see how Intents work and
understand their role in Android navigation.
Launching a Second Activity with an Intent
In the Phoneword application, an Intent was used to launch a second screen (Activity). Start by creating an Intent,
passing in the current Context ( this , referring to the current Context) and the type of Application Block that
you're looking for ( TranslationHistoryActivity ):

Intent intent = new Intent(this, typeof(TranslationHistoryActivity));

The Context is an interface to global information about the application environment – it lets newly-created
objects know what's going on with the application. If you think of an Intent as a message, you are providing the
name of the message recipient ( TranslationHistoryActivity ) and the receiver's address ( Context ).
Android provides an option to attach simple data to an Intent (complex data is handled differently). In the
Phoneword example, PutStringArrayExtra is used to attach a list of phone numbers to the Intent and
StartActivity is called on the recipient of the Intent. The completed code looks like this:

translationHistoryButton.Click += (sender, e) =>


{
var intent = new Intent(this, typeof(TranslationHistoryActivity));
intent.PutStringArrayListExtra("phone_numbers", _phoneNumbers);
StartActivity(intent);
};

Additional Concepts Introduced in Phoneword


The Phoneword application introduced several concepts not covered in this guide. These concepts include:
String Resources – In the Phoneword application, the text of the TranslationHistoryButton was set to
"@string/translationHistory" . The @string syntax means that the string's value is stored in the string resources
file, Strings.xml. The following value for the translationHistory string was added to Strings.xml:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="translationHistory">Call History</string>
</resources>

For more information on string resources and other Android resources, refer to the Android Resources guide.
ListView and ArrayAdapter – A ListView is a UI component that provides a simple way to present a scrolling list
of rows. A ListView instance requires an Adapter to feed it with data contained in row views. The following line
of code was used to populate the user interface of TranslationHistoryActivity :

this.ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, phoneNumbers);

ListViews and Adapters are beyond the scope of this document, but they are covered in the very comprehensive
ListViews and Adapters guide. Populating a ListView With Data deals specifically with using built-in ListActivity
and ArrayAdapter classes to create and populate a ListView without defining a custom layout, as was done in the
Phoneword example.

Summary
Congratulations, you've completed your first multi-screen Android application! This guide introduced Android
Application Building Blocks and Intents and used them to build a multi-screened Android application. You now
have the solid foundation you need to start developing your own Xamarin.Android applications.
Next, you'll learn to build cross-platform applications with Xamarin in the Building Cross-Platform Applications
guides.
Xamarin for Java Developers
6/20/2018 • 24 minutes to read • Edit Online

If you are a Java developer, you are well on your way to leveraging your skills and existing code on the Xamarin
platform while reaping the code reuse benefits of C#. You will find that C# syntax is very similar to Java syntax,
and that both languages provide very similar features. In addition, you'll discover features unique to C# that will
make your development life easier.

Overview
This article provides an introduction to C# programming for Java developers, focusing primarily on the C#
language features that you will encounter while developing Xamarin.Android applications. Also, this article
explains how these features differ from their Java counterparts, and it introduces important C# features (relevant
to Xamarin.Android) that are not available in Java. Links to additional reference material are included, so you can
use this article as a "jumping off" point for further study of C# and .NET.
If you are familiar with Java, you will feel instantly at home with the syntax of C#. C# syntax is very similar to Java
syntax – C# is a "curly brace" language like Java, C, and C++. In many ways, C# syntax reads like a superset of Java
syntax, but with a few renamed and added keywords.
Many key characteristics of Java can be found in C#:
Class-based object-oriented programming
Strong typing
Support for interfaces
Generics
Garbage collection
Runtime compilation
Both Java and C# are compiled to an intermediate language that is run in a managed execution environment. Both
C# and Java are statically-typed, and both languages treat strings as immutable types. Both languages use a
single-rooted class hierarchy. Like Java, C# supports only single inheritance and does not allow for global
methods. In both languages, objects are created on the heap using the new keyword, and objects are garbage-
collected when they are no longer used. Both languages provide formal exception handling support with try /
catch semantics. Both provide thread management and synchronization support.

However, there are many differences between Java and C#. For example:
Java does not support implicitly-typed local variables (C# supports the var keyword).
In Java, you can pass parameters only by value, while in C# you can pass by reference as well as by value.
(C# provides the ref and out keywords for passing parameters by reference; there is no equivalent to
these in Java).
Java does not support preprocessor directives like #define .
Java does not support unsigned integer types, while C# provides unsigned integer types such as ulong ,
uint , ushort and byte .

Java does not support operator overloading; in C# you can overload operators and conversions.
In a Java switch statement, code can fall through into the next switch section, but in C# the end of every
switch section must terminate the switch (the end of each section must close with a break statement).

In Java, you specify the exceptions thrown by a method with the throws keyword, but C# has no concept of
checked exceptions – the throws keyword is not supported in C#.
C# supports Language-Integrated Query (LINQ ), which lets you use the reserved words from , select ,
and where to write queries against collections in a way that is similar to database queries.
Of course, there are many more differences between C# and Java than can be covered in this article. Also, both
Java and C# continue to evolve (for example, Java 8, which is not yet in the Android toolchain, supports C#-style
lambda expressions) so these differences will change over time. Only the most important differences currently
encountered by Java developers new to Xamarin.Android are outlined here.
Going from Java to C# Development provides an introduction to the fundamental differences between C#
and Java.
Object-Oriented Programming Features outlines the most important object-oriented feature differences
between the two languages.
Keyword Differences provides a table of useful keyword equivalents, C#-only keywords, and links to C#
keyword definitions.
C# brings many key features to Xamarin.Android that are not currently readily available to Java developers on
Android. These features can help you to write better code in less time:
Properties – With C#'s property system, you can access member variables safely and directly without
having to write setter and getter methods.
Lambda Expressionss – In C# you can use anonymous methods (also called lambdas) to express your
functionality more succinctly and more efficiently. You can avoid the overhead of having to write one-time-
use objects, and you can pass local state to a method without having to add parameters.
Event Handling – C# provides language-level support for event-driven programming, where an object can
register to be notified when an event of interest occurs. The event keyword defines a multicast broadcast
mechanism that a publisher class can use to notify event subscribers.
Asynchronous Programming – The asynchronous programming features of C# ( async / await ) keep apps
responsive. The language-level support of this feature makes async programming easy to implement and
less error-prone.
Finally, Xamarin allows you to leverage existing Java assets via a technology known as binding. You can call your
existing Java code, frameworks, and libraries from C# by making use of Xamarin's automatic binding generators.
To do this, you simply create a static library in Java and expose it to C# via a binding.

Going From Java to C# Development


The following sections outline the basic "getting started" differences between C# and Java; a later section describes
the object-oriented differences between these languages.
Libraries vs. Assemblies
Java typically packages related classes in .jar files. In C# and .NET, however, reusable bits of precompiled code are
packaged into assemblies, which are typically packaged as .dll files. An assembly is a unit of deployment for
C#/.NET code, and each assembly is typically associated with a C# project. Assemblies contain intermediate code
(IL ) that is just-in-time compiled at runtime.
For more information about assemblies, see the MSDN Assemblies and the Global Assembly Cache topic.
Packages vs. Namespaces
C# uses the namespace keyword to group related types together; this is similar to Java's package keyword.
Typically, a Xamarin.Android app will reside in a namespace created for that app. For example, the following C#
code declares the WeatherApp namespace wrapper for a weather-reporting app:

namespace WeatherApp
{
...

Importing Types
When you make use of types defined in external namespaces, you import these types with a using statement
(which is very similar to the Java import statement). In Java, you might import a single type with a statement like
the following:

import javax.swing.JButton

You might import an entire Java package with a statement like this:

import javax.swing.*

The C# using statement works in a very similar way, but it allows you to import an entire package without
specifying a wildcard. For example, you will often see a series of using statements at the beginning of
Xamarin.Android source files, as seen in this example:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Net;
using System.IO;
using System.Json;
using System.Threading.Tasks;

These statements import functionality from the System , Android.App , Android.Content , etc. namespaces.
Generics
Both Java and C# support generics, which are placeholders that let you plug in different types at compile time.
However, generics work slightly differently in C#. In Java, type erasure makes type information available only at
compile time, but not at run time. By contrast, the .NET common language runtime (CLR ) provides explicit support
for generic types, which means that C# has access to type information at runtime. In day-to-day Xamarin.Android
development, the importantance of this distinction is not often apparent, but if you are using reflection, you will
depend on this feature to access type information at run time.
In Xamarin.Android, you will often see the generic method FindViewById used to get a reference to a layout
control. This method accepts a generic type parameter that specifies the type of control to look up. For example:

TextView label = FindViewById<TextView> (Resource.Id.Label);

In this code example, FindViewById gets a reference to the TextView control that is defined in the layout as Label,
then returns it as a TextView type.
For more information about generics, see the MSDN Generics topic. Note that there are some limitations in
Xamarin.Android support for generic C# classes; for more information, see Limitations.

Object-Oriented Programming Features


Both Java and C# use very similar object-oriented programming idioms:
All classes are ultimately derived from a single root object – all Java objects derive from java.lang.Object ,
while all C# objects derive from System.Object .
Instances of classes are reference types.
When you access the properties and methods of an instance, you use the " . " operator.
All class instances are created on the heap via the new operator.
Because both languages use garbage collection, there is way to explicitly release unused objects (i.e., there is
not a delete keyword as there is in C++).
You can extend classes through inheritance, and both languages only allow a single base class per type.
You can define interfaces, and a class can inherit from (i.e., implement) multiple interface definitions.
However, there are also some important differences:
Java has two powerful features that C# does not support: anonymous classes and inner classes. (However,
C# does allow nesting of class definitions – C#'s nested classes are like Java's static nested classes.)
C# supports C -style structure types ( struct ) while Java does not.
In C#, you can implement a class definition in separate source files by using the partial keyword.
C# interfaces cannot declare fields.
C# uses C++-style destructor syntax to express finalizers. The syntax is different from Java's finalize
method, but the semantics are nearly the same. (Note that in C#, destructors automatically call the base-
class destructor – in contrast to Java where an explicit call to super.finalize is used.)
Class Inheritance
To extend a class in Java, you use the extends keyword. To extend a class in C#, you use a colon ( : ) to indicate
derivation. For example, in Xamarin.Android apps, you will often see class derivations that resemble the following
code fragment:

public class MainActivity : Activity


{
...

In this example, MainActivity inherits from the Activity class.


To declare support for an interface in Java, you use the implements keyword. However, in C#, you simply add
interface names to the list of classes to inherit from, as shown in this code fragment:

public class SensorsActivity : Activity, ISensorEventListener


{
...

In this example, SensorsActivity inherits from Activity and implements the functionality declared in the
ISensorEventListener interface. Note that the list of interfaces must come after the base class (or you will get a
compile-time error). By convention, C# interface names are prepended with an upper-case "I"; this makes it
possible to determine which classes are interfaces without requiring an implements keyword.
When you want to prevent a class from being further subclassed in C#, you precede the class name with sealed –
in Java, you precede the class name with final .
For more about C# class definitions, see the MSDN Classes and Structs and Inheritance topics.
Properties
In Java, mutator methods (setters) and inspector methods (getters) are often used to control how changes are
made to class members while hiding and protecting these members from outside code. For example, the Android
TextView class provides getText and setText methods. C# provides a similar but more direct mechanism known
as properties. Users of a C# class can access a property in the same way as they would access a field, but each
access actually results in a method call that is transparent to the caller. This "under the covers" method can
implement side effects such as setting other values, performing conversions, or changing object state.
Properties are often used for accessing and modifying UI (user interface) object members. For example:

int width = rulerView.MeasuredWidth;


int height = rulerView.MeasuredHeight;
...
rulerView.DrawingCacheEnabled = true;

In this example, width and height values are read from the rulerView object by accessing its MeasuredWidth and
MeasuredHeight properties. When these properties are read, values from their associated (but hidden) field values
are fetched behind the scenes and returned to the caller. The rulerView object may store width and height values
in one unit of measurement (say, pixels) and convert these values on-the-fly to a different unit of measurement
(say, millimeters) when the MeasuredWidth and MeasuredHeight properties are accessed.
The rulerView object also has a property called DrawingCacheEnabled – the example code sets this property to
true to enable the drawing cache in rulerView . Behind the scenes, an associated hidden field is updated with the
new value, and possibly other aspects of rulerView state are modified. For example, when DrawingCacheEnabled is
set to false , rulerView may also erase any drawing cache information already accumulated in the object.
Access to properties can be read/write, read-only, or write-only. Also, you can use different access modifiers for
reading and writing. For example, you can define a property that has public read access but private write access.
For more information about C# properties, see the MSDN Properties topic.
Calling Base Class Methods
To call a base-class constructor in C#, you use a colon ( : ) followed by the base keyword and an initializer list;
this base constructor call is placed immediately after the derived constructor parameter list. The base-class
constructor is called on entry to the derived constructor; the compiler inserts the call to the base constructor at the
start of the method body. The following code fragment illustrates a base constructor called from a derived
constructor in a Xamarin.Android app:
public class PictureLayout : ViewGroup
{
...
public class PictureLayout (Context context)
: base (context)
{
...
}
...
}

In this example, the PictureLayout class is derived from the ViewGroup class. The PictureLayout constructor
shown in this example accepts a context argument and passes it to the ViewGroup constructor via the
base(context) call.

To call a base-class method in C#, use the base keyword. For example, Xamarin.Android apps often make calls to
base methods as shown here:

public class MainActivity : Activity


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

In this case, the OnCreate method defined by the derived class ( MainActivity ) calls the OnCreate method of the
base class ( Activity ).
Access Modifiers
Java and C# both support the public , private , and protected access modifiers. However, C# supports two
additional access modifiers:
internal – The class member is accessible only within the current assembly.
protected internal – The class member is accessible within the defining assembly, the defining class, and
derived classes (derived classes both inside and outside the assembly have access).
For more information about C# access modifiers, see the MSDN Access Modifiers topic.
Virtual and Override Methods
Both Java and C# support polymorphism, the ability to treat related objects in the same manner. In both
languages, you can use a base-class reference to refer to a derived-class object, and the methods of a derived class
can override the methods of its base classes. Both languages have the concept of a virtual method, a method in a
base class that is designed to be replaced by a method in a derived class. Like Java, C# supports abstract classes
and methods.
However, there are some differences between Java and C# in how you declare virtual methods and override them:
In C#, methods are non-virtual by default. Parent classes must explicitly label which methods are to be
overridden by using the virtual keyword. By contrast, all methods in Java are virtual methods by default.
To prevent a method from being overridden in C#, you simply leave off the virtual keyword. By contrast,
Java uses the final keyword to mark a method with "override is not allowed."
C# derived classes must use the override keyword to explicitly indicate that a virtual base-class method is
being overridden.
For more information about C#'s support for polymorphism, see the MSDN Polymorphism topic.

Lambda Expressions
C# makes it possible to create closures: inline, anonymous methods that can access the state of the method in
which they are enclosed. Using lambda expressions, you can write fewer lines of code to implement the same
functionality that you might have implemented in Java with many more lines of code.
Lambda expressions make it possible for you to skip the extra ceremony involved in creating a one-time-use class
or anonymous class as you would in Java – instead, you can just write the business logic of your method code
inline. Also, because lambdas have access to the variables in the surrounding method, you don't have to create a
long parameter list to pass state to your method code.
In C#, lambda expressions are created with the => operator as shown here:

(arg1, arg2, ...) => {


// implementation code
};

In Xamarin.Android, lambda expressions are often used for defining event handlers. For example:

button.Click += (sender, args) => {


clickCount += 1; // access variable in surrounding code
button.Text = string.Format ("Clicked {0} times.", clickCount);
};

In this example, the lambda expression code (the code within the curly braces) increments a click count and
updates the button text to display the click count. This lambda expression is registered with the button object as
a click event handler to be called whenever the button is tapped. (Event handlers are explained in more detail
below.) In this simple example, the sender and args parameters are not used by the lambda expression code, but
they are required in the lambda expression to meet the method signature requirements for event registration.
Under the hood, the C# compiler translates the lambda expression into an anonymous method that is called
whenever button click events take place.
For more information about C# and lambda expressions, see the MSDN Lambda Expressions topic.

Event Handling
An event is a way for an object to notify registered subscribers when something interesting happens to that object.
Unlike in Java, where a subscriber typically implements a Listener interface that contains a callback method, C#
provides language-level support for event handling through delegates. A delegate is like an object-oriented type-
safe function pointer – it encapsulates an object reference and a method token. If a client object wants to subscribe
to an event, it creates a delegate and passes the delegate to the notifying object. When the event occurs, the
notifying object invokes the method represented by the delegate object, notifying the subscribing client object of
the event. In C#, event handlers are essentially nothing more than methods that are invoked through delegates.
For more information about delegates, see the MSDN Delegates topic.
In C#, events are multicast; that is, more than one listener can be notified when an event takes place. This
difference is observed when you consider the syntactical differences between Java and C# event registration. In
Java you call SetXXXListener to register for event notifications; in C# you use the += operator to register for
event notifications by "adding" your delegate to the list of event listeners. In Java, you call SetXXXListener to
unregister, while in C# you use the -= to "subtract" your delegate from the list of listeners.
In Xamarin.Android, events are often used for notifying objects when a user does something to a UI control.
Normally, a UI control will have members that are defined using the event keyword; you attach your delegates to
these members to subscribe to events from that UI control.
To subscribe to an event:
1. Create a delegate object that refers to the method that you want to be invoked when the event occurs.
2. Use the += operator to attach your delegate to the event you are subscribing to.

The following example defines a delegate (with an explicit use of the delegate keyword) to subscribe to button
clicks. This button-click handler starts a new activity:

startActivityButton.Click += delegate {
Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};

However, you also can use a lambda expression to register for events, skipping the delegate keyword altogether.
For example:

startActivityButton.Click += (sender, e) => {


Intent intent = new Intent (this, typeof (MyActivity));
StartActivity (intent);
};

In this example, the startActivityButton object has an event that expects a delegate with a certain method
signature: one that accepts sender and event arguments and returns void. However, because we don't want to go to
the trouble to explicitly define such a delegate or its method, we declare the signature of the method with
(sender, e) and use a lambda expression to implement the body of the event handler. Note that we have to
declare this parameter list even though we aren't using the sender and e parameters.
It is important to remember that you can unsubscribe a delegate (via the -= operator), but you cannot
unsubscribe a lambda expression – attempting to do so can cause memory leaks. Use the lambda form of event
registration only when your handler will not unsubscribe from the event.
Typically, lambda expressions are used to declare event handlers in Xamarin.Android code. This shorthand way to
declare event handlers may seem cryptic at first, but it saves an enormous amount of time when you are writing
and reading code. With increasing familiarity, you become accustomed to recognizing this pattern (which occurs
frequently in Xamarin.Android code), and you spend more time thinking about the business logic of your
application and less time wading through syntactical overhead.

Asynchronous Programming
Asynchronous programming is a way to improve the overall responsiveness of your application. Asynchronous
programming features make it possible for the rest of your app code to continue running while some part of your
app is blocked by a lengthy operation. Accessing the web, processing images, and reading/writing files are
examples of operations that can cause an entire app to appear to freeze up if it is not written asynchronously.
C# includes language-level support for asynchronous programming via the async and await keywords. These
language features make it very easy to write code that performs long-running tasks without blocking the main
thread of your application. Briefly, you use the async keyword on a method to indicate that the code in the
method is to run asynchronously and not block the caller's thread. You use the await keyword when you call
methods that are marked with async . The compiler interprets the await as the point where your method
execution is to be moved to a background thread (a task is returned to the caller). When this task completes,
execution of the code resumes on the caller's thread at the await point in your code, returning the results of the
async call. By convention, methods that run asynchronously have Async suffixed to their names.

In Xamarin.Android applications, async and await are typically used to free up the UI thread so that it can
respond to user input (such as the tapping of a Cancel button) while a long-running operation takes place in a
background task.
In the following example, a button click event handler causes an asynchronous operation to download an image
from the web:

downloadButton.Click += downloadAsync;
...
async void downloadAsync(object sender, System.EventArgs e)
{
webClient = new WebClient ();
var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
byte[] bytes = null;

bytes = await webClient.DownloadDataTaskAsync(url);

// display the downloaded image ...

In this example, when the user clicks the downloadButton control, the downloadAsync event handler creates a
WebClient object and a Uri object to fetch an image from the specifed URL. Next, it calls the WebClient object's
DownloadDataTaskAsync method with this URL to retrieve the image.

Notice that the method declaration of downloadAsync is prefaced by the async keyword to indicate that it will run
asynchronously and return a task. Also note that the call to DownloadDataTaskAsync is preceded by the await
keyword. The app moves the execution of the event handler (starting at the point where await appears) to a
background thread until DownloadDataTaskAsync completes and returns. Meanwhile, the app's UI thread can still
respond to user input and fire event handlers for the other controls. When DownloadDataTaskAsync completes
(which may take several seconds), execution resumes where the bytes variable is set to the result of the call to
DownloadDataTaskAsync , and the remainder of the event handler code displays the downloaded image on the
caller's (UI) thread.
For an introduction to async / await in C#, see the MSDN Asynchronous Programming with Async and Await
topic. For more information about Xamarin support of asynchronous programming features, see Async Support
Overview.

Keyword Differences
Many language keywords used in Java are also used in C#. There are also a number of Java keywords that have an
equivalent but differently-named counterpart in C#, as listed in this table:

JAVA C# DESCRIPTION

boolean bool Used for declaring the boolean values


true and false.

extends : Precedes the class and interfaces to


inherit from.

implements : Precedes the class and interfaces to


inherit from.
JAVA C# DESCRIPTION

import using Imports types from a namespace, also


used for creating a namespace alias.

final sealed Prevents class derivation; prevents


methods and properties from being
overridden in derived classes.

instanceof is Evaluates whether an object is


compatible with a given type.

native extern Declares a method that is implemented


externally.

package namespace Declares a scope for a related set of


objects.

T... params T Specifies a method parameter that


takes a variable number of arguments.

super base Used to access members of the parent


class from within a derived class.

synchronized lock Wraps a critical section of code with


lock acquisition and release.

Also, there are many keywords that are unique to C# and have no counterpart in Java. Xamarin.Android code
often makes use of the following C# keywords (this table is useful to refer to when you are reading through
Xamarin.Android sample code):

C# DESCRIPTION

as Performs conversions between compatible reference types or


nullable types.

async Specifies that a method or lambda expression is asynchronous.

await Suspends the execution of a method until a task completes.

byte Unsigned 8-bit integer type.

delegate Used to encapsulate a method or anonymous method.

enum Declares an enumeration, a set of named constants.

event Declares an event in a publisher class.

fixed Prevents a variable from being relocated.

get Defines an accessor method that retrieves the value of a


property.
C# DESCRIPTION

in Enables a parameter to accept a less derived type in a generic


interface.

object An alias for the Object type in the .NET framework.

out Parameter modifier or generic type parameter declaration.

override Extends or modifies the implementation of an inherited


member.

partial Declares a definition to be split into multiple files, or splits a


method definition from its implementation.

readonly Declares that a class member can be assigned only at


declaration time or by the class constructor.

ref Causes an argument to be passed by reference rather than by


value.

set Defines an accessor method that sets the value of a property.

string Alias for the String type in the .NET framework.

struct A value type that encapsulates a group of related variables.

typeof Obtains the type of an object.

var Declares an implicitly-typed local variable.

value References the value that client code wants to assign to a


property.

virtual Allows a method to be overridden in a derived class.

Interoperating with Existing Java Code


If you have existing Java functionality that you do not want to convert to C#, you can reuse your existing Java
libraries in Xamarin.Android applications via two techniques:
Create a Java Bindings Library – Using this approach, you use Xamarin tools to generate C# wrappers
around Java types. These wrappers are called bindings. As a result, your Xamarin.Android application can
use your .jar file by calling into these wrappers.
Java Native Interface – The Java Native Interface (JNI) is a framework that makes it possible for C# apps
to call or be called by Java code.
For more information about these techniques, see Java Integration Overview.

For Further Reading


The MSDN C# Programming Guide is a great way to get started in learning the C# programming language, and
you can use the C# Reference to look up particular C# language features.
In the same way that Java knowledge is at least as much about familiarity with the Java class libraries as knowing
the Java language, practical knowledge of C# requires some familiarity with the .NET framework. Microsoft's
Moving to C# and the .NET Framework, for Java Developers learning packet is a good way to learn more about
the .NET framework from a Java perspective (while gaining a deeper understanding of C#).
When you are ready to tackle your first Xamarin.Android project in C#, our Hello, Android series can help you
build your first Xamarin.Android application and further advance your understanding of the fundamentals of
Android application development with Xamarin.

Summary
This article provided an introduction to the Xamarin.Android C# programming environment from a Java
developer's perspective. It pointed out the similarities between C# and Java while explaining their practical
differences. It introduced assemblies and namespaces, explained how to import external types, and provided an
overview of the differences in access modifiers, generics, class derivation, calling base-class methods, method
overriding, and event handling. It introduced C# features that are not available in Java, such as properties, async /
await asynchronous programming, lambdas, C# delegates, and the C# event handling system. It included tables
of important C# keywords, explained how to interoperate with existing Java libraries, and provided links to related
documentation for further study.

Related Links
Java Integration Overview
C# Programming Guide
C# Reference
Moving to C# and the .NET Framework, for Java Developers
Xamarin.Android Application Fundamentals
5/2/2018 • 3 minutes to read • Edit Online

This section provides a guide on some of the more common things tasks or concepts that developers need to be
aware of when developing Android applications.

Accessibility
This page describes how to use the Android Accessibility APIs to build apps according to the accessibility checklist.

Understanding Android API Levels


This guide describes how Android uses API levels to manage app compatibility across different versions of
Android, and it explains how to configure Xamarin.Android project settings to deploy these API levels in your app.
In addition, this guide explains how to write runtime code that deals with different API levels, and it provides a
reference list of all Android API levels, version numbers (such as Android 8.0), Android code names (such as Oreo),
and build version codes.

Resources in Android
This article introduces the concept of Android resources in Xamarin.Android and documents how to use them. It
covers how to use resources in your Android application to support application localization, and multiple devices
including varying screen sizes and densities.

Activity Lifecycle
Activities are a fundamental building block of Android Applications and they can exist in a number of different
states. The activity lifecycle begins with instantiation and ends with destruction, and includes many states in
between. When an activity changes state, the appropriate lifecycle event method is called, notifying the activity of
the impending state change and allowing it to execute code to adapt to that change. This article examines the
lifecycle of activities and explains the responsibility that an activity has during each of these state changes to be
part of a well-behaved, reliable application.

Localization
This article explains how to localize a Xamarin.Android into other languages by translating strings and providing
alternate images.

Services
This article covers Android services, which are Android components that allow work to be done in the background.
It explains the different scenarios that services are suited for and shows how to implement them both for
performing long-running background tasks as well as to provide an interface for remote procedure calls.

Broadcast Receivers
This guide covers how to create and use broadcast receivers, an Android component that responds to system-wide
broadcasts, in Xamarin.Android.
Permissions
You can use the tooling support built into Visual Studio for Mac or Visual Studio to create and add permissions to
the Android Manifest. This document describes how to add permissions in Visual Studio and Xamarin Studio.

Graphics and Animation


Android provides a very rich and diverse framework for supporting 2D graphics and animations. This document
introduces these frameworks and discusses how to create custom graphics and animations and use them in a
Xamarin.Android application.

CPU Architectures
Xamarin.Android supports several CPU architectures, including 32-bit and 64-bit devices. This article explains how
to target an app to one or more Android-supported CPU architectures.

Handling Rotation
This article describes how to handle device orientation changes in Xamarin.Android. It covers how to work with the
Android resource system to automatically load resources for a particular device orientation as well as how to
programmatically handle orientation changes. Then it describes techniques for maintaining state when a device is
rotated.

Android Audio
The Android OS provides extensive support for multimedia, encompassing both audio and video. This guide
focuses on audio in Android and covers playing and recording audio using the built-in audio player and recorder
classes, as well as the low -level audio API. It also covers working with Audio events broadcast by other
applications, so that developers can build well-behaved applications.

Notifications
This section explains how to implement local and remote notifications in Xamarin.Android. It describes the various
UI elements of an Android notification and discusses the API's involved with creating and displaying a notification.
For remote notifications, both Google Cloud Messaging and Firebase Cloud Messaging are explained. Step-by-
step walkthroughs and code samples are included.

Touch
This section explains the concepts and details of implementing touch gestures on Android. Touch APIs are
introduced and explained followed by an exploration of gesture recognizers.

HttpClient Stack and SSL/TLS


This section explains the HttpClient Stack and SSL/TLS Implementation selectors for Android. These settings
determine the HttpClient and SSL/TLS implementation that will be used by your Xamarin.Android apps.

Writing Responsive Applications


This article discusses how to use threading to keep a Xamarin.Android application responsive by moving long-
running tasks on to a background thread.
Accessibility on Android
4/12/2018 • 3 minutes to read • Edit Online

This page describes how to use the Android Accessibility APIs to build apps according to the accessibility checklist.
Refer to the iOS accessibility and OS X accessibility pages for other platform APIs.

Describing UI Elements
Android provides a ContentDescription property that is used by screen reading APIs to provide an accessible
description of the control's purpose.
The content description can be set in either C# or in the AXML layout file.
C#
The description can be set in code to any string (or a string resource):

saveButton.ContentDescription = "Save data";

AXML layout
In XML layouts use the android:contentDescription attribute:

<ImageButton
android:id=@+id/saveButton"
android:src="@drawable/save_image"
android:contentDescription="Save data" />

Use Hint for TextView


For EditText and TextView controls for data input, use the Hint property to provide a description of what input
is expected (instead of ContentDescription ). When some text has been entered, the text itself will be "read" instead
of the hint.
C#
Set the Hint property in code:

someText.Hint = "Enter some text"; // displays (and is "read") when control is empty

AXML layout
In XML layout files use the android:hint attribute:

<EditText
android:id="@+id/someText"
android:hint="Enter some text" />

LabelFor links input fields with labels


To associate a label with a data input control, use the LabelFor property to
C#
In C#, set the LabelFor property to the resource ID of the control this this content describes (typically this
property is set on a label and references some other input control):

EditText edit = FindViewById<EditText> (Resource.Id.editFirstName);


TextView tv = FindViewById<TextView> (Resource.Id.labelFirstName);
tv.LabelFor = Resource.Id.editFirstName;

AXML layout
In layout XML use the android:labelFor property to reference another control's identifier:

<TextView
android:id="@+id/labelFirstName"
android:hint="Enter some text"
android:labelFor="@+id/editFirstName" />
<EditText
android:id="@+id/editFirstName"
android:hint="Enter some text" />

Announce for Accessibility


Use the AnnounceForAccessibility method on any view control to communicate an event or status change to users
when accessibility is enabled. This method isn't required for most operations where the built-in narration provides
sufficient feedback, but should be used where additional information would be helpful for the user.
The code below shows a simple example calling AnnounceForAccessibility :

button.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
button.AnnounceForAccessibility (button.Text);
};

Changing Focus Settings


Accessible navigation relies on controls having focus to aid the user in understanding what operations are
available. Android provides a Focusable property which can tag controls as specifically able to receive focus
during navigation.
C#
To prevent a control from gaining focus with C#, set the Focusable property to false :

label.Focusable = false;

AXML layout
In layout XML files set the android:focusable attribute:

<android:focusable="false" />

You can also control focus order with the nextFocusDown , nextFocusLeft , nextFocusRight , nextFocusUp attributes,
typically set in the layout AXML. Use these attributes to ensure the user can navigate easily through the controls
on the screen.
Accessibility and Localization
In the examples above the hint and content description are set directly to the display value. It is preferable to use
values in a Strings.xml file, such as this:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="enter_info">Enter some text</string>
<string name="save_info">Save data</string>
</resources>

Using text from a strings file is shown below in C# and AXML layout files:
C#
Instead of using string literals in code, look up translated values from strings files with Resources.GetText :

someText.Hint = Resources.GetText (Resource.String.enter_info);


saveButton.ContentDescription = Resources.GetText (Resource.String.save_info);

AXML
In layout XML accessibility attributes like hint and contentDescription can be set to a string identifier:

<TextView
android:id="@+id/someText"
android:hint="@string/enter_info" />
<ImageButton
android:id=@+id/saveButton"
android:src="@drawable/save_image"
android:contentDescription="@string/save_info" />

The benefit of storing text in a separate file is multiple language translations of the file can be provided in your app.
See the Android localization guide to learn how add localized string files to an application project.

Testing Accessibility
Follow these steps to enable TalkBack and Explore by Touch to test accessibility on Android devices.
You may need to install TalkBack from Google Play if it does not appear in Settings > Accessibility.

Related Links
Cross-platform Accessibility
Android Accessibility APIs
Understanding Android API Levels
7/3/2018 • 18 minutes to read • Edit Online

Xamarin.Android has several Android API level settings that determine your app's compatibility with multiple
versions of Android. This guide explains what these settings mean, how to configure them, and what effect they
have on your app at run time.

Quick Start
Xamarin.Android exposes three Android API level project settings:
Target Framework – Specifies which framework to use in building your application. This API level is used
at compile time by Xamarin.Android.
Minimum Android Version – Specifies the oldest Android version that you want your app to support.
This API level is used at run time by Android.
Target Android Version – Specifies the version of Android that your app is intended to run on. This API
level is used at run time by Android.
Before you can configure an API level for your project, you must install the SDK platform components for that
API level. For more information about downloading and installing Android SDK components, see Android SDK
Setup.

NOTE
Beginning in August 2018, the Google Play Console will require that new apps target API level 26 (Android 8.0) or higher.
Existing apps will be required to target API level 26 or higher beginning in November 2018. For more information, see
Improving app security and performance on Google Play for years to come.

Visual Studio
Visual Studio for Mac
Normally, all three Xamarin.Android API levels are set to the same value. On the Application page, set
Compile using Android version (Target Framework) to the latest stable API version (or, at a minimum, to
the Android version that has all of the features you need). In the following screenshot, the Target Framework is
set to Android 7.1 (API Level 25 - Nougat):
On the Android Manifest page, set the Minimum Android version to Use Compile using SDK version and
set the Target Android version to the same value as the Target Framework version (in the following screenshot,
the Target Android Framework is set to Android 7.1 (Nougat)):

If you want to maintain backward compatibility with an earlier version of Android, set Minimum Android
version to target to the oldest version of Android that you want your app to support. (Note that API Level 14
is the minimum API level required for Google Play services and Firebase support.) The following example
configuration supports Android versions from API Level 14 thru API level 25:
If your app supports multiple Android versions, your code must include runtime checks to ensure that your app
works with the Minimum Android version setting (see Runtime Checks for Android Versions below for details).
If you are consuming or creating a library, see API Levels and Libraries below for best practices in configuring
API level settings for libraries.

Android Versions and API Levels


As the Android platform evolves and new Android versions are released, each Android version is assigned a
unique integer identifier, called the API Level. Therefore, each Android version corresponds to a single Android
API Level. Because users install apps on older as well as the most recent versions of Android, real-world
Android apps must be designed to work with multiple Android API levels.
Android Versions
Each release of Android goes by multiple names:
The Android version, such as Android 7.1
A code name, such as Nougat
A corresponding API level, such as API level 25
An Android code name may correspond to multiple versions and API levels (as seen in the list below ), but each
Android version corresponds to exactly one API level.
In addition, Xamarin.Android defines build version codes that map to the currently known Android API levels.
The following list can help you translate between API level, Android version, code name, and Xamarin.Android
build version code.
API 27 (Android 8.1) – Oreo, released December 2017. Build version code
Android.OS.BuildVersionCodes.OMr1

API 26 (Android 8.0) – Oreo, released August 2017. Build version code Android.OS.BuildVersionCodes.O

API 25 (Android 7.1) – Nougat, released December 2016. Build version code
Android.OS.BuildVersionCodes.NMr1

API 24 (Android 7.0) – Nougat, released August 2016. Build version code
Android.OS.BuildVersionCodes.N

API 23 (Android 6.0) – Marshmallow, released August 2015. Build version code
Android.OS.BuildVersionCodes.M
API 22 (Android 5.1) – Lollipop, released March 2015. Build version code
Android.OS.BuildVersionCodes.LollipopMr1

API 21 (Android 5.0) – Lollipop, released November 2014. Build version code
Android.OS.BuildVersionCodes.Lollipop

API 20 (Android 4.4W ) – Kitkat Watch, released June 2014. Build version code
Android.OS.BuildVersionCodes.KitKatWatch

API 19 (Android 4.4) – Kitkat, released October 2013. Build version code
Android.OS.BuildVersionCodes.KitKat

API 18 (Android 4.3) – Jelly Bean, released July 2013. Build version code
Android.OS.BuildVersionCodes.JellyBeanMr2

API 17 (Android 4.2-4.2.2) – Jelly Bean, released November 2012. Build version code
Android.OS.BuildVersionCodes.JellyBeanMr1

API 16 (Android 4.1-4.1.1) – Jelly Bean, released June 2012. Build version code
Android.OS.BuildVersionCodes.JellyBean

API 15 (Android 4.0.3-4.0.4) – Ice Cream Sandwich, released December 2011. Build version code
Android.OS.BuildVersionCodes.IceCreamSandwichMr1

API 14 (Android 4.0-4.0.2) – Ice Cream Sandwich, released October 2011. Build version code
Android.OS.BuildVersionCodes.IceCreamSandwich

API 13 (Android 3.2) – Honeycomb, released June 2011. Build version code
Android.OS.BuildVersionCodes.HoneyCombMr2

API 12 (Android 3.1.x) – Honeycomb, released May 2011. Build version code
Android.OS.BuildVersionCodes.HoneyCombMr1

API 11 (Android 3.0.x) – Honeycomb, released February 2011. Build version code
Android.OS.BuildVersionCodes.HoneyComb

API 10 (Android 2.3.3-2.3.4) – Gingerbread, released February 2011. Build version code
Android.OS.BuildVersionCodes.GingerBreadMr1

API 9 (Android 2.3-2.3.2) – Gingerbread, released November 2010. Build version code
Android.OS.BuildVersionCodes.GingerBread

API 8 (Android 2.2.x) – Froyo, released June 2010. Build version code
Android.OS.BuildVersionCodes.Froyo

API 7 (Android 2.1.x) – Eclair, released January 2010. Build version code
Android.OS.BuildVersionCodes.EclairMr1

API 6 (Android 2.0.1) – Eclair, released December 2009. Build version code
Android.OS.BuildVersionCodes.Eclair01

API 5 (Android 2.0) – Eclair, released November 2009. Build version code
Android.OS.BuildVersionCodes.Eclair

API 4 (Android 1.6) – Donut, released September 2009. Build version code
Android.OS.BuildVersionCodes.Donut

API 3 (Android 1.5) – Cupcake, released May 2009. Build version code
Android.OS.BuildVersionCodes.Cupcake
API 2 (Android 1.1) – Base, released February 2009. Build version code
Android.OS.BuildVersionCodes.Base11

API 1 (Android 1.0) – Base, released October 2008. Build version code
Android.OS.BuildVersionCodes.Base

As this list indicates, new Android versions are released frequently – sometimes several releases per year. As a
result, the universe of Android devices that might run your app includes of a wide variety of older and newer
Android versions. How can you guarantee that your app will run consistently and reliably on so many different
versions of Android? Android's API levels can help you manage this problem.
Android API Levels
Each Android device runs at exactly one API level – this API level is guaranteed to be unique per Android
platform version. The API level precisely identifies the version of the API set that your app can call into; it
identifies the combination of manifest elements, permissions, etc. that you code against as a developer.
Android's system of API levels helps Android determine whether an application is compatible with an Android
system image prior to installing the application on a device.
When an application is built, it contains the following API level information:
The target API level of Android that the app is built to run on.
The minimum Android API level that an Android device must have to run your app.
These settings are used to ensure that the functionality needed to run the app correctly is available on the
Android device at installation time. If not, the app is blocked from running on that device. For example, if the API
level of an Android device is lower than the minimum API level that you specify for your app, the Android
device will prevent the user from installing your app.

Project API Level Settings


The following sections explain how to use the SDK Manager to prepare your development environment for the
API levels you want to target, followed by detailed explanations of how to configure Target Framework,
Minimum Android version, and Target Android version settings in Xamarin.Android.
Android SDK Platforms
Before you can select a Target or Minimum API level in Xamarin.Android, you must install the Android SDK
platform version that corresponds to that API level. The range of available choices for Target Framework,
Minimum Android version, and Target Android version is limited to the range of Android SDK versions that you
have installed. You can use the SDK Manager to verify that the required Android SDK versions are installed, and
you can use it to add any new API levels that you need for your app. If you are not familiar with how to install
API levels, see Android SDK Setup.
Target Framework
The Target Framework (also known as compileSdkVersion ) is the specific Android framework version (API level)
that your app is compiled for at build time. This setting specifies what APIs your app expects to use when it runs,
but it has no effect on which APIs are actually available to your app when it is installed. As a result, changing the
Target Framework setting does not change runtime behavior.
The Target Framework identifies which library versions your application is linked against – this determines
which APIs you can use in your app. For example, if you want to use the NotificationBuilder.SetCategory
method that was introduced in Android 5.0 Lollipop, you must set the Target Framework to API Level 21
(Lollipop) or later. If you set your project's Target Framework to an API level such as API Level 19 (KitKat)
and try to call the SetCategory method in your code, you will get a compile error.
We recommend that you always compile with the latest available Target Framework version. Doing so provides
you with helpful warning messages for any deprecated APIs that might be called by your code. Using the latest
Target Framework version is especially important when you use the latest support library releases – each library
expects your app to be compiled at that support library's minimum API level or greater.
Visual Studio
Visual Studio for Mac
To access the Target Framework setting in Visual Studio, open the project properties in Solution Explorer and
select the Application page:

Set the Target Framework by selecting an API level in the drop-down menu under Compile using Android
version as shown above.
Minimum Android Version
The Minimum Android version (also known as minSdkVersion ) is the oldest version of the Android OS (i.e., the
lowest API level) that can install and run your application. By default, an app can only be installed on devices
matching the Target Framework setting or higher; if the Minimum Android version setting is lower than the
Target Framework setting, your app can also run on earlier versions of Android. For example, if you set the
Target Framework to Android 7.1 (Nougat) and set the Minimum Android version to Android 4.0.3 (Ice
Cream Sandwich), your app can be installed on any platform from API level 15 to API level 25, inclusive.
Although your app may successfully build and install on this range of platforms, this does not guarantee that it
will successfully run on all of these platforms. For example, if your app is installed on Android 5.0 (Lollipop)
and your code calls an API that is available only in Android 7.1 (Nougat) and newer, your app will get a
runtime error and possibly crash. Therefore, your code must ensure – at runtime – that it calls only those APIs
that are supported by the Android device that it is running on. In other words, your code must include explicit
runtime checks to ensure that your app uses newer APIs only on devices that are recent enough to support
them. Runtime Checks for Android Versions, later in this guide, explains how to add these runtime checks to
your code.
Visual Studio
Visual Studio for Mac
To access the Minimum Android version setting in Visual Studio, open the project properties in Solution
Explorer and select the Android Manifest page. In the drop-down menu under Minimum Android version
you can select the Minimum Android version for your application:
If you select Use Compile using SDK version, the Minimum Android version will be the same as the Target
Framework setting.
Target Android Version
The Target Android Version (also known as targetSdkVersion ) is the API level of the Android device where the
app expects to run. Android uses this setting to determine whether to enable any compatibility behaviors – this
ensures that your app continues to work the way you expect. Android uses the Target Android version setting of
your app to figure out which behavior changes can be applied to your app without breaking it (this is how
Android provides forward compatibility).
The Target Framework and the Target Android version, while having very similar names, are not the same thing.
The Target Framework setting communicates target API level information to Xamarin.Android for use at
compile time, while the Target Android version communicates target API level information to Android for use at
run time (when the app is installed and running on a device).
Visual Studio
Visual Studio for Mac
To access this setting in Visual Studio, open the project properties in Solution Explorer and select the Android
Manifest page. In the drop-down menu under Target Android version you can select the Target Android
version for your application:
We recommend that you explicitly set the Target Android version to the latest version of Android that you use to
test your app. Ideally, it should be set to the latest Android SDK version – this allows you to use new APIs prior
to working through the behavior changes. For most developers, we do not recommend setting the Target
Android version to Use Compile using SDK version.
In general, the Target Android Version should be bounded by the Minimum Android Version and the Target
Framework. That is:
Minimum Android Version <= Target Android Version <= Target Framework
For more information about SDK levels, see the Android Developer uses-sdk documentation.

Runtime Checks for Android Versions


As each new version of Android is released, the framework API is updated to provide new or replacement
functionality. With few exceptions, API functionality from earlier Android versions is carried forward into newer
Android versions without modifications. As a result, if your app runs on a particular Android API level, it will
typically be able to run on a later Android API level without modifications. But what if you also want to run your
app on earlier versions of Android?
If you select a Minimum Android version that is lower than your Target Framework setting, some APIs may not
be available to your app at runtime. However, your app can still run on an earlier device, but with reduced
functionality. For each API that is not available on Android platforms corresponding to your Minimum Android
version setting, your code must explicitly check the value of the Android.OS.Build.VERSION.SdkInt property to
determine the API level of the platform the app is running on. If the API level is lower than the Minimum
Android version that supports the API you want to call, then your code has to find a way to function properly
without making this API call.
For example, let's suppose that we want to use the NotificationBuilder.SetCategory method to categorize a
notification when running on Android 5.0 Lollipop (and later), but we still want our app to run on earlier
versions of Android such as Android 4.1 Jelly Bean (where SetCategory is not available). Referring to the
Android version table at the beginning of this guide, we see that the build version code for Android 5.0
Lollipop is Android.OS.BuildVersionCodes.Lollipop . To support older versions of Android where SetCategory is
not available, our code can detect the API level at runtime and conditionally call SetCategory only when the API
level is greater than or equal to the Lollipop build version code:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)


{
builder.SetCategory(Notification.CategoryEmail);
}

In this example, our app's Target Framework is set to Android 5.0 (API Level 21) and its Minimum Android
version is set to Android 4.1 (API Level 16). Because SetCategory is available in API level
Android.OS.BuildVersionCodes.Lollipop and later, this example code will call SetCategory only when it is actually
available – it will not attempt to call SetCategory when the API level is 16, 17, 18, 19, or 20. The functionality is
reduced on these earlier Android versions only to the extent that notifications are not sorted properly (because
they are not categorized by type), yet the notifications are still published to alert the user. Our app still works,
but its functionality is slightly diminished.
In general, the build version check helps your code decide at runtime between doing something the new way
versus the old way. For example:
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
{
// Do things the Lollipop way
}
else
{
// Do things the pre-Lollipop way
}

There's no fast and simple rule that explains how to reduce or modify your app's functionality when it runs on
older Android versions that are lacking one or more APIs. In some cases (such as in the SetCategory example
above), it's sufficient to simply omit the API call when it's not available. However, in other cases, you may need
to implement alternate functionality for when Android.OS.Build.VERSION.SdkInt is detected to be less than the
API level that your app needs to present its optimum experience.

API Levels and Libraries


Visual Studio
Visual Studio for Mac
When you create a Xamarin.Android library project (such as a class library or a bindings library), you can
configure only the Target Framework setting – the Minimum Android version and the Target Android version
settings are not available. That is because there is no Android Manifest page:

The Minimum Android version and Target Android version settings are not available because the resulting
library is not a stand-alone app – the library could be run on any Android version, depending on the app that it
is packaged with. You can specify how the library is to be compiled, but you can't predict which platform API
level the library will be run on. With this in mind, the following best practices should be observed when
consuming or creating libraries:
When consuming an Android library – If you are consuming an Android library in your application,
be sure to set your app's Target Framework setting to an API level that is at least as high as the Target
Framework setting of the library.
When creating an Android library – If you are creating an Android library for use by other
applications, be sure to set its Target Framework setting to the minimum API level that it needs in order
to compile.
These best practices are recommended to help prevent the situation where a library attempts to call an API that
is not available at runtime (which can cause the app to crash). If you are a library developer, you should strive to
restrict your usage of API calls to a small and well-established subset of the total API surface area. Doing so
helps to ensure that your library can be used safely across a wider range of Android versions.
Summary
This guide explained how Android API levels are used to manage app compatibility across different versions of
Android. It provided detailed steps for configuring the Xamarin.Android Target Framework, Minimum Android
version, and Target Android version project settings. It provided instructions for using the Android SDK
Manager to install SDK packages, included examples of how to write code to deal with different API levels at
runtime, and explained how to manage API levels when creating or consuming Android libraries. It also
provided a comprehensive list that relates API levels to Android version numbers (such as Android 4.4),
Android version names (such as Kitkat), and Xamarin.Android build version codes.

Related Links
Android SDK Setup
SDK CLI Tooling Changes
Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion
What is API Level?
Codenames, Tags, and Build Numbers
Android Resources
4/12/2018 • 2 minutes to read • Edit Online

This article introduces the concept of Android resources in Xamarin.Android and will document how to use them.
It covers how to use resources in your Android application to support application localization, and multiple
devices including varying screen sizes and densities.

Overview
An Android application is seldom just source code. There are often many other files that make up an application:
video, images, fonts, and audio files just to name a few. Collectively, these non-source code files are referred to as
resources and are compiled (along with the source code) during the build process and packaged as an APK for
distribution and installation onto devices:

Resources offer several advantages to an Android application:


Code-Separation – Separates source code from images, strings, menus, animations, colors, etc. As such
resources can help considerably when localizing.
Target multiple devices – Provides simpler support of different device configurations without code
changes.
Compile-time Checking – Resources are static and compiled into the application. This allows the usage
of the resources to be checked at compile time, when it will be easy to catch and correct the mistakes, as
opposed to run-time when it is more difficult to locate and costly to correct.
When a new Xamarin.Android project is started, a special directory called Resources is created, along with some
subdirectories:
Visual Studio
Visual Studio for Mac
In the image above, the application resources are organized according to their type into these subdirectories:
images will go in the drawable directory; views go in the layout subdirectory, etc.
There are two ways to access these resources in a Xamarin.Android application: programmatically in code and
declaratively in XML using a special XML syntax.
These resources are called Default Resources and are used by all devices unless a more specific match is specified.
Additionally, every type of resource may optionally have Alternate Resources that Android may use to target
specific devices. For example, resources may be provided to target the user's locale, the screen size, or if the device
is rotated 90 degrees from portrait to landscape, etc. In each of these cases, Android will load the resources for
use by the application without any extra coding effort by the developer.
Alternate resources are specified by adding a short string, called a qualifier, to the end of the directory holding a
given type of resources.
For example, resources/drawable-de will specify the images for devices that are set to a German locale, while
resources/drawable-fr would hold images for devices set to a French locale. An example of providing alternate
resources can be seen in the image below where the same application is being run with just the locale of the
device changing:

This article will take a comprehensive look at using resources and cover the following topics:
Android Resource Basics – Using default resources programmatically and declaratively, adding resource
types such as images and fonts to an application.
Device Specific Configurations – Supporting the different screen resolutions and densities in an
application.
Localization – Using resources to support the different regions an application may be used.

Related Links
Using Android Assets
Application Fundamentals
Application Resources
Supporting Multiple Screens
Android Resource Basics
7/25/2018 • 4 minutes to read • Edit Online

Almost all Android applications will have some sort of resources in them; at a minimum they often have the user
interface layouts in the form of XML files. When a Xamarin.Android application is first created, default resources
are setup by the Xamarin.Android project template:
Visual Studio
Visual Studio for Mac

The five files that make up the default resources were created in the Resources folder:
Icon.png – The default icon for the application
Main.axml – The default user interface layout file for an application. Note that while Android uses the .xml
file extension, Xamarin.Android uses the .axml file extension.
Strings.xml – A string table to help with localization of the application
AboutResources.txt – This is not necessary and may safely be deleted. It just provides a high level
overview of the Resources folder and the files in it.
Resource.designer.cs – This file is automatically generated and maintained by Xamarin.Android and holds
the unique ID's assigned to each resource. This is very similar and identical in purpose to the R.java file that
an Android application written in Java would have. It is automatically created by the Xamarin.Android tools
and will be regenerated from time to time.

Creating and Accessing Resources


Creating resources is as simple as adding files to the directory for the resource type in question. The screen shot
below shows string resources for German locales were added to a project. When Strings.xml was added to the file,
the Build Action was automatically set to AndroidResource by the Xamarin.Android tools:
Visual Studio
Visual Studio for Mac
This allows the Xamarin.Android tools to properly compile and embed the resources in to the APK file. If for some
reason the Build Action is not set to Android Resource, then the files will be excluded from the APK, and any
attempt to load or access the resources will result in a run-time error and the application will crash.
Also, it's important to note that while Android only supports lowercase filenames for resource items,
Xamarin.Android is a bit more forgiving; it will support both uppercase and lowercase filenames. The convention
for image names is to use lowercase with underscores as separators (for example, my_image_name.png). Note
that resource names cannot be processed if dashes or spaces are used as separators.
Once resources have been added to a project, there are two ways to use them in an application – programmatically
(inside code) or from XML files.

Referencing Resources Programmatically


To access these files programmatically, they are assigned a unique resource ID. This resource ID is an integer
defined in a special class called Resource , which is found in the file Resource.designer.cs, and looks something
like this:
public partial class Resource
{
public partial class Attribute
{
}
public partial class Drawable {
public const int Icon=0x7f020000;
}
public partial class Id
{
public const int Textview=0x7f050000;
}
public partial class Layout
{
public const int Main=0x7f030000;
}
public partial class String
{
public const int App_Name=0x7f040001;
public const int Hello=0x7f040000;
}
}

Each resource ID is contained inside a nested class that corresponds to the resource type. For example, when the
file Icon.png was added to the project, Xamarin.Android updated the Resource class, creating a nested class called
Drawable with a constant inside named Icon . This allows the file Icon.png to be referred to in code as
Resource.Drawable.Icon . The Resource class should not be manually edited, as any changes that are made to it will
be overwritten by Xamarin.Android.
When referencing resources programmatically (in code), they can be accessed via the Resources class hierarchy
which uses the following syntax:

@[<PackageName>.]Resource.<ResourceType>.<ResourceName>

PackageName – The package which is providing the resource and is only required when resources from
other packages are being used.
ResourceType – This is the nested resource type that is within the Resource class described above.
Resource Name – this is the filename of the resource (without the extension) or the value of the
android:name attribute for resources that are in an XML element.

Referencing Resources from XML


Resources in an XML file are accessed by a following a special syntax:

@[<PackageName>:]<ResourceType>/<ResourceName>.

PackageName – the package which is providing the resource and is only required when resources from
other packages are being used.
ResourceType – This is the nested resource type that is within the Resource class.
Resource Name – this is the filename of the resource (without the file type extension) or the value of the
android:name attribute for resources that are in an XML element.

For example the contents of a layout file, Main.axml, are as follows:


<?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">
<ImageView android:id="@+id/myImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/flag" />
</LinearLayout>

This example has an ImageView that requires a drawable resource named flag. The ImageView has its src
attribute set to **@drawable/flag**. When the activity starts, Android will look inside the directory
Resource/Drawable for a file named flag.png (the file extension could be another image format, like flag.jpg)
and load that file and display it in the ImageView . When this application is run, it would look something like the
following image:
Default Resources
4/12/2018 • 4 minutes to read • Edit Online

Default resources are items that are not specific to any particular device or form factor, and therefore are the
default choice by the Android OS if no more specific resources can be found. As such, they're the most common
type of resource to create. They're organized into sub-directories of the Resources directory according to their
resource type:
Visual Studio
Visual Studio for Mac

In the image above, the project has default values for drawable resources, layouts, and values (XML files that
contain simple values).
A complete list of resource types is provided below:
animator – XML files that describe property animations. Property animations were introduced in API level
11 (Android 3.0) and provides for the animation of properties on an object. Property animations are a more
flexible and powerful way to describe animations on any type of object.
anim – XML files that describe tween animations. Tween animations are a series of animation instructions
to perform transformations on the contents of a View object, or example, rotation an image or growing the
size of text. Tween animations are limited to only View objects.
color – XML files that describe a state list of colors. To understand color state lists, consider a UI widget such
as a Button. It may have different states such as pressed or disabled, and the button may change color with
each change in state. The list is expressed in a state list.
drawable – Drawable resources are a general concept for graphics that can be compiled into the application
and then accessed by API calls or referenced by other XML resources. Some examples of drawables are
bitmap files (.png, .gif, .jpg), special resizable bitmaps known as Nine-Patches, state lists, generic shapes
defined in XML, etc.
layout – XML files that describe a user interface layout, such as an activity or a row in a list.
menu – XML files that describe application menus such as Options Menus, Context Menus, and submenus.
For an example of menus, see the Popup Menu Demo or the Standard Controls sample.
raw – Arbitrary files that are saved in their raw, binary form. These files are compiled into an Android
application in a binary format.
values – XML files that contain simple values. An XML file in the values directory does not define a single
resource, but instead can define multiple resources. For example one XML file may hold a list of string
values, while another XML file may hold a list of color values.
xml – XML files that are similar in function to the .NET configuration files. These are arbitrary XML that can
be read at run time by the application
Alternate Resources
4/12/2018 • 8 minutes to read • Edit Online

Alternate resources are those resources that target a specific device or run-time configuration such as the current
language, particular screen size, or pixel density. If Android can match a resource that is more specific for a
particular device or configuration than the default resource, then that resource will be used instead. If it does not
find an alternate resource that matches the current configuration, then the default resources will be loaded. How
Android decides what resources will be used by an application will be covered in more detail below, in the section
Resource Location
Alternate resources are organized as a sub-directory inside the Resources folder according to the resource type,
just like default resources. The name of the alternate resource subdirectory is in the form: ResourceType-Qualifier
Qualifier is a name that identifies a specific device configuration. There may be more than one qualifier in a name,
each of them separated by a dash. For example, the screenshot below shows a simple project that has alternate
resources for various configurations such as locale, screen density, screen size, and orientation:
Visual Studio
Visual Studio for Mac

The following rules apply when adding qualifiers to a resource type:


1. There may be more than one qualifier, with each qualifier separated by a dash.
2. The qualifiers maybe specified only once.
3. Qualifiers must be in the order they appear in the table below.
The possible qualifiers are listed below for reference:
MCC and MNC – The mobile country code (MCC ) and optionally the mobile network code (MNC ). The
SIM card will provide the MCC, while the network the device is connected to will provide the MNC.
Although it is possible to target locales using the mobile country code, the recommend approach is to use
the Language qualifier specified below. For example, to target resources to Germany, the qualifier would be
mcc262 . To target resources for T -Mobile in the U.S., the qualifier is mcc310-mnc026 . For a complete list of
mobile country codes and mobile network codes see http://mcc-mnc.com/.
Language – The two-letter ISO 639-1 language code and optionally followed by the two-letter ISO -3166-
alpha-2 region code. If both qualifiers are provided, then they are separated by an -r . For example, to
target French-speaking locales then the qualifier of fr is used. To target French-Canadian locales, the
fr-rCA would be used. For a complete list of language codes and region codes, see Codes for the
Representation of Names Of Languages and Country names and code elements.
Smallest Width – Specifies the smallest screen width the application is meant to execute on. Covered in
more detail in Creating Resources for Varying Screens. Available in API level 13 (Android 3.2) and above.
For example, the qualifier sw320dp is used to target devices whose height and width is at least 320dp.
Available Width – The minimum width of the screen in the format wNdp, where N is the width in density
independent pixels. This value may change as the user rotates the device. Covered in more detail in Creating
Resources for Varying Screens. Available in in API level 13 (Android 3.2) and above. Example: the qualifier
w720dp is used to target devices that have a width of least 720dp.
Available Height – The minimum height of the screen in the format hNdp, where N is the height in dp.
This value may change as the user rotates the device. Covered in more detail in Creating Resources for
Varying Screens. Available in in API level 13 (Android 3.2) and above. For example, the qualifier h720dp is
used to target devices that have a height of least 720dp
Screen Size – This qualifier is a generalization of the screen size that these resources are for. It is covered in
more detail in Creating Resources for Varying Screens. Possible values are small , normal , large , and
xlarge . Added in API level 9 ( Android 2.3/Android 2.3.1/Android 2.3.2 )

Screen Aspect – This is based on the aspect ratio, not the screen orientation. A long screen is wider. Added
in API level 4 (Android 1.6). Possible values are long and notlong.
Screen Orientation – Portrait or landscape screen orientation. This can change during the lifetime of an
application. Possible values are port and land .
Dock Mode – For devices in a car dock or a desk dock. Added in API level 8 (Android 2.2.x). Possible values
are car and desk .
Night Mode – Whether or not the application is running at night or in the day. This may change during the
lifetime of an application and is meant to give developers an opportunity to use darker versions of an
interface at night. Added in API level 8 (Android 2.2.x). Possible values are night and notnight .
Screen Pixel Density (dpi) – The number of pixels in a given area on the physical screen. Typically
expressed as dots per inch (dpi). Possible values are:
ldpi – Low density screens.
mdpi – Medium density screens
hdpi – High density screens
xhdpi – Extra high density screens
nodpi – Resources that are not to be scaled
tvdpi – Introduced in API level 13 (Android 3.2) for screens between mdpi and hdpi.
Touchscreen Type – Specifies the type of touchscreen a device may have. Possible values are notouch (no
touch screen), stylus (a resistive touchscreen suitable for a stylus), and finger (a touchscreen).
Keyboard Availability – Specifies what kind of keyboard is available. This may change during the lifetime
of an application – for example when a user opens a hardware keyboard. Possible values are:
keysexposed – The device has a keyboard available. If there is no software keyboard enabled, then
this is only used when the hardware keyboard is opened.
keyshidden – The device does have a hardware keyboard but it is hidden and no software keyboard
is enabled.
keyssoft – the device has a software keyboard enabled.
Primary Text Input Method – Use to specify what kinds of hardware keys are available for input. Possible
values are:
nokeys – There are no hardware keys for input.
qwerty – There is a qwerty keyboard available.
12key – There is a 12-key hardware keyboard
Navigation Key Availability – For when 5-way or d-pad (directional-pad) navigation is available. This can
change during the lifetime of your application. Possible values are:
navexposed – the navigational keys are available to the user
navhidden – the navigational keys are not available.
Primary Non-Touch Navigation Method – The kind of navigation available on the device. Possible
values are:
nonav – the only navigation facility available is the touch screen
dpad – a d-pad (directional-pad) is available for navigation
trackball – the device has a trackball for navigation
wheel – the uncommon scenario where there are one or more directional wheels available
Platform Version (API level) – The API level supported by the device in the format vN, where N is the
API level that is being targeted. For example, v11 will target an API level 11 (Android 3.0) device.
For more complete information about resource qualifiers see Providing Resources on the Android Developers
website.

How Android Determines What Resources to Use


It is very possible and likely that an Android application will contain many resources. It is important to understand
how Android will select the resources for an application when it runs on a device.
Android determines the resources base by iterating over the following test of rules:
Eliminate contradictory qualifiers – for example, if the device orientation is portrait, then all landscape
resource directories will be rejected.
Ignore qualifiers not supported – Not all qualifiers are available to all API levels. If a resource directory
contains a qualifier that is not supported by the device, then that resource directory will be ignored.
Identify the next highest priority qualifier – referring to the table above select the next highest priority
qualifier (from top to bottom).
Keep any resource directories for qualifier – if there are any resource directories that match the qualifier
to the table above select the next highest priority qualifier (from top to bottom).
These rules are also illustrated in the following flowchart:

When the system is looking for density-specific resources and cannot find them, it will attempt to locate other
density specific resources and scale them. Android may not necessarily use the default resources. For example,
when looking for a low -density resource and it is not available, Android may select high-density version of the
resource over the default or medium-density resources. It does this because the high-density resource can be
scaled down by a factor of 0.5, which will result in fewer visibility issues than scaling down a medium-density
resource which would require a factor of 0.75.
As an example, consider an application that has the following drawable resource directories:

drawable
drawable-en
drawable-fr-rCA
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

And now the application is run on a device with the following configuration:
Locale – en-GB
Orientation – port
Screen density – hdpi
Touchscreen type – notouch
Primary input method – 12key
To begin with, the French resources are eliminated as they conflict with the locale of en-GB , leaving us with:
drawable
drawable-en
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

Next, the first qualifier is selected from the qualifiers table above: MCC and MNC. There are no resource
directories that contain this qualifier so the MCC/MNC code is ignored.
The next qualifier is selected, which is Language. There are resources that match the language code. All resource
directories that do not match the language code of en are rejected, so that the list of resources is now:

drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi

The next qualifier that is present is for screen orientation, so all resource directories that do not match the screen
orientation of port are eliminated:

drawable-en-port
drawable-en-port-ldpi

Next is the qualifier for screen density, ldpi , which results in the exclusion of one more resource directory:

drawable-en-port-ldpi

As a result of this process, Android will use the drawable resources in the resource directory
drawable-en-port-ldpi for the device.

NOTE
The screen size qualifiers provide one exception to this selection process. It is possible for Android to select resources that are
designed for a smaller screen than what the current device provides. For example, a large screen device may use the
resources provide for a normal sized screen. However the reverse of this is not true: the same large screen device will not use
the resources provided for an xlarge screen. If Android cannot find a resource set that matches a given screen size, the
application will crash.
Creating Resources for Varying Screens
4/12/2018 • 7 minutes to read • Edit Online

Android itself runs on many different devices, each having a wide variety of resolutions, screen sizes, and screen
densities. Android will perform scaling and resizing to make your application work on these devices, but this may
result in a sub-optimal user experience. For example, images may appear blurry, images may occupy too much (or
not enough) screen space which causes the position of UI elements in the layout will overlap or be too far apart.

Concepts
A few terms and concepts are important to understand to support multiple screens.
Screen Size – The amount of physical space for displaying your application
Screen Density – The number of pixels in any given area on the screen. The typical unit of measure is dots
per inch (dpi).
Resolution – The total number of pixels on the screen. When developing applications, resolution is not as
important as screen size and density.
Density-independent pixel (dp) – This is a virtual unit of measure to allow layouts to be designed
independent of density. To convert dp into screen pixels the following formula is used:
px = dp × dpi ÷ 160
Orientation – The screen's orientation is considered to be landscape when it is wider than it is tall. In
contrast, portrait orientation is when the screen is taller than it is wide. The orientation can change during
the lifetime of an application as the user rotates the device.
Notice that the first three of these concepts are inter-related – increasing the resolution without increasing the
density will increase the screen size. However if both the density and resolution are increased then the screen size
can remain unchanged. This relationship between screen size, density and resolution complicate screen support
very quickly.
To help deal with this complexity, the Android framework prefers to use density-independent pixels (dp ) for screen
layouts. By using density independent pixels, UI elements will appear to the user to have the same physical size on
screens with different densities.

Supporting Various Screen Sizes and Densities


Android handles most of the work to render the layouts properly for each screen configuration. However, there
are some actions that can be taken to help the system out.
The use of density-independent pixels instead of actual pixels in layouts is sufficient in most cases to ensure
density independence. Android will scale the drawables at runtime to the appropriate size. However, it is possible
that this scaling will cause bitmaps to appear blurry. To avoid this, it may be necessary to supply alternate
resources for the different densities. When designing devices for multiple resolutions and screen densities it will
prove easier to start with the higher resolution or density images and then scale down. This will prevent any
blurring or distortion that may result from the resizing.
Declare the Screen Size the Application Supports
Declaring the screen size ensures that only supported devices can download the application. This is accomplished
by setting the supports-screens element in the AndroidManifest.xml file. This element is used to specify what
screen sizes are supported by the application. A given screen is considered to be supported if the application can
properly it's layouts to fill screen. By using this manifest element, the application will not show up in Google Play
for devices that do not meet the screen specifications. However, the application will still run on devices with
unsupported screens, but the layouts may appear blurry and pixelated.
To do this in Xamarin.Android, it is necessary to first add an AndroidManifest.xml file to the project if it does not
already exist:
Visual Studio
Visual Studio for Mac

AndroidManifest.xml is added to the Properties directory. The file is then edited to include supports-screens:

Provide Alternate Layouts for Different Screen Sizes


Although Android will resize according the screen size, this may not be sufficient in some cases. It may be
desirable to increase the size of some UI elements on a larger screen, or to change the positioning of the UI
elements for a smaller screen.
Starting with API Level 13 (Android 3.2), the screen sizes are deprecated in favor of using the swNdp qualifier.
This new qualifier declares the amount of space a given layout needs. It is strongly recommended that
applications that are meant to run on Android 3.2 or higher should be using these newer qualifiers.
For example, if a layout required a minimum 700dp of screen width, the alternate layout would go in a folder
layout-sw700dp:
Visual Studio
Visual Studio for Mac

As a guideline, here are some numbers for various devices:


Typical phone – 320dp: a typical phone
A 5" tablet / "tweener" device – 480dp: such as the Samsung Note
A 7" tablet – 600dp: such as the Barnes & Noble Nook
A 10" tablet – 720dp: such as the Motorola Xoom
For applications that target API levels up to 12 (Android 3.1), the layouts should go in directories that use the
qualifiers small/normal/large/xlarge as generalizations of the various screen sizes that are available in most
devices. For example, in the image below, there are alternate resources for the four different screen sizes:
Visual Studio
Visual Studio for Mac

The following is a comparison of how the older pre-API Level 13 screen size qualifiers compare to density-
independent pixels:
426dp x 320dp is small
470dp x 320dp is normal
640dp x 480dp is large
960dp x 720dp is xlarge
The newer screen size qualifiers in API level 13 and up have a higher precedence than the older screen qualifiers
of API levels 12 and lower. For applications that will span the old and the new API levels, it may be necessary to
create alternate resources using both sets of qualifiers as shown in the following screen shot:
Visual Studio
Visual Studio for Mac

Provide Different Bitmaps for Different Screen Densities


Although Android will scale bitmaps as necessary for a device, the bitmaps themselves may not elegantly scale up
or down: they may become fuzzy or blurry. Providing bitmaps appropriate for the screen density will mitigate this
problem.
For example, the image below is an example of layout and appearance problems that may occur when density
specify resources are not provided.
Compare this to a layout that is designed with density specific resources:

Create Varying Density Resources with Android Asset Studio


The creation of these bitmaps of various densities can be a bit tedious. As such, Google has created an online
utility which can reduce some of the tedium involved with the creation of these bitmaps called the Android Asset
Studio.

This website will help with creation of bitmaps that target the four common screen densities by providing one
image. Android Asset Studio will then create the bitmaps with some customizations and then allow them to be
downloaded as a zip file.

Tips for Multiple Screens


Android runs on a bewildering number of devices, and the combination of screen sizes and screen densities can
seem overwhelming. The following tips can help minimize the effort necessary to support various devices:
Only Design and Develop for What you Need – There are a lot of different devices out there, but some
exist in rare form factors that may take a lot of effort to design and develop for. The Screen Size and
Density dashboard is a page provided by Google that provides data on breakdown of the screen
size/screen density matrix. This breakdown provides insight on how to development effort on supporting
screens.
Use DPs rather than Pixels - Pixels become troublesome as screen density changes. Do not hardcode
pixel values. Avoid pixels in favor of dp (density-independent pixels).
Avoid AbsoluteLayout Wherever Possible – it is deprecated in API level 3 (Android 1.5) and will result in
brittle layouts. It should not be used. Instead, try to use more flexible layout widgets such as LinearLayout,
RelativeLayout, or the new GridLayout.
Pick one layout orientation as your default – For example, instead of providing the alternate resources
layout-land and layout-port, put the resources for landscape in layout, and the resources for portrait
into layout-port.
Use LayoutParams for Height and Width - When defining UI elements in an XML layout file, an
Android application using the wrap_content and fill_parent values will have more success ensure a
proper look across different devices than using pixel or density independent units. These dimension values
cause Android to scale bitmap resources as appropriate. For this same reason, density-independent units
are best reserved for when specifying the margins and padding of UI elements.

Testing Multiple Screens


An Android application needs to be tested against all configurations that will be supported. Ideally devices should
be tested on the actual devices themselves but in many cases this is not possible or practical. In this case the use of
the emulator and Android Virtual Devices setup for each device configuration will be useful.
The Android SDK provides some emulator skins may be used to create AVD's will replicate the size, density, and
resolution of many devices. Many of the hardware vendors likewise provide skins for their devices.
Another option is to use the services of a third party testing service. These services will take an APK, run it on
many different devices, and then provide feedback how the application worked.
Application Localization and String Resources
4/12/2018 • 2 minutes to read • Edit Online

Application localization is the act of providing alternate resources to target a specific region or locale. For example,
you might provide localized language strings for various countries, or you might change colors or layout to match
particular cultures. Android will load and use the resources appropriate for the device's locale at runtime time
without any changes to the source code.
For example, the image below shows the same application running in three different device locales, but the text
displayed in each button is specific to the locale that each device is set to:

In this example, the contents of a layout file, Main.axml looks something like this:

<?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"
>
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>

In the example above, the string for the button was loaded from the resources by providing the resource ID for the
string:
Visual Studio
Visual Studio for Mac
Localizing Android Apps
Read the Introduction to Localization for tips and guidance on localizing mobile apps.
The Localizing Android Apps guide contains more specific examples on how to translate strings and localize
images using Xamarin.Android.

Related Links
Localizing Android Apps
Cross-Platform Localization Overview
Using Android Assets
4/12/2018 • 2 minutes to read • Edit Online

Assets provide a way to include arbitrary files like text, xml, fonts, music, and video in your application. If you try to
include these files as "resources", Android will process them into its resource system and you will not be able to
get the raw data. If you want to access data untouched, Assets are one way to do it.
Assets added to your project will show up just like a file system that can read from by your application using
AssetManager. In this simple demo, we are going to add a text file asset to our project, read it using AssetManager ,
and display it in a TextView.

Add Asset to Project


Assets go in the Assets folder of your project. Add a new text file to this folder called read_asset.txt . Place some
text in it like "I came from an asset!".
Visual Studio
Visual Studio for Mac
Visual Studio should have set the Build Action for this file to AndroidAsset:

Selecting the correct BuildAction ensures that the file will be packaged into the APK at compile time.

Reading Assets
Assets are read using an AssetManager. An instance of the AssetManager is available by accessing the Assets
property on an Android.Content.Context , such as an Activity. In the following code, we open our read_asset.txt
asset, read the contents, and display it using a TextView.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// Create a new TextView and set it as our view


TextView tv = new TextView (this);

// Read the contents of our asset


string content;
AssetManager assets = this.Assets;
using (StreamReader sr = new StreamReader (assets.Open ("read_asset.txt")))
{
content = sr.ReadToEnd ();
}

// Set TextView.Text to our asset content


tv.Text = content;
SetContentView (tv);
}

Running the Application


Run the application and you should see the following:

Related Links
AssetManager
Context
Fonts
4/13/2018 • 11 minutes to read • Edit Online

Overview
Beginning with API level 26, the Android SDK allows fonts to be treated as resources, just like a layouts or
drawables. The Android Support Library 26 NuGet will backport the new font API's to those apps that target API
level 14 or higher.
After targetting API 26 or installing the Android Support Library v26, there are two ways to use fonts in an
Android application:
1. Package the font as an Android resource – this ensures that the font is always available to the application,
but will increase the size of the APK.
2. Download the fonts – Android also supports downloading a font from a font provider. The font provider
checks if the font is already on the device. If necessary, the font will be downloaded and cached on the device.
This font can be shared between multiple applications.
Similar fonts (or a font that may have several different styles) may be grouped into font families. This allows
developers to specify certain attributes of the font, such as it's weight, and Android will automatically select the
appropriate font from the font family.
The Android Support Library v26 will backport support for fonts to API level 26. When targeting the older API
levels, it is necessary to declare the app XML namespace and to name the various font attributes using the
android: namespace and the app: namespace. If only the android: namespace is used, then the fonts will not be
displayed devices running API level 25 or less. For example, this XML snippet declares a new font family resource
that will work in API level 14 and higher:

<?xml version="1.0" encoding="utf-8"?>


<font-family
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<font android:font="@font/sourcesanspro_regular"
android:fontStyle="normal"
android:fontWeight="400"
app:font="@font/sourcesanspro_regular"
app:fontStyle="normal"
app:fontWeight="400" />

</font-family>

As long as fonts are provided to an Android application in a proper way, they can be applied to a UI widget by
setting the fontFamily attribute. For example, the following snippet demonstrates how to display a font in a
TextView:

<TextView
android:text="The quick brown fox jumped over the lazy dog."
android:fontFamily="@font/sourcesanspro_regular"
app:fontFamily="@font/sourcesanspro_regular"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
This guide will first discuss how to use fonts as an Android resource, and then move on to discuss how to
download fonts at runtime.

Fonts as a Resource
Packaging a font into an Android APK ensures that it is always available to the application. A font file (either a .TTF
or a .OTF file) is added to a Xamarin.Android application just like any other resource, by copying files to a
subdirectory in the Resources folder of a Xamarin.Android project. Fonts resources are kept in a font sub-
directory of the Resources folder of the project.

NOTE
The fonts should have a Build Action of AndroidResource or they will not be packaged into the final APK. The build action
should be automatically set by the IDE.

When there are many similar font files (for example, the same font with different weights or styles) it is possible to
group them into a font family.
Font Families
A font family is a set of fonts that have different weights and styles. For example, there might be separate font files
for bold or italic fonts. The font family is defined by font elements in an XML file that is kept in the
Resources/font directory. Each font family should have it's own XML file.
To create a a font family, first add all the fonts to the Resources/font folder. Then create a new XML file in the font
folder for the font family. The name of the XML file has no affinity or relationship to the fonts being referenced; the
resource file can be any legal Android resource file name. This XML file will have a root font-family element that
contains one or more font elements. Each font element declares the attributes of a font.
The following XML is an example of a font family for the Sources Sans Pro font that defines many different font
weights. This is saved as file in the Resources/font folder named sourcesanspro.xml:

<?xml version="1.0" encoding="utf-8"?>


<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<font android:font="@font/sourcesanspro_regular"
android:fontStyle="normal"
android:fontWeight="400"
app:font="@font/sourcesanspro_regular"
app:fontStyle="normal"
app:fontWeight="400" />
<font android:font="@font/sourcesanspro_bold"
android:fontStyle="normal"
android:fontWeight="800"
app:font="@font/sourcesanspro_bold"
app:fontStyle="normal"
app:fontWeight="800" />
<font android:font="@font/sourcesanspro_italic"
android:fontStyle="italic"
android:fontWeight="400"
app:font="@font/sourcesanspro_italic"
app:fontStyle="italic"
app:fontWeight="400" />
</font-family>

The fontStyle attribute has two possible values:


normal – a normal font
italic – an italic font
The fontWeight attribute corresponds to the CSS font-weight attribute and refers to the thickness of the font.
This is a value in the range of 100 - 900. The following list describes the common font weight values and their
name:
Thin – 100
Extra Light – 200
Light – 300
Normal – 400
Medium – 500
Semi Bold – 600
Bold – 700
Extra Bold – 800
Black – 900
Once a font family has been defined, it can be used declaratively by setting the fontFamily , textStyle , and
fontWeight attributes in the layout file. For example the following XML snippet sets a 400 weight font (normal)
and an italic text style:

<TextView
android:text="Sans Source Pro semi-bold italic, 600 weight, italic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/sourcesanspro"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_horizontal"
android:fontWeight="600"
android:textStyle="italic"
/>

Programmatically Assigning Fonts


Fonts can be programmatically set by using the Resources.GetFont method to retrieve a Typeface object. Many
views have a TypeFace property that can be used to assign the font to the widget. This code snippet shows how to
programmatically set the font on a TextView:

Android.Graphics.Typeface typeface = this.Resources.GetFont(Resource.Font.caveat_regular);


textView1.Typeface = typeface;
textView1.Text = "Changed the font";

The GetFont method will automatically load the the first font within a font family. To load a font that matches a
specific style, use the Typeface.Create method. This method will try to load a font that matches the specified style.
As an example, this snippet will try to load a bold Typeface object from a font family that is defined in
Resources/fonts:

var typeface = Typeface.Create("<FONT FAMILY NAME>", Android.Graphics.TypefaceStyle.Bold);


textView1.Typeface = typeface;

Downloading Fonts
Instead of packaging fonts as an application resource, Android can download fonts from a remote source. This will
have the desirable effect of reducing the size of the APK.
Fonts are downloaded with the assistance of a font provider. This is a specialized content provider that manages
the downloading and caching of fonts to all applications on the device. Android 8.0 includes a font provider to
download fonts from the Google Font Repository. This default font provider is backported to API level 14 with the
Android Support Library v26.
When an app makes a request for a font, the font provider will first check to see if the font is already on the device.
If not, it will then attempt to download the font. If the font cannot be downloaded, then Android will use the default
system font. Once the font has been downloaded, it is available to all applications on the device, not just the app
that made the initial request.
When a request is made to download a font, the app does not directly query the font provider. Instead, apps will
use an instance of the FontsContract API (or the FontsContractCompat if the Support Library 26 is being used).
Android 8.0 supports downloading fonts in two different ways:
1. Declare Downloadable Fonts as a Resource – An app may declare downloadable fonts to Android via XML
resource files. These files will contain all of the meta-data that Android needs to asynchronously download the
fonts when the app starts and cache them on the device.
2. Programmatically – APIs in Android API level 26 allow an application to download the fonts
programmatically, while the application is running. Apps will create a FontRequest object for a given font, and
pass this object to the FontsContract class. The FontsContract takes the FontRequest and retrieves the font
from a font provider. Android will synchronously download the font. An example of creating a FontRequest will
be shown later in this guide.
Regardless of which approach is used, resources files that must be added to the Xamarin.Android application
before fonts can be downloaded. First, the font(s) must be declared in an XML file in the Resources/font directory
as part of a font family. This snippet is an example of how to download fonts from the Google Fonts Open Source
collection using the default font provider that comes with Android 8.0 (or Support Library v26):

<?xml version="1.0" encoding="utf-8"?>


<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fontProviderAuthority="com.google.android.gms.fonts"
android:fontProviderPackage="com.google.android.gms"
android:fontProviderQuery="VT323"
android:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
app:fontProviderAuthority="com.google.android.gms.fonts"
app:fontProviderPackage="com.google.android.gms"
app:fontProviderQuery="VT323"
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
>
</font-family>

The font-family element contains the following attributes, declaring the information that Android requires to
download the fonts:
1. fontProviderAuthority – The authority of the Font Provider to be used for the request.
2. fontPackage – The package for the Font Provider to be used for the request. This is used to verify the identity
of the provider.
3. fontQuery – This is a string that will help the font provider locate the requested font. Details on the font query
are specific to the font provider. The QueryBuilder class in the Downloadable Fonts sample app provides some
information on the query format for fonts from the Google Fonts Open Source Collection.
4. fontProviderCerts – A resource array with the list of sets of hashes for the certificates that the provider should
be signed with.
Once the fonts are defined, it may be necessary to provide information about the font certificates involved with the
download.
Font Certificates
If the font provider is not preinstalled on the device, or if the app is using the Xamarin.Android.Support.Compat
library, Android requires the security certificates of the font provider. These certificates will be listed in an array
resource file that is kept in Resources/values directory.
For example, the following XML is named Resources/values/fonts_cert.xml and stores the certificates for the
Google font provider:

<?xml version="1.0" encoding="utf-8"?>


<resources>
<array name="com_google_android_gms_fonts_certs">
<item>@array/com_google_android_gms_fonts_certs_dev</item>
<item>@array/com_google_android_gms_fonts_certs_prod</item>
</array>
<string-array name="com_google_android_gms_fonts_certs_dev">
<item>

MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1U
EBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQ
EJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ
2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5k
cm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdG
Ns8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6
t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr2
2ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOj
gfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQs
wCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECx
MHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFM
AMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEB
ahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtA
WPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8n
fBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
</item>
</string-array>
<string-array name="com_google_android_gms_fonts_certs_prod">
<item>

MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQ
HEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4Mj
EyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3M
RQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCC
AQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRcz
fey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs
1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYX
tqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r
45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29
vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBA
UAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+
a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1Mvcy
UTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3W
fMBEmh/9iFBDAaTCK
</item>
</string-array>
</resources>

With these resource files in place, the app is capable of downloading the fonts.
Declaring Downloadable Fonts as Resources
By listing the downloadable fonts in the AndroidManifest.XML, Android will asynchronously download the fonts
when the app first starts. The font's themselves are listed in an array resource file, similar to this one:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="downloadable_fonts" translatable="false">
<item>@font/vt323</item>
</array>
</resources>

To download these fonts, they have to be declared in AndroidManifest.XML by adding meta-data as a child of
the application element. For example, if the downloadable fonts are declared in a resource file at
Resources/values/downloadable_fonts.xml, then this snippet would have to be added to the manifest:

<meta-data android:name="downloadable_fonts" android:resource="@array/downloadable_fonts" />

Downloading a Font with the Font APIs


It is possible to programmatically download a font by instantiating a FontRequest object and passing that to the
FontContractCompat.RequestFont method. The FontContractCompat.RequestFont method will first check to see if the
font exists on the device, and then if necessary will asynchronously query the font provider and try to download
the font for the app. If FontRequest is unable to download the font, then Android will use the default system font.
A FontRequest object contains information that will be used by the font provider to locate and download a font. A
FontRequest requires four pieces of information:
1. Font Provider Authority – The authority of the Font Provider to be used for the request.
2. Font Package – The package for the Font Provider to be used for the request. This is used to verify the identity
of the provider.
3. Font Query – This is a string that will help the font provider locate the requested font. Details on the font query
are specific to the font provider. The details of the string are specific to the font provider. The QueryBuilder class
in the Downloadable Fonts sample app provides some information on the query format for fonts from the
Google Fonts Open Source Collection.
4. Font Provider Certificates – A resource array with the list of sets of hashes for the certificates the provider
should be signed with.
This snippet is an example of instantiating a new FontRequest object:

FontRequest request = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms",


<FontToDownload>, Resource.Array.com_google_android_gms_fonts_certs);

In the previous snippet FontToDownload is a query that will help the font from the Google Fonts Open Source
collection.
Before passing the FontRequest to the FontContractCompat.RequestFont method, there are two objects that must be
created:
FontsContractCompat.FontRequestCallback – This is an abstract class which must be extended. It is a callback that
will be invoked when RequestFont is finished. A Xamarin.Android app must subclass
FontsContractCompat.FontRequestCallback and override the OnTypefaceRequestFailed and OnTypefaceRetrieved ,
providing the actions to be taken when the download fails or succeeds respectively.
Handler – This is a Handler which will be used by RequestFont to download the font on a thread, if necessary.
Fonts should not be downloaded on the UI thread.
This snippet is an example of a C# class that will asynchronously download a font from Google Fonts Open Source
collection. It implements the FontRequestCallback interface, and raises a C# event when FontRequest has finished.
public class FontDownloadHelper : FontsContractCompat.FontRequestCallback
{
// A very simple font query; replace as necessary
public static readonly String FontToDownload = "Courgette";

Android.OS.Handler Handler = null;

public event EventHandler<FontDownloadEventArg> FontDownloaded = delegate


{
// just an empty delegate to avoid null reference exceptions.
};

public void DownloadFonts(Context context)


{
FontRequest request = new FontRequest("com.google.android.gms.fonts",
"com.google.android.gms",FontToDownload , Resource.Array.com_google_android_gms_fonts_certs);
FontsContractCompat.RequestFont(context, request, this, GetHandlerThreadHandler());
}

public override void OnTypefaceRequestFailed(int reason)


{
base.OnTypefaceRequestFailed(reason);
FontDownloaded(this, new FontDownloadEventArg(null));
}

public override void OnTypefaceRetrieved(Android.Graphics.Typeface typeface)


{
base.OnTypefaceRetrieved(typeface);
FontDownloaded(this, new FontDownloadEventArg(typeface));
}

Handler GetHandlerThreadHandler()
{
if (Handler == null)
{
HandlerThread handlerThread = new HandlerThread("fonts");
handlerThread.Start();
Handler = new Handler(handlerThread.Looper);
}
return Handler;
}
}

public class FontDownloadEventArg : EventArgs


{
public FontDownloadEventArg(Android.Graphics.Typeface typeface)
{
Typeface = typeface;
}
public Android.Graphics.Typeface Typeface { get; private set; }
public bool RequestFailed
{
get
{
return Typeface != null;
}
}
}

To use this helper, a new FontDownloadHelper is created, and an event handler is assigned:
var fontHelper = new FontDownloadHelper();

fontHelper.FontDownloaded += (object sender, FontDownloadEventArg e) =>


{
//React to the request
};
fontHelper.DownloadFonts(this); // this is an Android Context instance.

Summary
This guide discussed the new APIs in Android 8.0 to support downloadable fonts and fonts as resources. It
discussed how to embed existing fonts in an APK and to use them in a layout. It also discussed how Android 8.0
supports downloading fonts from a font provider, either programmatically or by declaring the font meta-data in
resource files.

Related Links
fontFamily
FontConfig
FontRequest
FontsContractCompat
Resources.GetFont
Typeface
Android Support Library 26 NuGet
Using Fonts in Android
CSS font weight specification
Google Fonts Open Source collection
Source Sans Pro
Activity Lifecycle
4/12/2018 • 17 minutes to read • Edit Online

Activities are a fundamental building block of Android applications and they can exist in a number of different
states. The activity lifecycle begins with instantiation and ends with destruction, and includes many states in
between. When an activity changes state, the appropriate lifecycle event method is called, notifying the activity of
the impending state change and allowing it to execute code to adapt to that change. This article examines the
lifecycle of activities and explains the responsibility that an activity has during each of these state changes to be
part of a well-behaved, reliable application.

Activity Lifecycle Overview


Activities are an unusual programming concept specific to Android. In traditional application development there
is usually a static main method, which is executed to launch the application. With Android, however, things are
different; Android applications can be launched via any registered activity within an application. In practice, most
applications will only have a specific activity that is specified as the application entry point. However, if an
application crashes, or is terminated by the OS, the OS can try to restart the application at the last open activity
or anywhere else within the previous activity stack. Additionally, the OS may pause activities when they're not
active, and reclaim them if it is low on memory. Careful consideration must be made to allow the application to
correctly restore its state in the event that an activity is restarted, especially if that activity depends on data from
previous activities.
The activity lifecycle is implemented as a collection of methods the OS calls throughout the lifecycle of an activity.
These methods allow developers to implement the functionality that is necessary to satisfy the state and resource
management requirements of their applications.
It is extremely important for the application developer to analyze the requirements of each activity to determine
which methods exposed by the activity lifecycle need to be implemented. Failure to do this can result in
application instability, crashes, resource bloat, and possibly even underlying OS instability.
This chapter examines the activity lifecycle in detail, including:
Activity States
Lifecycle Methods
Retaining the State of an Application
This section also includes a walkthrough that provide practical examples on how to efficiently save state during
the Activity lifecycle. By the end of this chapter you should have an understanding of the Activity lifecycle and
how to support it in an Android application.

Activity Lifecycle
The Android activity lifecycle comprises a collection of methods exposed within the Activity class that provide the
developer with a resource management framework. This framework allows developers to meet the unique state
management requirements of each activity within an application and properly handle resource management.
Activity States
The Android OS arbitrates Activities based on their state. This helps Android identify activities that are no longer
in use, allowing the OS to reclaim memory and resources. The following diagram illustrates the states an Activity
can go through during its lifetime:
These states can be broken into 4 main groups as follows:
1. Active or Running – Activities are considered active or running if they are in the foreground, also known as
the top of the activity stack. This is considered the highest priority activity in Android, and as such will only
be killed by the OS in extreme situations, such as if the activity tries to use more memory than is available
on the device as this could cause the UI to become unresponsive.
2. Paused – When the device goes to sleep, or an activity is still visible but partially hidden by a new, non-
full-sized or transparent activity, the activity is considered paused. Paused activities are still alive, that is,
they maintain all state and member information, and remain attached to the window manager. This is
considered to be the second highest priority activity in Android and, as such, will only be killed by the OS if
killing this activity will satisfy the resource requirements needed to keep the Active/Running Activity stable
and responsive.
3. Stopped/Backgrounded – Activities that are completely obscured by another activity are considered
stopped or in the background. Stopped activities still try to retain their state and member information for
as long as possible, but stopped activities are considered to be the lowest priority of the three states and,
as such, the OS will kill activities in this state first to satisfy the resource requirements of higher priority
activities.
4. Restarted – It is possible for an activity that is anywhere from paused to stopped in the lifecycle to be
removed from memory by Android. If the user navigates back to the activity it must be restarted, restored
to its previously saved state, and then displayed to the user.
Activity Re -Creation in Response to Configuration Changes
To make matters more complicated, Android throws one more wrench in the mix called Configuration Changes.
Configuration changes are rapid activity destruction/re-creation cycles that occur when the configuration of an
activity changes, such as when the device is rotated (and the activity needs to get re-built in landscape or portrait
mode), when the keyboard is displayed (and the activity is presented with an opportunity to resize itself ), or when
the device is placed in a dock, among others.
Configuration changes still cause the same Activity State changes that would occur during stopping and
restarting an activity. However, in order to make sure that an application feels responsive and performs well
during configuration changes, it's important that they be handled as quickly as possible. Because of this, Android
has a specific API that can be used to persist state during configuration changes. We'll cover this later in the
Managing State Throughout the Lifecycle section.
Activity Lifecycle Methods
The Android SDK and, by extension, the Xamarin.Android framework provide a powerful model for managing
the state of activities within an application. When an activity's state is changing, the activity is notified by the OS,
which calls specific methods on that activity. The following diagram illustrates these methods in relationship to
the Activity Lifecycle:
As a developer, you can handle state changes by overriding these methods within an activity. It's important to
note, however, that all lifecycle methods are called on the UI thread and will block the OS from performing the
next piece of UI work, such as hiding the current activity, displaying a new activity, etc. As such, code in these
methods should be as brief as possible to make an application feel well performing. Any long-running tasks
should be executed on a background thread.
Let's examine each of these lifecycle methods and their use:
OnCreate
OnCreate is the first method to be called when an activity is created. OnCreate is always overridden to perform
any startup initializations that may be required by an Activity such as:
Creating views
Initializing variables
Binding static data to lists
OnCreate takes a Bundle parameter, which is a dictionary for storing and passing state information and objects
between activities If the bundle is not null, this indicates the activity is restarting and it should restore its state
from the previous instance. The following code illustrates how to retrieve values from the bundle:

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);

string intentString;
bool intentBool;

if (bundle != null)
{
intentString = bundle.GetString("myString");
intentBool = bundle.GetBoolean("myBool");
}

// Set our view from the "main" layout resource


SetContentView(Resource.Layout.Main);
}

Once OnCreate has finished, Android will call OnStart .


OnStart
OnStart is always called by the system after OnCreate is finished. Activities may override this method if they
need to perform any specific tasks right before an activity becomes visible such as refreshing current values of
views within the activity. Android will call OnResume immediately after this method.
OnResume
The system calls OnResume when the Activity is ready to start interacting with the user. Activities should override
this method to perform tasks such as:
Ramping up frame rates (a common task in game building)
Starting animations
Listening for GPS updates
Display any relevant alerts or dialogs
Wire up external event handlers
As an example, the following code snippet shows how to initialize the camera:

public void OnResume()


{
base.OnResume(); // Always call the superclass first.

if (_camera==null)
{
// Do camera initializations here
}
}

OnResume is important because any operation that is done in OnPause should be un-done in OnResume , since it's
the only lifecycle method that is guaranteed to execute after OnPause when bringing the activity back to life.
OnPause
OnPause is called when the system is about to put the activity into the background or when the activity becomes
partially obscured. Activities should override this method if they need to:
Commit unsaved changes to persistent data
Destroy or clean up other objects consuming resources
Ramp down frame rates and pausing animations
Unregister external event handlers or notification handlers (i.e. those that are tied to a service). This must
be done to prevent Activity memory leaks.
Likewise, if the Activity has displayed any dialogs or alerts, they must be cleaned up with the .Dismiss()
method.
As an example, the following code snippet will release the camera, as the Activity cannot make use of it while
paused:

public void OnPause()


{
base.OnPause(); // Always call the superclass first

// Release the camera as other activities might need it


if (_camera != null)
{
_camera.Release();
_camera = null;
}
}

There are two possible lifecycle methods that will be called after OnPause :
1. OnResume will be called if the Activity is to be returned to the foreground.
2. OnStop will be called if the Activity is being placed in the background.
OnStop
OnStop is called when the activity is no longer visible to the user. This happens when one of the following occurs:
A new activity is being started and is covering up this activity.
An existing activity is being brought to the foreground.
The activity is being destroyed.
OnStop may not always be called in low -memory situations, such as when Android is starved for resources and
cannot properly background the Activity. For this reason, it is best not to rely on OnStop getting called when
preparing an Activity for destruction. The next lifecycle methods that may be called after this one will be
OnDestroy if the Activity is going away, or OnRestart if the Activity is coming back to interact with the user.

OnDestroy
OnDestroy is the final method that is called on an Activity instance before it's destroyed and completely removed
from memory. In extreme situations Android may kill the application process that is hosting the Activity, which
will result in OnDestroy not being invoked. Most Activities will not implement this method because most clean up
and shut down has been done in the OnPause and OnStop methods. The OnDestroy method is typically
overridden to clean up long running resources that might leak resources. An example of this might be
background threads that were started in OnCreate .
There will be no lifecycle methods called after the Activity has been destroyed.
OnRestart
OnRestart is called after your activity has been stopped, prior to it being started again. A good example of this
would be when the user presses the home button while on an activity in the application. When this happens
OnPause and then OnStop methods are called, and the Activity is moved to the background but is not destroyed.
If the user were then to restore the application by using the task manager or a similar application, Android will
call the OnRestart method of the activity.
There are no general guidelines for what kind of logic should be implemented in OnRestart . This is because
OnStart is always invoked regardless of whether the Activity is being created or being restarted, so any
resources required by the Activity should be initialized in OnStart , rather than OnRestart .
The next lifecycle method called after OnRestart will be OnStart .
Back vs. Home
Many Android devices have two distinct buttons: a "Back" button and a "Home" button. An example of this can be
seen in the following screenshot of Android 4.0.3:

There is a subtle difference between the two buttons, even though they appear to have the same effect of putting
an application in the background. When a user clicks the Back button, they are telling Android that they are done
with the activity. Android will destroy the Activity. In contrast, when the user clicks the Home button the activity is
merely placed into the background – Android will not kill the activity.

Managing State Throughout the Lifecycle


When an Activity is stopped or destroyed the system provides an opportunity to save the state of the Activity for
later rehydration. This saved state is referred to as instance state. Android provides three options for storing
instance state during the Activity lifecycle:
1. Storing primitive values in a Dictionary known as a Bundle that Android will use to save state.
2. Creating a custom class that will hold complex values such as bitmaps. Android will use this custom class
to save state.
3. Circumventing the configuration change lifecycle and assuming complete responsibility for maintaining
state in the activity.
This guide covers the first two options.
Bundle State
The primary option for saving instance state is to use a key/value dictionary object known as a Bundle. Recall that
when an Activity is created that the OnCreate method is passed a bundle as a parameter, this bundle can be used
to restore the instance state. It is not recommended to use a bundle for more complex data that won't quickly or
easily serialize to key/value pairs (such as bitmaps); rather, it should be used for simple values like strings.
An Activity provides methods to help with saving and retrieving the instance state in the Bundle:
OnSaveInstanceState – This is invoked by Android when the activity is being destroyed. Activities can
implement this method if they need to persist any key/value state items.
OnRestoreInstanceState – This is called after the OnCreate method is finished, and provides another
opportunity for an Activity to restore its state after initialization is complete.
The following diagram illustrates how these methods are used:
OnSaveInstanceState
OnSaveInstanceState will be called as the Activity is being stopped. It will receive a bundle parameter that the
Activity can store its state in. When a device experiences a configuration change, an Activity can use the Bundle
object that is passed in to preserve the Activity state by overriding OnSaveInstanceState . For example, consider
the following code:

int c;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

this.SetContentView (Resource.Layout.SimpleStateView);

var output = this.FindViewById<TextView> (Resource.Id.outputText);

if (bundle != null) {
c = bundle.GetInt ("counter", -1);
} else {
c = -1;
}

output.Text = c.ToString ();

var incrementCounter = this.FindViewById<Button> (Resource.Id.incrementCounter);

incrementCounter.Click += (s,e) => {


output.Text = (++c).ToString();
};
}

The code above increments an integer named c when a button named incrementCounter is clicked, displaying
the result in a TextView named output . When a configuration change happens - for example, when the device is
rotated - the above code would lose the value of c because the bundle would be null , as shown in the figure
below:
To preserve the value of c in this example, the Activity can override OnSaveInstanceState , saving the value in the
bundle as shown below:

protected override void OnSaveInstanceState (Bundle outState)


{
outState.PutInt ("counter", c);
base.OnSaveInstanceState (outState);
}

Now when the device is rotated to a new orientation, the integer is saved in the bundle and is retrieved with the
line:

c = bundle.GetInt ("counter", -1);

NOTE
It is important to always call the base implementation of OnSaveInstanceState so that the state of the view hierarchy can
also be saved.

Vi e w St a t e

Overriding OnSaveInstanceState is an appropriate mechanism for saving transient data in an Activity across
orientation changes, such as the counter in the above example. However, the default implementation of
OnSaveInstanceState will take care of saving transient data in the UI for every view, so long as each view has an
ID assigned. For example, say an application has an EditText element defined in XML as follows:

<EditText android:id="@+id/myText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>

Since the EditText control has an id assigned, when the user enters some data and rotates the device, the data
is still displayed, as shown below:
OnRestoreInstanceState
OnRestoreInstanceState will be called after OnStart . It provides an activity the opportunity to restore any state
that was previously saved to a Bundle during the previous OnSaveInstanceState . This is the same bundle that is
provided to OnCreate , however.
The following code demonstrates how state can be restored in OnRestoreInstanceState :

protected override void OnRestoreInstanceState(Bundle savedState)


{
base.OnRestoreSaveInstanceState(savedState);
var myString = savedState.GetString("myString");
var myBool = savedState.GetBoolean("myBool");
}

This method exists to provide some flexibility around when state should be restored. Sometimes it is more
appropriate to wait until all initializations are done before restoring instance state. Additionally, a subclass of an
existing Activity may only want to restore certain values from the instance state. In many cases, it's not necessary
to override OnRestoreInstanceState , since most activities can restore state using the bundle provided to
OnCreate .

For an example of saving state using a Bundle , refer to the Walkthrough - Saving the Activity state.
Bundle Limitations
Although OnSaveInstanceState makes it easy to save transient data, it has some limitations:
It is not called in all cases. For example, pressing Home or Back to exit an Activity will not result in
OnSaveInstanceState being called.

The bundle passed into OnSaveInstanceState is not designed for large objects, such as images. In the case
of large objects, saving the object from OnRetainNonConfigurationInstance is preferable, as discussed
below.
Data saved by using the bundle is serialized, which can lead to delays.
Bundle state is useful for simple data that doesn't use much memory, whereas non-configuration instance data is
useful for more complex data, or data that is expensive to retrieve, such as from a web service call or a
complicated database query. Non-configuration instance data gets saved in an object as needed. The next section
introduces OnRetainNonConfigurationInstance as a way of preserving more complex data types through
configuration changes.
Persisting Complex Data
In addition to persisting data in the bundle, Android also supports saving data by overriding
OnRetainNonConfigurationInstance and returning an instance of a Java.Lang.Object that contains the data to
persist. There are two primary benefits of using OnRetainNonConfigurationInstance to save state:
The object returned from OnRetainNonConfigurationInstance performs well with larger, more complex data
types because memory retains this object.
The OnRetainNonConfigurationInstance method is called on demand, and only when needed. This is more
economical than using a manual cache.
Using OnRetainNonConfigurationInstance is suitable for scenarios where it is expensive to retrieve the data
multiple times, such as in web service calls. For example, consider the following code that searches Twitter:

public class NonConfigInstanceActivity : ListActivity


{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SearchTwitter ("xamarin");
}

public void SearchTwitter (string text)


{
string searchUrl = String.Format("http://search.twitter.com/search.json?" + "q=
{0}&rpp=10&include_entities=false&" + "result_type=mixed", text);

var httpReq = (HttpWebRequest)HttpWebRequest.Create (new Uri (searchUrl));


httpReq.BeginGetResponse (new AsyncCallback (ResponseCallback), httpReq);
}

void ResponseCallback (IAsyncResult ar)


{
var httpReq = (HttpWebRequest)ar.AsyncState;

using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse (ar)) {


ParseResults (httpRes);
}
}

void ParseResults (HttpWebResponse httpRes)


{
var s = httpRes.GetResponseStream ();
var j = (JsonObject)JsonObject.Load (s);

var results = (from result in (JsonArray)j ["results"] let jResult = result as JsonObject select jResult
["text"].ToString ()).ToArray ();

RunOnUiThread (() => {


PopulateTweetList (results);
});
}

void PopulateTweetList (string[] results)


{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
}
}

This code retrieves results from the web formatted as JSON, parses them, and then presents the results in a list,
as shown in the following screenshot:
When a configuration change occurs - for example, when a device is rotated - the code repeats the process. To
reuse the originally retrieved results and not cause needless, redundant network calls, we can use
OnRetainNonconfigurationInstance to save the results, as shown below:

public class NonConfigInstanceActivity : ListActivity


{
TweetListWrapper _savedInstance;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

var tweetsWrapper = LastNonConfigurationInstance as TweetListWrapper;

if (tweetsWrapper != null) {
PopulateTweetList (tweetsWrapper.Tweets);
} else {
SearchTwitter ("xamarin");
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()


{
base.OnRetainNonConfigurationInstance ();
return _savedInstance;
}

...

void PopulateTweetList (string[] results)


{
ListAdapter = new ArrayAdapter<string> (this, Resource.Layout.ItemView, results);
_savedInstance = new TweetListWrapper{Tweets=results};
}
}

Now when the device is rotated, the original results are retrieved from the LastNonConfiguartionInstance
property. In this example, the results consist of a string[] containing tweets. Since
OnRetainNonConfigurationInstance requires that a Java.Lang.Object be returned, the string[] is wrapped in a
class that subclasses Java.Lang.Object , as shown below:

class TweetListWrapper : Java.Lang.Object


{
public string[] Tweets { get; set; }
}

For example, attempting to use a TextView as the object returned from OnRetainNonConfigurationInstance will
leak the Activity, as illustrated by the code below:
TextView _textView;

protected override void OnCreate (Bundle bundle)


{
base.OnCreate (bundle);

var tv = LastNonConfigurationInstance as TextViewWrapper;

if(tv != null) {
_textView = tv;
var parent = _textView.Parent as FrameLayout;
parent.RemoveView(_textView);
} else {
_textView = new TextView (this);
_textView.Text = "This will leak.";
}

SetContentView (_textView);
}

public override Java.Lang.Object OnRetainNonConfigurationInstance ()


{
base.OnRetainNonConfigurationInstance ();
return _textView;
}

In this section, we learned how to preserve simple state data with the Bundle , and persist more complex data
types with OnRetainNonConfigurationInstance .

Summary
The Android activity lifecycle provides a powerful framework for state management of activities within an
application but it can be tricky to understand and implement. This chapter introduced the different states that an
activity may go through during its lifetime, as well as the lifecycle methods that are associated with those states.
Next, guidance was provided as to what kind of logic should be performed in each of these methods.

Related Links
Handling Rotation
Android Activity
Walkthrough - Saving the Activity state
4/12/2018 • 4 minutes to read • Edit Online

We have covered the theory behind saving state in the Activity Lifecycle guide; now, let's walk through an example.

Activity State Walkthrough


Let's open the ActivityLifecycle_Start project (in the ActivityLifecycle sample), build it, and run it. This is a very
simple project that has two activities to demonstrate the activity lifecycle and how the various lifecycle methods
are called. When you start the application, the screen of MainActivity is displayed:

Viewing State Transitions


Each method in this sample writes to the IDE application output window to indicate activity state. (To open the
output window in Visual Studio, type CTRL -ALT-O; to open the output window in Visual Studio for Mac, click
View > Pads > Application Output.)
When the app first starts, the output window displays the state changes of Activity A:

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

When we click the Start Activity B button, we see Activity A pause and stop while Activity B goes through its
state changes:
[ActivityLifecycle.MainActivity] Activity A - OnPause
[ActivityLifecycle.SecondActivity] Activity B - OnCreate
[ActivityLifecycle.SecondActivity] Activity B - OnStart
[ActivityLifecycle.SecondActivity] Activity B - OnResume
[ActivityLifecycle.MainActivity] Activity A - OnStop

As a result, Activity B is started and displayed in place of Activity A:

When we click the Back button, Activity B is destroyed and Activity A is resumed:

[ActivityLifecycle.SecondActivity] Activity B - OnPause


[ActivityLifecycle.MainActivity] Activity A - OnRestart
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume
[ActivityLifecycle.SecondActivity] Activity B - OnStop
[ActivityLifecycle.SecondActivity] Activity B - OnDestroy

Adding a Click Counter


Next, we're going to change the application so that we have a button that counts and displays the number of times
it is clicked. First, let's add a _counter instance variable to MainActivity :

int _counter = 0;

Next, let's edit the Resource/layout/Main.axml layout file and add a new clickButton that displays the number
of times the user has clicked the button. The resulting Main.axml should resemble the following:
<?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">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/mybutton_text" />
<Button
android:id="@+id/clickButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/counterbutton_text" />
</LinearLayout>

Let's add the following code to the end of the OnCreate method in MainActivity – this code handles click events
from the clickButton :

var clickbutton = FindViewById<Button> (Resource.Id.clickButton);


clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
clickbutton.Click += (object sender, System.EventArgs e) =>
{
_counter++;
clickbutton.Text = Resources.GetString (
Resource.String.counterbutton_text, _counter);
} ;

When we build and run the app again, a new button appears that increments and displays the value of _counter
on each click:

But when we rotate the device to landscape mode, this count is lost:
Examining the application output, we see that Activity A was paused, stopped, destroyed, recreated, restarted, then
resumed during the rotation from portrait to landscape mode:

[ActivityLifecycle.MainActivity] Activity A - OnPause


[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

Because Activity A is destroyed and recreated again when the device is rotated, its instance state is lost. Next, we
will add code to save and restore the instance state.
Adding Code to Preserve Instance State
Let's add a method to MainActivity to save the instance state. Before Activity A is destroyed, Android
automatically calls OnSaveInstanceState and passes in a Bundle that we can use to store our instance state. Let's
use it to save our click count as an integer value:

protected override void OnSaveInstanceState (Bundle outState)


{
outState.PutInt ("click_count", _counter);
Log.Debug(GetType().FullName, "Activity A - Saving instance state");

// always call the base implementation!


base.OnSaveInstanceState (outState);
}

When Activity A is recreated and resumed, Android passes this Bundle back into our OnCreate method. Let's add
code to OnCreate to restore the _counter value from the passed-in Bundle . Add the following code just before
the line where clickbutton is defined:
if (bundle != null)
{
_counter = bundle.GetInt ("click_count", 0);
Log.Debug(GetType().FullName, "Activity A - Recovered instance state");
}

Build and run the app again, then click the second button a few times. When we rotate the device to landscape
mode, the count is preserved!

Let's take a look at the output window to see what happened:

[ActivityLifecycle.MainActivity] Activity A - OnPause


[ActivityLifecycle.MainActivity] Activity A - Saving instance state
[ActivityLifecycle.MainActivity] Activity A - OnStop
[ActivityLifecycle.MainActivity] Activity A - On Destroy

[ActivityLifecycle.MainActivity] Activity A - OnCreate


[ActivityLifecycle.MainActivity] Activity A - Recovered instance state
[ActivityLifecycle.MainActivity] Activity A - OnStart
[ActivityLifecycle.MainActivity] Activity A - OnResume

Before the OnStop method was called, our new OnSaveInstanceState method was called to save the _counter
value in a Bundle . Android passed this Bundle back to us when it called our OnCreate method, and we were able
to used it to restore the _counter value to where we left off.

Summary
In this walkthough, we have used our knowledge of the Activity Lifecycle to preserve state data.

Related Links
ActivityLifecycle (sample)
Activity Lifecycle
Android Activity
Creating Android Services
6/7/2018 • 9 minutes to read • Edit Online

This guide discusses Xamarin.Android services, which are Android components that allow work to be done without
an active user interface. Services are very commonly used for tasks that are performed in the background, such as
time consuming calculations, downloading files, playing music, and so on. It explains the different scenarios that
services are suited for and shows how to implement them both for performing long -running background tasks as
well as for providing an interface for remote procedure calls.

Android Services Overview


Mobile apps are not like desktop apps. Desktops have copious amounts of resources such as screen real estate,
memory, storage space, and a connected power supply, mobile devices do not. These constraints force mobile
apps to behave differently. For example, the small screen on a mobile device typically means that only one app (i.e.
Activity) is visible at a time. Other Activities are moved to the background and pushed into a suspended state
where they cannot perform any work. However, just because an Android application is in the background does not
mean that it is impossible for app to keep working.
Android applications are made up of at least one of the following four primary components: Activities, Broadcast
Receivers, Content Providers, and Services. Activities are the cornerstone of many great Android applications
because they provide the UI that allows a user to interact with the application. However, when it comes to
performing concurrent or background work, Activities are not always the best choice.
The primary mechanism for background work in Android is the service. An Android service is a component that is
designed to do some work without a user interface. A service might download a file, play music, or apply a filter to
an image. Services can also be used for interprocess communication (IPC ) between Android applications. For
example one Android app might use the music player service that is from another app or an app might expose
data (such as a person's contact information) to other apps via a service.
Services, and their ability to perform background work, are crucial to providing a smooth and fluid user interface.
All Android applications have a main thread (also known as a UI thread) on which the Activities are run. To keep
the device responsive, Android must be able to update the user interface at the rate of 60 frames per second. If an
Android app performs too much work on the main thread, then Android will drop frames, which in turn causes the
UI to appear jerky (also sometimes referred to as janky). This means that any work performed on the UI thread
should complete in the time span between two frames, approximately 16 milliseconds (1 second every 60 frames).
To address this concern, a developer may use threads in an Activity to perform some work that would block the UI.
However, this could cause problems. It is very possible that Android will destroy and recreate the multiple
instances of the Activity. However, Android will not automatically destroy the threads, which could result in
memory leaks. A prime example of this is when the device is rotated – Android will try to destroy the instance of
the Activity and then recreate a new one:

This is a potential memory leak – the thread created by the first instance of the Activity will still be running. If the
thread has a reference to the first instance of the Activity, this will prevent Android from garbage collecting the
object. However, the second instance of the Activity is still created (which in turn might create a new thread).
Rotating the device several times in rapid succession may exhaust all the RAM and force Android to terminate the
entire application to reclaim memory.
As a rule of thumb, if the work to be performed should outlive an Activity, then a service should be created to
perform that work. However, if the work is only applicable in the context of an Activity, then creating a thread to
perform the work might be more appropriate. For example, creating a thumbnail for a photo that was just added
to a photo gallery app should probably occur in a service. However, a thread might be more appropriate to play
some music that should only be heard while an Activity is in the foreground.
Background work can be broken down into two broad classifications:
1. Long Running Task – This is work that is ongoing until explicitly stopped. An example of a long running task
is an app that streams music or that must monitor data collected from a sensor. These tasks must run even
though the application has no visible user interface.
2. Periodic Tasks – (sometimes referred to as a job) A periodic task is one that is of relatively short in duration
(several seconds) and is run on a schedule (i.e. once a day for a week or perhaps just once in the next 60
seconds). An example of this is downloading a file from the internet or generating a thumbnail for an image.
There are four different types of Android services:
Bound Service – A bound service is a service that has some other component (typically an Activity) bound
to it. A bound service provides an interface that allows the bound component and the service to interact
with each other. Once there are no more clients bound to the service, Android will shut the service down.
IntentService – An IntentService is a specialized subclass of the Service class that simplifies service
creation and usage. An IntentService is meant to handle individual autonomous calls. Unlike a service,
which can concurrently handle multiple calls, an IntentService is more like a work queue processor – work
is queued up and an IntentService processes each job one at a time on a single worker thread. Typically,
an IntentService is not bound to an Activity or a Fragment.
Started Service – A started service is a service that has been started by some other Android component
(such as an Activity) and is run continously in the background until something explicitly tells the service to
stop. Unlike a bound service, a started service does not have any clients directly bound to it. For this reason,
it is important to design started services so that they may be gracefully restarted as necessary.
Hybrid Service – A hybrid service is a service that has the characteristics of a started service and a bound
service. A hybrid service can be started by when a component binds to it or it may be started by some
event. A client component may or may not be bound to the hybrid service. A hybrid service will keep
running until it is explicitly told to stop, or until there are no more clients bound to it.
Which type of service to use is very dependent on application requirements. As a rule of thumb, an IntentService
or a bound service are sufficient for most tasks that an Android application must perform, so preference should be
given to one of those two types of services. An IntentService is a good choice for "one-shot" tasks, such as
downloading a file, while a bound service would be suitable when frequent interactions with an Activity/Fragment
is required.
While most services run in the background, there is a special sub-category known as a foreground service. This is
a service that is given a higher priority (compared to a normal service) to perform some work for the user (such as
playing music).
It is also possible to run a service in it's own process on the same device, this is sometimes referred to as a remote
service or as an out-of-process service. This does require more effort to create, but can be useful for when an
application needs to share functionality with other applications, and can, in some cases, improve the user
experience of an application.
Background Execution Limits in Android 8.0
Starting in Android 8.0 (API level 26), an Android application no longer have the ability to run freely in the
background. When in the foreground, an app can start and run services without restriction. When an application
moves into the background, Android will grant the app a certain amount of time to start and use services. Once
that time has elapsed, the app can no longer start any services and any services that were started will be
terminated. At this point is is not possible for the app to perform any work. Android considers an application to be
in the foreground if one of the following conditions are met:
There is a visible activity (either started or paused).
The app has started a foreground service.
Another app is in the foreground and is using components from an app that would be otherwise in the
background. An example of this is if Application A, which is in the foreground, is bound to a service provided
by Application B. Application B would then also be considered in the foreground, and not terminated by
Android for being in the background.
There are some situations where, even though an app is in the background, Android will wake up the app and
relax these restrictions for a few minutes, allowing the app to perform some work:
A high priority Firebase Cloud Message is received by the app.
The app receives a broadcast, such as
The application receives an executes a PendingIntent in response to a Notification.

Existing Xamarin.Android applications may have to change how they perform background work to avoid any
issues that might arise on Android 8.0. Here are some practical alterantives to an Android service:
Schedule work to run in the background using the Android Job Scheduler or the Firebase Job
Dispatcher – These two libraries provide a framework for applications to segregate background work in to
jobs, a discrete unit of work. Apps can then schedule the job with the operating system along with some criteria
about when the job can run.
Start the service in the foreground – a foreground service is useful for when the app must perform some
task in the background and the user may need to periodically interact with that task. The foreground service
will display a persistent notification so that the user is aware that the app is running a background task and also
provides a way to monitor or interact with the task. An example of this would be a podcasting app that is
playing back a podcast to the user or perhaps downloading a podcast episode so that it can be enjoyed later.
Use a high priority Firebase Cloud Message (FCM ) – When Android receives a high priority FCM for an
app, it will allow that app to run services in the background for a short period of time. This would be a good
alternative to having a background service that polls an app in the background.
Defer work for when the app comes into the foreground – If none of the previous solutions are viable,
then apps must develop their own way to pause and resume work when the app comes to the foreground.

Related Links
Android Oreo Background Execution Limits
Creating a Service
5/7/2018 • 4 minutes to read • Edit Online

Xamarin.Android services must obey two inviolable rules of Android services:


They must extend the Android.App.Service .
They must be decorated with the Android.App.ServiceAttribute .
Another requirement of Android services is that they must be registered in the AndroidManifest.xml and given a
unique name. Xamarin.Android will automatically register the service in the manifest at build time with the
necessary XML attribute.
This code snippet is the simplest example of creating a service in Xamarin.Android that meets these two
requirements:

[Service]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things.
}

At compile time, Xamarin.Android will register the service by injecting the following XML element into
AndroidManifest.xml (notice that Xamarin.Android generated a random name for the service):

<service android:name="md5a0cbbf8da641ae5a4c781aaf35e00a86.DemoService" />

It is possible to share a service with other Android applications by exporting it. This is accomplished by setting the
Exported property on the ServiceAttribute . When exporting a service, the ServiceAttribute.Name property
should also be set to provide a meaningful public name for the service. This snippet demonstrates how to export
and name a service:

[Service(Exported=true, Name="com.xamarin.example.DemoService")]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things.
}

The AndroidManifest.xml element for this service will then look something like:

<service android:exported="true" android:name="com.xamarin.example.DemoService" />

Services have their own lifecycle with callback methods that are invoked as the service is created. Exactly which
methods are invoked depends on the type of service. A started service must implement different lifecycle methods
than a bound service, while a hybrid service must implement the callback methods for both a started service and a
bound service. These methods are all members of the Service class; how the service is started will determine
what lifecycle methods will be invoked. These lifecycle methods will be discussed in more detail later.
By default, a service will start in the same process as an Android application. It is possible to start a service in its
own process by setting the ServiceAttribute.IsolatedProcess property to true:
[Service(IsolatedProcess=true)]
public class DemoService : Service
{
// Magical code that makes the service do wonderful things, in it's own process!
}

The next step is to examine how to start a service and then move on to examine how to implement the three
different types of services.

NOTE
A service runs on the UI thread, so if any work is to be performed which blocks the UI, the service must use threads to
perform the work.

Starting A Service
The most basic way to start a service in Android is to dispatch an Intent which contains meta-data to help identify
which service should be started. There are two different styles of Intents that can be used to start a service:
Explicit Intent – An explicit Intent will identify exactly what service should be used to complete a given
action. An explicit Intent can be thought of as a letter that has a specific address; Android will route the intent
to the service that is explicitly identified. This snippet is one example of using an explicit Intent to start a
service called DownloadService :

// Example of creating an explicit Intent in an Android Activity


Intent downloadIntent = new Intent(this, typeof(DownloadService));
downloadIntent.data = Uri.Parse(fileToDownload);

Implicit Intent – This type of Intent loosely identifies the of action that the user wishes to perform, but the
exact service to complete that action is unknown. An implicit Intent can be thought of as a letter that is
addressed "To Whom It May Concern...". Android will examine the contents of the Intent, and determine if
there is an existing service which matches the intent.
An intent filter is used to help match the implicit intent with a registered service. An intent filter is an XML
element that is added to AndroidManifest.xml which contains the necessary meta-data to help match a
Service with an implicit intent.

Intent sendIntent = new Intent("common.xamarin.DemoService");


sendIntent.Data = Uri.Parse(fileToDownload);

If Android has more than one possible match for an implicit intent, then it may ask the user to select the
component to handle the action:
IMPORTANT
Starting in Android 5.0 (AP level 21) an implicit intent cannot be used to start a service.

Where possible, applications should use explicit Intents to start a service. An implicit Intent does not ask for a
specific service to start – it is a request for some service installed on the device to handle the request. This
ambiguous request can result in the wrong service handling the request or another app needlessly starting (which
increases the pressure for resources on the device).
How the Intent is dispatched depends on the type of service and will be discussed in more detail later in the guides
specific to each type of service.
Creating an Intent Filter for Implicit Intents
To associate a service with a implicit Intent, an Android app must provide some meta-data to identify the
capabilities of the service. This meta-data is provided by intent filters. Intent filters contain some information, such
as an action or a type of data, that must be present in an Intent to start a service. In Xamarin.Android, the intent
filter is registered in AndroidManifest.xml by decorating a service with the IntentFilterAttribute . For example,
the following code adds an intent filter with an associated action of com.xamarin.DemoService :

[Service]
[IntentFilter(new String[]{"com.xamarin.DemoService"})]
public class DemoService : Service
{
}

This results in an entry being included in the AndroidManifest.xml file – an entry that is packaged with the
application in a way analogous to the following example:
<service android:name="demoservice.DemoService">
<intent-filter>
<action android:name="com.xamarin.DemoService" />
</intent-filter>
</service>

With the basics of a Xamarin.Android service out of the way, let's examine the the different subtypes of services in
more detail.

Related Links
Android.App.Service
Android.App.ServiceAttribute
Android.App.Intent
Android.App.IntentFilterAttribute
Bound Services in Xamarin.Android
5/7/2018 • 11 minutes to read • Edit Online

Bound services are Android services that provide a client-server interface that a client (such as an Android Activity )
can interact with. This guide will discuss the key components involved with creating a bound service and how to
use it in a Xamarin.Android application.

Bound Services Overview


Services that provide a client-server interface for clients to directly interact with the service are referred to as
bound services. There can be multiple clients connected to a single instance of a service at the same time. The
bound service and the client are isolated from each other. Instead, Android provides a series of intermediate
objects that manage the state of the connection between the two. This state is maintained by an object that
implements the Android.Content.IServiceConnection interface. This object is created by the client and passed as a
parameter to the BindService method. The BindService is available on any Android.Content.Context object (such
as an Activity). It is a request to the Android operating system to start up the service and bind a client to it. There
are three ways to a client may bind to a service using the BindService method:
A service binder – A service binder is a class that implements the Android.OS.IBinder interface. Most
applications will not implement this interface directly, instead they will extend the Android.OS.Binder class. This
is the most common approach and is suitable for when the service and the client exist in the same process.
Using a Messenger – This technique is suitable for when the service might exist in a separate process. Instead,
service requests are marshalled between the client and service via an Android.OS.Messenger . An
Android.OS.Handler is created in the service which will handle the Messenger requests. This will be covered in
another guide.
Using AIDL – This strikes terror in the heart of most Android developers, and will not be covered in this guide.
Once a client has been bound to a service, communication between the two is occurs via Android.OS.IBinder
object. This object is responsible for the interface that will allow the client to interact with the service. It is not
necessary for each Xamarin.Android application to implement this interface from scratch, the Android SDK
provides the Android.OS.Binder class which takes care of most of the code required with marshalling the object
between the client and the service.
When a client is done with the service, it must unbind from it by calling the UnbindService method. Once the last
client has unbound from a service, Android will stop and dispose of the bound service.
This diagram illustrates how the Activity, service connection, binder, and service all related to each other:
This guide will discuss how to extend the Service class to implement a bound service. It will also cover
implementing IServiceConnection and extending Binder to allow a client to communicate with the service. A
sample app accompanies this guide, which contain a solution with a single Xamarin.Android project called
BoundServiceDemo . This is a very basic application which demonstrates how to implement a service and how
to bind an activity to it. The bound service has a very simple API with only one method, GetFormattedTimestamp ,
which returns a string that tells the user when the service has started and how long it has been running. The app
also allows the user to manually unbind and bind to the service.
Implementing and Consuming a Bound Service
There are three components that must be implemented in order for an Android application to consume a bound
service:
1. Extend the Service class and Implement the Lifecycle Callback Methods – This class will contain the
code that will perform the work that will be requested of the service. This will be covered in more detail below.
2. Create a Class that Implements IServiceConnection – This interface provides callback methods will invoked
by Android to notify the client when the connection to the service has changed, i.e. the client has connected or
disconnected to the service. The service connection will also provide a reference to an object that the client can
use to directly interact with the service. This reference is known as the binder.
3. Create a Class that Implements IBinder – A Binder implementation provides the API that a client uses to
communicate with the service. The Binder can either provide a reference to the bound service, allowing
methods to be directly invoked or the Binder can provide a client API that encapsulates and hides the bound
service from the application. An IBinder must provide the necessary code for remote procedure calls. It is not
necessary (or recommended) to implement the IBinder interface directly. Instead applications should extend
the Binder type which provides most of the base functionality required by an IBinder .
4. Starting and Binding to a Service – Once the service connection, binder, and service have been created the
Android application is responsible for starting the service and binding to it.
Each of these steps will be discussed in the following sections in more detail.
Extend the Service Class
To create a service using Xamarin.Android, it is necessary to subclass Service and to adorn the the class with the
ServiceAttribute . The attribute is used by the Xamarin.Android build tools to properly register the service in the
app's AndroidManifest.xml file Much like an activity, a bound service has it's own lifecycle and callback methods
associated with the significant events in it's lifecycle. The following list is an example of some of the more common
callback methods that a service will implement:
OnCreate – This method is invoked by Android as it is instantiating the service. It is used to initialize any
variables or objects that are required by the service during it's lifetime. This method is optional.
OnBind – This method must be implemented by all bound services. It is invoked when the first client tries to
connect to the service. It will return an instance of IBinder so that the client may interact with the service. As
long as the service is running, the IBinder object will be used to fulfill any future client requests to bind to the
service.
OnUnbind – This method is called when all bound clients have unbound. By returning true from this method,
the service will later call OnRebind with the intent passed to OnUnbind when new clients bind to it. You would do
this when a service continues running after it has been unbound. This would happen if the recently unbound
service were also a started service, and StopService or StopSelf hadn’t been called. In such a scenario,
OnRebind allows the intent to be retrieved. The default returns false , which does nothing. Optional.
OnDestroy – This method is called when Android is destroying the service. Any necessary cleanup, such as
releasing resources, should be performed in this method. Optional.
The key lifecycle events of a bound service are shown in this diagram:
The following code snippet, from the companion application that accompanies this guide, shows how to implement
a bound service in Xamarin.Android:
using Android.App;
using Android.Util;
using Android.Content;
using Android.OS;

namespace BoundServiceDemo
{
[Service(Name="com.xamarin.ServicesDemo1")]
public class TimestampService : Service, IGetTimestamp
{
static readonly string TAG = typeof(TimestampService).FullName;
IGetTimestamp timestamper;

public IBinder Binder { get; private set; }

public override void OnCreate()


{
// This method is optional to implement
base.OnCreate();
Log.Debug(TAG, "OnCreate");
timestamper = new UtcTimestamper();
}

public override IBinder OnBind(Intent intent)


{
// This method must always be implemented
Log.Debug(TAG, "OnBind");
this.Binder = new TimestampBinder(this);
return this.Binder;
}

public override bool OnUnbind(Intent intent)


{
// This method is optional to implement
Log.Debug(TAG, "OnUnbind");
return base.OnUnbind(intent);
}

public override void OnDestroy()


{
// This method is optional to implement
Log.Debug(TAG, "OnDestroy");
Binder = null;
timestamper = null;
base.OnDestroy();
}

/// <summary>
/// This method will return a formatted timestamp to the client.
/// </summary>
/// <returns>A string that details what time the service started and how long it has been running.
</returns>
public string GetFormattedTimestamp()
{
return timestamper?.GetFormattedTimestamp();
}
}
}

In the sample, the OnCreate method initializes an object that holds the logic for retrieving and formatting a
timestamp that would be requested by a client. When the first client tries to bind to the service, Android will invoke
the OnBind method. This service will instantiate a TimestampServiceBinder object that will allow the clients to
access this instance of the running service. The TimestampServiceBinder class is discussed in the next section.
Implementing IBinder
As mentioned, an IBinder object provides the communication channel between a client and a service. Android
applications should not implement the IBinder interface, the Android.OS.Binder should be extended. The Binder
class provides much of the necessary infrastructure which is necessary marshal the binder object from the service
(which may be running in a separate process) to the client. In most cases, the Binder subclass is only a few lines of
code and wraps a reference to the service. In this example, TimestampBinder has a property that exposes the
TimestampService to the client:

public class TimestampBinder : Binder


{
public TimestampBinder(TimestampService service)
{
this.Service = service;
}

public TimestampService Service { get; private set; }


}

This Binder makes it possible to invoke the public methods on the service; for example:

string currentTimestamp = serviceConnection.Binder.Service.GetFormattedTimestamp()

Once Binder has been extended, it is necessary to implement IServiceConnection to connect everything together.
Creating the Service Connection
The IServiceConnection will present|introduce|expose|connect the Binder object to the client. In addition to
implementing the IServiceConnection interface, the class must extend Java.Lang.Object . The service connection
should also provide some way that the client can access the Binder (and therefore communicate with the bound
service).
This code is from the accompanying sample project is one possible way to implement IServiceConnection :
using Android.Util;
using Android.OS;
using Android.Content;

namespace BoundServiceDemo
{
public class TimestampServiceConnection : Java.Lang.Object, IServiceConnection, IGetTimestamp
{
static readonly string TAG = typeof(TimestampServiceConnection).FullName;

MainActivity mainActivity;
public TimestampServiceConnection(MainActivity activity)
{
IsConnected = false;
Binder = null;
mainActivity = activity;
}

public bool IsConnected { get; private set; }


public TimestampBinder Binder { get; private set; }

public void OnServiceConnected(ComponentName name, IBinder service)


{
Binder = service as TimestampBinder;
IsConnected = this.Binder != null;

string message = "onServiceConnected - ";


Log.Debug(TAG, $"OnServiceConnected {name.ClassName}");

if (IsConnected)
{
message = message + " bound to service " + name.ClassName;
mainActivity.UpdateUiForBoundService();
}
else
{
message = message + " not bound to service " + name.ClassName;
mainActivity.UpdateUiForUnboundService();
}

Log.Info(TAG, message);
mainActivity.timestampMessageTextView.Text = message;

public void OnServiceDisconnected(ComponentName name)


{
Log.Debug(TAG, $"OnServiceDisconnected {name.ClassName}");
IsConnected = false;
Binder = null;
mainActivity.UpdateUiForUnboundService();
}

public string GetFormattedTimestamp()


{
if (!IsConnected)
{
return null;
}

return Binder?.GetFormattedTimestamp();
}
}
}
As a part of the binding process, Android will invoke the OnServiceConnected method, providing the name of the
service that is being bound and the binder that holds a reference to the service itself. In this example, the service
connection has two properties, one that holds a reference to the Binder and a boolean flag for if the client is
connected to the service or not.
The OnServiceDisconnected method is only invoked when the connection between a client and a service is
unexpectedly lost or broken. This method allows the client a chance to respond to the interruption in service.

Starting and Binding to a Service with an Explicit Intent


To use a bound service, a client (such as an Activity) must instantiate an object that implements
Android.Content.IServiceConnection and invoke the BindService method. BindService will return true if the
service is bound to, false if it is not. The BindService method takes three parameters:
An Intent – The Intent should explicitly identify which service to connect to.
An IServiceConnection Object – This object is an intermediary that provides callback methods to notify the
client when the bound service is started and stopped.
Android.Content.Bind enum – This parameter is a set of flags are are used by the system to when bind the
object. The most commonly used value is Bind.AutoCreate , which will automatically start the service if it isn't
already running.
The following Code snippet is an example of how to start a bound service in an Activity using an explicit intent:

protected override void OnStart ()


{
base.OnStart ();

if (serviceConnection == null)
{
this.serviceConnection = new TimestampServiceConnection(this);
}

Intent serviceToStart = new Intent(this, typeof(TimestampService));


BindService(serviceToStart, this.serviceConnection, Bind.AutoCreate);

IMPORTANT
Starting with Android 5.0 (API level 21) it is only possible to bind to a service with an explicit intent.

Architectural Notes About the Service Connection and the Binder.


Some OOP purists may disapprove of the previous implementation of the TimestampBinder class as it is a violation
of the Law of Demeter which, in it's simplest form states "Don't talk to strangers; only talk to your friends". This
particular implementation exposes the concrete TimestampService class to all clients.
Strictly speaking, it is not necessary for the client to know about the TimestampService and exposing that concrete
class to clients can make an application more brittle and harder to maintain over it's lifetime. An alternate approach
is to use an interface which exposes the GetFormattedTimestamp() method, and proxy calls to the service through
the Binder (or possible the service connection class):
public class TimestampBinder : Binder, IGetTimestamp
{
TimestampService service;
public TimestampBinder(TimestampService service)
{
this.service = service;
}

public string GetFormattedTimestamp()


{
return service?.GetFormattedTimestamp();
}
}

This particular example allow an activity to invoke methods on the service itself:

// In this example the Activity is only talking to a friend, i.e. the IGetTimestamp interface provided by the
Binder.
string currentTimestamp = serviceConnection.Binder.GetFormattedTimestamp()

Related Links
Android.App.Service
Android.Content.Bind
Android.Content.Context
Android.Content.IServiceConnection
Android.OS.Binder
Android.OS.IBinder
BoundServiceDemo (sample)
Intent Services in Xamarin.Android
4/12/2018 • 2 minutes to read • Edit Online

Intent Services Overview


Both started and bound services run on the main thread, which means that to keep performance smooth, a service
needs to perform the work asynchronously. One of the simplest ways to address this concern is with a worker
queue processor pattern, where the work to be done is placed in a queue that is serviced by a single thread.
The IntentService is a subclass of the Service class that provides an Android specific implementation of this
pattern. It will manage queueing work, starting up a worker thread to service the queue, and pulling requests off
the queue to be run on the worker thread. An IntentService will quietly stop itself and remove the worker thread
when there is no more work in the queue.
Work is submitted to the queue by creating an Intent and then passing that Intent to the StartService method.
It is not possible to stop or interrupt the OnHandleIntent method IntentService while it is working. Because of this
design, an IntentService should be kept stateless – it should not rely on an active connection or communication
from the rest of the application. An IntentService is meant to statelessly process the work requests.
There are two requirements for subclassing IntentService :
1. The new type (created by subclassing IntentService ) only overrides the OnHandleIntent method.
2. The constructor for the new type requires a string which is used to name the worker thread that will handle the
requests. The name of this worker thread is primarily used when debugging the application.
The following code shows an IntentService implementation with the overridden OnHandleIntent method:

[Service]
public class DemoIntentService: IntentService
{
public DemoIntentService () : base("DemoIntentService")
{
}

protected override void OnHandleIntent (Android.Content.Intent intent)


{
Console.WriteLine ("perform some long running work");
...
Console.WriteLine ("work complete");
}
}

Work is sent to an IntentService by instantiating an Intent and then calling the StartService method with that
Intent as a parameter. The Intent will be passed to the service as a parameter in the OnHandleIntent method. This
code snippet is an example of sending a work request to an Intent:
// This code might be called from within an Activity, for example in an event
// handler for a button click.
Intent downloadIntent = new Intent(this, typeof(DemoIntentService));

// This is just one example of passing some values to an IntentService via the Intent:
downloadIntent.Put
("file_to_download", "http://www.somewhere.com/file/to/download.zip");

StartService(downloadIntent);

The IntentService can extract the values from the Intent, as demonstrated in this code snippet:

protected override void OnHandleIntent (Android.Content.Intent intent)


{
string fileToDownload = intent.GetStringExtra("file_to_download");

Log.Debug("DemoIntentService", $"File to download: {fileToDownload}.");


}

Related Links
IntentService
StartService
Started Services with Xamarin.Android
4/12/2018 • 5 minutes to read • Edit Online

Started Services Overview


Started services typically perform a unit of work without providing any direct feedback or results to the client. An
example of a unit of work is a service that uploads a file to a server. The client will make a request to a service to
upload a file from the device to a website. The service will quietly upload the file (even if the app has no Activities in
the foreground), and terminate itself when the upload is finished. It is important to realize that a started service will
run on the UI thread of an application. This means that if a service is to perform work that will block the UI thread,
it must create and dispose of threads as necessary.
Unlike a bound service, there is no communication channel between a "pure" started service and its clients. This
means that a started service will implement some different lifecycle methods than a bound service. The following
list highlights the common lifecycle methods in a started service:
OnCreate – Called one time when the service is first started. This is where initialization code should be
implemented.
OnBind – This method must be implemented by all service classes, however a started service does not typically
have a client bound to it. Because of this, a started service just returns null . In contrast, a hybrid service (which
is the combination of a bound service and a started service) has to implement and return a Binder for the
client.
OnStartCommand – Called for each request to start the service, either in response to a call to StartService or a
restart by the system. This is where the service can begin any long-running task. The method returns a
StartCommandResult value that indicates how or if the system should handle restarting the service after a
shutdown due to low memory. This call takes place on the main thread. This method is described in more detail
below.
OnDestroy – This method is called when the Service is being destroyed. It is used to perform any final clean up
required.
The important method for a started service is the OnStartCommand method. It will be invoked each time the service
receives a request to do some work. The following code snippet is an example of OnStartCommand :

public override StartCommandResult OnStartCommand (Android.Content.Intent intent, StartCommandFlags flags, int


startId)
{
// This method executes on the main thread of the application.
Log.Debug ("DemoService", "DemoService started");
...
return StartCommandResult.Sticky;
}

The first parameter is an Intent object containing the meta-data about the work to perform. The second
parameter contains a StartCommandFlags value that provides some information about the method call. This
parameter has one of two possible values:
StartCommandFlag.Redelivery – This means that the Intent is a re-delivery of a previous Intent . This value is
provided when the service had returned StartCommandResult.RedeliverIntent but was stopped before it could be
properly shut down.
StartCommandFlag.Retry - This value is received when a previous OnStartCommand call failed and Android is
trying to start the service again with the same intent as the previous failed attempt.
Finally, the third parameter is an integer value that is unique to the application that identifies the request. It is
possible that multiple callers may invoke the same service object. This value is used to associate a request to stop a
service with a given request to start a service. It will be discussed in more detail in the section Stopping the Service.
The value StartCommandResult is returned by the service as a suggestion to Android on what to do if the service is
killed due to resource constraints. There are three possible values for StartCommandResult :
StartCommandResult.NotSticky – This value tells Android that it is not necessary to restart the service that it
has killed. As an example of this, consider a service that generates thumbnails for a gallery in an app. If the
service is killed, it isn't crucial to recreate the thumbnail immediately – the thumbnail can be recreated the next
time the app is run.
StartCommandResult.Sticky – This tells Android to restart the Service, but not to deliver the last Intent that
started the Service. If there are no pending Intents to handle, then a null will be provided for the Intent
parameter. An example of this might be a music player app; the service will restart ready to play music, but it
will play the last song.
StartCommandResult.RedeliverIntent – This value is will tell Android to restart the service and re-deliver the
last Intent . An example of this is a service that downloads a data file for an app. If the service is killed, the data
file still needs to be downloaded. By returning StartCommandResult.RedeliverIntent , when Android restarts the
service it will also provide the Intent (which holds the URL of the file to download) to the service. This will
enable the download to either restart or resume (depending on the exact implementation of the code).
There is a fourth value for StartCommandResult – StartCommandResult.ContinuationMask . This value is returned by
OnStartCommand and it describes how Android will continue the service it has killed. This value isn't typically used to
start a service.
The key lifecycle events of a started service are shown in this diagram:
Stopping the Service
A started service will keep running indefinitely; Android will keep the service running as long as there are sufficient
system resources. Either the client must stop the service, or the service may stop itself when it is done its work.
There are two ways to stop a service:
Android.Content.Context.StopService() – A client (such as an Activity) can request a service stop by
calling the StopService method:

StopService(new Intent(this, typeof(DemoService));

Android.App.Service.StopSelf() – A service may shut itself down by invoking the StopSelf :


StopSelf();

Using startId to Stop a Service


Multiple callers can request that a service be started. If there is an outstanding start request, the service can use the
startId that is passed into OnStartCommand to prevent the service from being stopped prematurely. The startId
will correspond to the latest call to StartService , and will be incremented each time it is called. Therefore, if a
subsequent request to StartService has not yet resulted in a call to OnStartCommand , the service can call
StopSelfResult , passing it the latest value of startId it has received (instead of simply calling StopSelf ). If a call
to StartService has not yet resulted in a corresponding call to OnStartCommand , the system will not stop the
service, because the startId used in the StopSelf call will not correspond to the latest StartService call.

Related Links
StartedServicesDemo (sample)
Android.App.Service
Android.App.StartCommandFlags
Android.App.StartCommandResult
Android.Content.BroadcastReceiver
Android.Content.Intent
Android.OS.Handler
Android.Widget.Toast
Status Bar Icons
Foreground Services
7/11/2018 • 3 minutes to read • Edit Online

A foreground service is a special type of a bound service or a started service. Occasionally services will perform
tasks that users must be actively aware of, these services are known as foreground services. An example of a
foreground service is an app that is providing the user with directions while driving or walking. Even if the app is in
the background, it is still important that the service has sufficient resources to work properly and that the user has
a quick and handy way to access the app. For an Android app, this means that a foreground service should receive
higher priority than a "regular" service and a foreground service must provide a Notification that Android will
display as long as the service is running.
To start a foreground service, the app must dispatch an Intent that tells Android to start the service. Then the
service must register itself as a foreground service with Android. Apps that are running on Android 8.0 (or higher)
should use the Context.StartForegroundService method to start the service, while apps that are running on devices
with an older version of Android should use Context.StartService
This C# extension method is an example of how to start a foreground service. On Android 8.0 and higher it will use
the StartForegroundService method, otherwise the older StartService method will be used.

public static void StartForegroundServiceComapt<T>(this Context context, Bundle args = null) where T : Service
{
var intent = new Intent(context, typeof(T));
if (args != null)
{
intent.PutExtras(args);
}

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)


{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
}

Registering as a Foreground Service


Once a foreground service has started, it must register itself with Android by invoking the StartForeground . If the
service is started with the Service.StartForegroundService method but does not register itself, then Android will
stop the service and flag the app as non-responsive.
StartForeground takes two parameters, both of which are mandatory:
An integer value that is unique within the application to identify the service.
A Notification object that Android will display in the status bar for as long as the service is running.
Android will display the notification in the status bar for as long as the service is running. The notification, at
minimum, will provide a visual cue to the user that the service is running. Ideally, the notification should provide
the user with a shortcut to the application or possibly some action buttons to control the application. An example of
this is a music player – the notification that is displayed may have buttons to pause/play music, to rewind to the
previous song, or to skip to the next song.
This code snippet is an example of registering a service as a foreground service:

// This is any integer value unique to the application.


public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)


{
// Code not directly related to publishing the notification has been omitted for clarity.
// Normally, this method would hold the code to be run when the service is started.

var notification = new Notification.Builder(this)


.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.ic_stat_name)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.AddAction(BuildRestartTimerAction())
.AddAction(BuildStopServiceAction())
.Build();

// Enlist this instance of the service as a foreground service


StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
}

The previous notification will display a status bar notification that that is similar to the following:

This screenshot shows the expanded notification in the notification tray with two actions that allow the user to
control the service:
More information about notifications is available in the Local Notifications section of the Android Notifications
guide.

Unregistering as a Foreground Service


A service can de-list itself as a foreground service by calling the method StopForeground . StopForeground will not
stop the service, but it will remove the notification icon and signals Android that this service can be shut down if
necessary.
The status bar notification that is displayed can also be removed by passing true to the method:

StopForeground(true);

If the service is halted with a call to StopSelf or StopService , the status bar notification will be removed.

Related Links
Android.App.Service
Android.App.Service.StartForeground
Local Notifications
ForegroundServiceDemo (sample)
Running Android Services in Remote Processes
4/12/2018 • 26 minutes to read • Edit Online

Generally, all components in an Android application will run in the same process. Android services are a notable
exception to this in that they can be configured to run in their own processes and shared with other applications,
including those from other Android developers. This guide will discuss how to create and use an Android remote
service using Xamarin.

Out of Process Services Overview


When an application starts up, Android creates a process in which to run the application. Typically, all the
components the application will run in this one process. Android services are a notable exception to this in that
they can be configured to run in their own processes and shared with other applications, including those from
other Android developers. These types of services are referred to as remote services or out-of-process services. The
code for these services will be contained in the same APK as the main application; however, when the service is
started Android will create a new process for just that service. In contrast, a service that runs in the same process
as the rest of the application is sometimes referred to as a local service.
In general, it is not necessary for an application to implement a remote service. A local service is sufficient (and
desirable) for an app's requirements in many cases. An out-of-process has it's own memory space which must be
managed by Android. Although this does introduce more overhead to the overall application, there are some
scenarios where it can be advantageous to run a service in its own process:
1. Sharing Functionality – Some application developers may have multiple apps and functionality that is
shared between all the applications. Packaging that functionality in an Android service which runs in its own
process may simplify application maintenance. It is also possible to package the service in its own stand-
alone APK and deploy it separately from the rest of the application.
2. Improving the User Experience – There are two possible ways that an out-of-process service can improve
the user experience of the application. The first way deals with memory management. When a garbage
collection (GC ) cycle occurs, Android will pause all activity in the process until the GC is complete. The user
might perceive this pause as a "stutter" or "jank". When a service is running in it's own process, it is the
service process that is paused, not the application process. This pause will be much less noticeable to the
user as the application process (and therefore the user interface) is not paused.
Secondly, if the memory requirements of a process becomes too large, Android may kill that process to free
up resources for the device. If a service does have a large memory footprint and it is running in the same
process as the UI, then when Android forcibly reclaims those resources the UI will be shut down, forcing the
user to start the app. However, if a service, running in its own process is shut down by Android, the UI
process remains unaffected. The UI can bind (and restart) the service, transparent to the user, and resume
normal functioning.
3. Improving Application Performance – The UI process may be terminated or shut down independent of
the service process. By moving lengthy startup tasks to an out-of-process service, it is possible that the
startup time of the UI maybe improved (assuming that the service process is kept alive in between the times
that UI is launched).
In many ways, binding to a service running in another process is the same as binding to a local service. The client
will invoke BindService to bind (and start, if necessary) the service. An Android.OS.IServiceConnection object will
be created to manage the connection between the client and the service. If the client successfully binds to the
service, then Android will return an object via the IServiceConnection that can be used to invoke methods on the
service. The client then interacts with the service using this object. To review, here are the steps to bind to a service:
Create an Intent – An explicit intent must be used to binding to the service.
Implement and Instantiate an IServiceConnection object – The IServiceConnection object acts as an
intermediary between the client and the service. It is responsible for monitoring the connection between client
and server.
Invoke the BindService method – Calling BindService will dispatch the intent and the service connection
created in the previous steps to Android, which will take care of starting the service and establishing
communication between client and service.
The need to cross process boundaries does introduce extra complexity: the communication is one-way (client to
server) and the client can't directly invoke methods on the service class. Recall that when a service is running the
same process as the client, Android provides an IBinder object which may allow for two-way communication. This
is not the case with service running in its own process. A client communicates with a remote service with the the
help of the Android.OS.Messenger class.
When a client requests to bind with the remote service, Android will invoke the Service.OnBind lifecycle method,
which will return the internal IBinder object that is encapsulated by the Messenger . The Messenger is a thin
wrapper over a special IBinder implementation that is provided by the Android SDK. The Messenger takes care of
the communication between the two different processes. The developer is unconcerned with the details of
serializing a message, marshalling the message across the process boundary, and then deserializing it on the client.
This work is handled by the Messenger object. This diagram shows the client-side Android components that are
involved when a client initiates binding to an out-of-process service:
The Service class in the remote process will go through the same lifecycle callbacks that a bound service in a local
process will go through, and many of the APIs involved are the same. Service.OnCreate is used to initialize a
Handler and inject that into Messenger object. Likewise, OnBind is overridden, but instead of returning an
IBinder object, the service will return the Messenger . This diagram illustrates what happens in the service when a
client is binding to it:
When a Message is received by a service, it is processed by in instance of Android.OS.Handler . The service will
implement its own Handler subclass that must override the HandleMessage method. This method is invoked by the
Messenger and receives the Message as a parameter. The Handler will inspect the Message meta-data and use that
information to invoke methods on the service.
One-way communication occurs when a client creates a Message object and dispatches it to the service using the
Messenger.Send method. Messenger.Send will serialize the Message and hand that serialized data off to Android,
which will route the message across the process boundary and to the service. The Messenger that is hosted by the
service will create a Message object from the incoming data. This Message is placed into a queue, where messages
are submitted one at a time to the Handler . The Handler will inspect the meta-data contained in the Message and
invoke the appropriate methods on the Service . The following diagram illustrates these various concepts in action:

This guide will discuss the details of implementing an out-of-process service. It will discuss how to implement a
service that is meant to run in its own process and how a client may communicate with that service using the
Messenger framework. It will also briefly discuss two-way communication: the client sending a message to a
service and the service sending a message back to the client. Because services can be shared between different
applications, this guide will also discuss one technique for limiting client access to the service by using Android
permissions.

IMPORTANT
Bugzilla 51940 - Services with isolated processes and custom Application class fail to resolve overloads properly reports that
a Xamarin.Android service will not start up properly when the IsolatedProcess is set to true . This guide is provided for a
reference. A Xamarin.Android application should still be able to communicate with an out-of-process service that is written in
Java.

Requirements
This guide assumes familiarity with creating services.
Although it is possible to use implicit intents with apps that target older Android APIs, this guide will focus
exclusively on the use of explicit intents. Apps targeting Android 5.0 (API level 21) or higher must use an explicit
intent to bind with a service; this is the technique that will be demonstrated in this guide..

Create a Service that Runs in a Separate Process


As described above, the fact that a service is running in its own process means that some different APIs are
involved. As a quick overview, here are the steps to bind with and consume a remote service:
Create the Service subclass – Subclass the Service type and implement the lifecycle methods for a bound
service. It is also necessary to set meta-data that will inform Android that the service is to run in its own
process.
Implement a Handler – The Handler is responsible for analyzing the client requests, extracting any
parameters that were passed from the client, and invoking the appropriate methods on the service.
Instantiate a Messenger – As described above, each Service must maintain an instance of the Messenger
class that will route client requests to the Handler that was created in the previous step.
A service that is meant to run in its own process is, fundamentally, still a bound service. The service class will
extend the base Service class and is decorated with the ServiceAttribute containing the meta-data that Android
needs to bundle in the Android manifest. To begin with, the following properties of the ServiceAttribute that are
important to an out-of-process service:
1. Exported – This property must be set to true to allow other applications to interact with the service. The
default value of this property is false .
2. Process – This property must be set. It is used to specify the name of the process that the service will run in.
3. IsolatedProcess – This property will enable extra security, telling Android to run the service in an isolated
sandbox with minimal permission to iteract with the rest of the system. See Bugzilla 51940 - Services with
isolated processes and custom Application class fail to resolve overloads properly.
4. Permission – It is possible to control client access to the service by specifying a permission that clients must
request (and be granted).
To run a service its own process, the Process property on the ServiceAttribute must be set to the name of the
service. To interact with outside applications, the Exported property should be set to true . If Exported is false ,
then only clients in the same APK (i.e. the same application) and running in the same process will be able to interact
with the service.
What kind of process the service will run in depends on the value of the Process property. Android identifies three
different types of processes:
Private Process – A private process is one that is only available to the application that started it. To identify
a process as private, its name must start with a : (semi-colon). The service depicted in the previous code
snippet and screenshot is a private process. The following code snippet is an example of the
ServiceAttribute :

[Service(Name = "com.xamarin.TimestampService",
Process=":timestampservice_process",
Exported=true)]

Global Process – A service that is run in a global process is accessible to all applications running on the
device. A global process must be a fully qualified class name that starts with a lower case character. (Unless
steps are taken to secure the service, other applications may bind and interact with it. Securing the service
against unauthorized use will be discussed later in this guide.)

[Service(Name = "com.xamarin.TimestampService",
Process="com.xamarin.xample.messengerservice.timestampservice_process",
Exported=true)]

Isolated Process – An isolated process is a process that runs in its own sandbox, isolated from the rest of
the system and with no special permissions of its own. To run a service in an isolated process, the
IsolatedProcess property of the ServiceAttribute is set to true as shown in this code snippet:
[Service(Name = "com.xamarin.TimestampService",
IsolatedProcess= true,
Process="com.xamarin.xample.messengerservice.timestampservice_process",
Exported=true)]

IMPORTANT
See Bugzilla 51940 - Services with isolated processes and custom Application class fail to resolve overloads properly

An isolated service is a simple way to secure an application and the device against untrusted code. For example, an
app may download and execute a script from a website. In this case, performing this in an isolated process provides
an additional layer of security against untrusted code compromising the Android device.

IMPORTANT
Once a service has been exported, the name of the service should not change. Changing the name of the service may break
other applications that are using the service.

To see the effect that the Process property has, the following screenshot shows a service running in its own
private process:

This next screenshot shows Process="com.xamarin.xample.messengerservice.timestampservice_process" and the


service running in a global process:
Once the ServiceAttribute has been set, the service needs to implement a Handler .
Implementing a Handler
To process client requests, the service must implement a Handler and override the HandleMessage methodThis is
the method takes a Message instance which which encapsulates the method call from the client and translates that
call into some action or task that the service will perform. The Message object exposes a property called What
which is an integer value, the meaning of which is shared between the client and the service and relates to some
task that the service is to perform for the client.
The following code snippet from the sample application shows one example of HandleMessage . In this example,
there are two actions that a client can request of the service:
The first action is a Hello, World message, the client has sent a simple message to the service.
The second action will invoke a method on the service and retrieve a string, in this case the string is a message
that returns what time the service started and how long it has been running:
public class TimestampRequestHandler : Android.OS.Handler
{
// other code omitted for clarity

public override void HandleMessage(Message msg)


{
int messageType = msg.What;
Log.Debug(TAG, $"Message type: {messageType}.");

switch (messageType)
{
case Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE:
// The client as sent a simple Hello, say in the Android Log.
break;

case Constants.GET_UTC_TIMESTAMP:
// Call methods on the service to retrive a timestamp message.
break;
default:
Log.Warn(TAG, $"Unknown messageType, ignoring the value {messageType}.");
base.HandleMessage(msg);
break;
}
}
}

It is also possible to package parameters for the service in the Message . This will be discussed later in this guide.
The next topic to consider is creating the Messenger object to process the incoming Message s.
Instantiating the Messenger
As previously discussed, deserializing the Message object and invoking Handler.HandleMessage is the responsibilty
of the Messenger object. The Messenger class also provides an IBinder object that the client will use to send
messages to the service.
When the service starts, it will instantiate the Messenger and inject the Handler . A good place to perform this
initialization is on the OnCreate method of the service. This code snippet is one example of a service that initializes
its own Handler and Messenger :

private Messenger messenger; // Instance variable for the Messenger

public override void OnCreate()


{
base.OnCreate();
messenger = new Messenger(new TimestampRequestHandler(this));
Log.Info(TAG, $"TimestampService is running in process id {Android.OS.Process.MyPid()}.");
}

At this point, the final step is for the Service to override OnBind .
Implementing Service.OnBind
All bound services, whether they run in their own process or not, must implement the OnBind method. The return
value of this method is some object that the client can use to interact with the service. Exactly what that object is
depends whether the service is a local service or a remote service. While a local service will return a custom
IBinder implementation, a remote service will return the IBinder that is encapsulated but the Messenger that
was created in the previous section:
public override IBinder OnBind(Intent intent)
{
Log.Debug(TAG, "OnBind");
return messenger.Binder;
}

Once these three steps are accomplished, the remote service can be considered complete.

Consuming the Service


All clients must implement some code to be able to bind and consume the remote service. Conceptually, from the
client's viewpoint, there are very few differences between binding to local service or a remote service. The client
invokes the BindService method, passing an explicit intent to identify the service and an IServiceConnection that
helps manage the connection between the client and the service.
This code snippet is an example of how to create an explicit intent for binding to a remote service. The intent
must identify the package that contains the service and the name of the service. One way to set this information is
to use an Android.Content.ComponentName object and to provide that to the intent. This code snippet is one example:

// This is the package name of the APK, set in the Android manifest
const string REMOTE_SERVICE_COMPONENT_NAME = "com.xamarin.TimestampService";
// This is the name of the service, according the value of ServiceAttribute.Name
const string REMOTE_SERVICE_PACKAGE_NAME = "com.xamarin.xample.messengerservice";

// Provide the package name and the name of the service with a ComponentName object.
ComponentName cn = new ComponentName(REMOTE_SERVICE_PACKAGE_NAME, REMOTE_SERVICE_COMPONENT_NAME);
Intent serviceToStart = new Intent();
serviceToStart.SetComponent(cn);

When the service is bound, the IServiceConnection.OnServiceConnected method is invoked and provides an
IBinder to a client. However, the client will not directly use the IBinder . Instead, it will instantiate a Messenger
object from that IBinder . This is the Messenger that the client will use to interact with the remote service.
The following is an example of a very basic IServiceConnection implementation that demonstrates how a client
would handle connecting to and disconnecting from a service. Notice that the OnServiceConnected method receives
and IBinder , and the client creates a Messenger from that IBinder :
public class TimestampServiceConnection : Java.Lang.Object, IServiceConnection
{
static readonly string TAG = typeof(TimestampServiceConnection).FullName;

MainActivity mainActivity;
Messenger messenger;

public TimestampServiceConnection(MainActivity activity)


{
IsConnected = false;
mainActivity = activity;
}

public bool IsConnected { get; private set; }


public Messenger Messenger { get; private set; }

public void OnServiceConnected(ComponentName name, IBinder service)


{
Log.Debug(TAG, $"OnServiceConnected {name.ClassName}");

IsConnected = service != null


Messenger = new Messenger(service);

if (IsConnected)
{
// things to do when the connection is successful. perhaps notify the client? enable UI features?
}
else
{
// things to do when the connection isn't successful.
}
}

public void OnServiceDisconnected(ComponentName name)


{
Log.Debug(TAG, $"OnServiceDisconnected {name.ClassName}");
IsConnected = false;
Messenger = null;

// Things to do when the service disconnects. perhaps notify the client? disable UI features?

}
}

Once the service connection and the intent are created, it is possible for the client to call BindService and initiate
the binding process:

IServiceConnection serviceConnection = new TimestampServiceConnection(this);


BindActivity(serviceToStart, serviceConnection, Bind.AutoCreate);

After the client has successfully bound to the service and the Messenger is available, it is possible for the client to
send Messages to the service.

Sending Messages to the Service


Once the client is connected and has a Messenger object, it is possible to communicate with the service by
dispatching Message objects via the Messenger . This communication is one-way, the client sends the message but
there is no return message from the service to the client. In this regard, the Message is a fire-and-forget
mechanism.
The preferred way to create a Message object is to use the Message.Obtain factory method. This method will pull a
Message object from a global pool that is maintained by Android. Message.Obtain also has some overloaded
methods that allow the Message object to be initialized with the values and parameters required by the service.
Once the Message is instantiated, it dispatched to the service by calling Messenger.Send . This snippet is one
example of creating and dispatching a Message to the service process:

Message msg = Message.Obtain(null, Constants.SAY_HELLO_TO_TIMESTAMP_SERVICE);


try
{
serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
Log.Error(TAG, ex, "There was a error trying to send the message.");
}

There are several different forms of the Message.Obtain method. The previous example uses the
Message.Obtain(Handler h, Int32 what) . Because this is an asynchronous request to an out-of-process service; there
will be no response from the service, so the Handler is set to null . The second parameter, Int32 what , will be
stored in the .What property of the Message object. The .What property is used by code in the service process to
invoke methods on the service.
The Message class also exposes two additional properties that may be of use to the recipent: Arg1 and Arg2 .
These two properties are integer values that may have some special agreed upon values that have meaning
between the client and the service. For example, Arg1 may hold a customer ID and Arg2 may hold a purchase
order number for that customer. The Method.Obtain(Handler h, Int32 what, Int32 arg1, Int32 arg2) can be used to
set the two properties when the Message is created. Another way to populate these two values is to set the .Arg
and .Arg2 properties directly on the Message object after it has been created.
Passing Additional Values to the Service
It is possible to pass more complex data to the service by using a Bundle . In this case, extra values can be placed in
a Bundle and sent along with the Message by setting the .Data property property before sending.

Bundle serviceParameters = new Bundle();


serviceParameters.

var msg = Message.Obtain(null, Constants.SERVICE_TASK_TO_PERFORM);


msg.Data = serviceParameters;

messenger.Send(msg);

NOTE
In general, a Message should not have a payload larger than 1MB. The size limit may vary according the version of Android
and on any proprietary changes the vendor might have made to their implementation of the Android Open Source Project
(AOSP) that is bundled with the device.

Returning Values from the Service


The messaging architecture that has been discussed to this point is one-way, the client sends a message to the
service. If it is necessary for the service to return a value to a client then everything that has been discussed to this
point is reversed. The service must create a Message , packaged any return values, and dispatch the Message via a
Messenger to the client. However, the service does not create its own Messenger ; instead, it relies on the client
instantiating and package a Messenger as part of the initial request. The service will Send the message using this
client-provided Messenger .
The sequence of events for two-way communication is this:
1. The client binds to the service. When the service and the client connect, the IServiceConnection that is
maintained by the client will have a reference to a Messenger object that is used to transmit Message s to the
service. To avoid confusion, this will be referred to as the Service Messenger.
2. Client instantiates a Handler (referred to as the Client Handler) and uses that to initialize its own Messenger
(the Client Messenger). Note that the Service Messenger and the Client Messenger are two different objects
that handle traffic in two different directions. The Service Messenger handles messages from the client to the
service, while the Client Messenger will handle messages from the service to the client.
3. The client creates a Message object, and sets the ReplyTo property with the Client Messenger. The message is
then sent to the service using the Service Messenger.
4. The service receives the message from the client, and performs the requested work.
5. When it is time for the service to send the response to the client, it will use Message.Obtain to create a new
Message object.
6. To send this message to the client, the service will extract the Client Messenger from the .ReplyTo property of
the client message and use that to .Send the Message back to the client.
7. When the response is received by the client, it has its own Handler that will process the Message by inspecting
the .What property (and if necessary, extracting any parameters contained by the Message ).

This sample code demonstrates how the client will instantiate the Message and package a Messenger that the
service should use for its response:

Handler clientHandler = new ActivityHandler();


Messenger clientMessenger = new Messenger(activityHandler);

Message msg = Message.Obtain(null, Constants.GET_UTC_TIMESTAMP);


msg.ReplyTo = clientMessenger;

try
{
serviceConnection.Messenger.Send(msg);
}
catch (RemoteException ex)
{
Log.Error(TAG, ex, "There was a problem sending the message.");
}

The service must make some changes to its own Handler to extract the Messenger and use that to send replies to
the client. This code snippet is an example of how the service's Handler would create a Message and send it back
to the client:
// This is the message that the service will send to the client.
Message responseMessage = Message.Obtain(null, Constants.RESPONSE_TO_SERVICE);
Bundle dataToReturn = new Bundle();
dataToReturn.PutString(Constants.RESPONSE_MESSAGE_KEY, "This is the result from the service.");
responseMessage.Data = dataToReturn;

// The msg object here is the message that was received by the service. The service will not instantiate a
client,
// It will use the client that is encapsulated by the message from the client.
Messenger clientMessenger = msg.ReplyTo;
if (clientMessenger!= null)
{
try
{
clientMessenger.Send(responseMessage);
}
catch (Exception ex)
{
Log.Error(TAG, ex, "There was a problem sending the message.");
}
}

Note that in the code samples above, the Messenger instance that is created by the client is not the same object that
is received by the service. These are two different Messenger objects running in two separate processes that
represent the communication channel.

Securing the Service with Android Permissions


A service that runs in a global process is accessible by all applications running on that Android device. In some
situations, this openness and availability is undesirable, and it is necessary to secure the service against access from
unauthorized clients. One way to limit access to the remote service is to use Android Permissions.
Permissions can be identified by the Permission property of the ServiceAttribute that decorates the Service
sub-class. This will name a permission that the client must be granted when binding to the service. If the client does
not have the appropriate permissions, then Android will throw a Java.Lang.SecurityException when the client tries
to bind to the service.
There are four different permission levels that Android provides:
normal – This is the default permission level. It is used to identify low -risk permissions that can be
automatically granted by Android to clients that request it. The user does not have to explicitly grant these
permissions, but the permissions can be viewed in the app settings.
signature – This is a special category of permission that will be granted automatically by Android to
applications that are all signed with the same certificate. This permission is designed to make it easily for an
application developer to share components or data between their apps without bothering the user for constant
approvals.
signatureOrSystem – This is very similar to the signature permissions described above. In addition to being
automatically granted to apps that are signed by the same certificate, this permission will also be granted to
apps that are signed the same certificate that was used to sign the apps installed with the Android system
image. This permission is typically only used by Android ROM developers to allow their applications to work
with third party apps. It is not commonly used by apps that are meant general distribution for the public at
large.
dangerous – Dangerous permissions are those that could cause problems for the user. For this reason,
dangerous permissions must be explicitly approved by the user.
Because signature and normal permissions are automatically granted at installed time by Android, it is crucial
that APK hosting the service be installed before the APK containing the client. If the client is installed first, Android
will not grant the permissions. In this case, it will be necessary to uninstall the client APK, install the service APK,
and then re-install the client APK.
There are two common ways to secure a service with Android permissions:
1. Implement signature level security – Signature level security means that permission is automatically
granted to those applications that are signed with the same key that was used to sign the APK holding the
service. This is a simple way for developers to secure their service yet keep them accessible from their own
applications. Signature level permissions are declared by setting the Permission property of the
ServiceAttribute to signature :

[Service(Name = "com.xamarin.TimestampService",
Process="com.xamarin.TimestampService.timestampservice_process",
Permission="signature")]
public class TimestampService : Service
{
}

2. Create a custom permission – It is possible for the developer of the service to create a custom permission
for the service. This is best for when a developer wants to share their service with applications from other
developers. A custom permission requires a bit more effort to implement and will be covered below.
A simplified example of creating a custom normal permission will be described in the next section. For more
information about Android permissions, please consult Google's documentation for Best Practices & Security. For
more information about Android permissions, see the Permissions section of the Android documentation for the
application manifest for more information about Android permissions.

NOTE
In general, Google discourages the use of custom permissions as they may prove confusing to users.

Creating a Custom Permission


To use a custom permission, it is declared by the service while the client explicitly requests that permission.
To create a permission in the service APK, a permission element is added to the manifest element in
AndroidManifest.xml. This permission must have the name , protectionLevel , and label attributes set. The
name attribute must be set to a string that uniquely identifies the permission. The name will be displayed in the
App Info view of the Android Settings (as shown in the next section).
The protectionLevel attribute must be set to one of the four string values that were described above. The label
and description must refer to string resources and are used to provide a user-friendly name and description to
the user.
This snippet is an example of declaring a custom permission attribute in AndroidManifest.xml of the APK that
contains the service:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.xamarin.xample.messengerservice">

<uses-sdk android:minSdkVersion="21" />

<permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP"
android:protectionLevel="signature"
android:label="@string/permission_label"
android:description="@string/permission_description"
/>

<application android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme">

</application>
</manifest>

Then, the AndroidManifest.xml of the client APK must explicitly request this new permission. This is done by
adding the users-permission attribute to the AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.xamarin.xample.messengerclient">

<uses-sdk android:minSdkVersion="21" />

<uses-permission android:name="com.xamarin.xample.messengerservice.REQUEST_TIMESTAMP" />

<application
android:allowBackup="true"
android:icon="@mipmap/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme">
</application>
</manifest>

View the Permissions Granted to an App


To view the permissions that an application has been granted, open the Android Settings app, and select Apps.
Find and select the application in the list. From the App Info screen, tap Permissions which will bring up a view
that shows all the permissions granted to the app:
Summary
This guide was an advanced discussion about how to run an Android service in a remote process. The differences
between a local and a remote service was explained, along with some reasons why a remote service can be helpful
to stability and performance of an Android app. After explaining how to implement a remote service and how a
client can communicate with the service, the guide went on to provide one way to limit access to the service from
only authorized clients.

Related Links
Handler
Message
Messenger
ServiceAttribute
The Exported attribute
Services with isolated processes and custom Application class fail to resolve overloads properly
Processes and Threads
Android Manifest - Permissions
Security Tips
MessengerServiceDemo (sample)
Service Notifications
4/12/2018 • 2 minutes to read • Edit Online

This guide discusses how an Android service may use local notifications to dispatch information to a user.

Service Notifications Overview


Service notifications allow an app to display information to the user, even if the Android application is not in the
foreground. It is possible for a notification to provide actions for the user, such as displaying an Activity from an
application. The following code sample demonstrates how a service might dispatch a notification to a user:

[Service]
public class MyService: Service
{
// A notification requires an id that is unique to the application.
const int NOTIFICATION_ID = 9000;

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)


{
// Code omitted for clarity - here is where the service would do something.

// Work has finished, now dispatch anotification to let the user know.
Notification.Builder notificationBuilder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.ic_notification_small_icon)
.SetContentTitle(Resources.GetString(Resource.String.notification_content_title))
.SetContentText(Resources.GetString(Resource.String.notification_content_text));

var notificationManager = (NotificationManager)GetSystemService(NotificationService);


notificationManager.Notify(NOTIFICATION_ID, notificationBuilder.Build());
}
}

This screenshot is an example of the notification that is displayed:

When the user slides down the notification screen from the top, the full notification is displayed:
Updating A Notification
To update a notification, the service will republish the notification using the same notification ID. Android will
display or update the notification in the status bar as necessary.
void UpdateNotification(string content)
{
var notification = GetNotification(content, pendingIntent);

NotificationManager notificationManager =
(NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(NOTIFICATION_ID, notification);
}

Notification GetNotification(string content, PendingIntent intent)


{
return new Notification.Builder(this)
.SetContentTitle(tag)
.SetContentText(content)
.SetSmallIcon(Resource.Drawable.NotifyLg)
.SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.Icon))
.SetContentIntent(intent).Build();
}

More information about notifications is available in the Local Notifications section of the Android Notifications
guide.

Related Links
Local Notifications in Android
Broadcast Receivers in Xamarin.Android
6/25/2018 • 8 minutes to read • Edit Online

This section discusses how to use a Broadcast Receiver.

Broadcast Receiver Overview


A broadcast receiver is an Android component that allows an application to respond to messages (an Android
Intent ) that are broadcast by the Android operating system or by an application. Broadcasts follow a publish-
subscribe model – an event causes a broadcast to be published and received by those components that are
interested in the event.
Android identifies two types of broadcasts:
Explicit broadcast – These types of broadcasts target a specific application. The most common use of an
explicit broadcast is to start an Activity. An example of an explicit broadcast when an app needs to dial a phone
number; it will dispatch an Intent that targets the Phone app on Android and pass along the phone number to
be dialed. Android will then route the intent to the Phone app.
Implicit broadcast – These broadcasts are dispatched to all apps on the device. An example of an implicit
broadcast is the ACTION_POWER_CONNECTED intent. This intent is published each time Android detects that the
battery on the device is charging. Android will route this intent to all apps that have registered for this event.
The broadcast receiver is a subclass of the BroadcastReceiver type and it must override the OnReceive method.
Android will execute OnReceive on the main thread, so this method should be designed to execute quickly. Care
should be taken when spawning threads in OnReceive because Android may terminate the process when the
method finishes. If a broadcast receiver must perform long running work then it is recommended to schedule a job
using the JobScheduler or the Firebase Job Dispatcher. Scheduling work with a job will be discussed in a separate
guide.
An intent filter is used to register a broadcast receiver so that Android can properly route messages. The intent
filter can be specified at runtime (this is sometimes referred to as a context-registered receiver or as dynamic
registration) or it can be statically defined in the Android Manifest (a manifest-registered receiver).
Xamarin.Android provides a C# attribute, IntentFilterAttribute , that will statically register the intent filter (this
will be discussed in more detail later in this guide). Starting in Android 8.0, it is not possible for an application to
statically register for an implicit broadcast.
The primary difference between the manifest-registered receiver and the context-registered receiver is that a
context-registered receiver will only respond to broadcasts while an application is running, while a manifest-
registered receiver can respond to broadcasts even though the app may not be running.
There are two sets of APIs for managing a broadcast receiver and sending broadcasts:
1. Context – The Android.Content.Context class can be used to register a broadcast receiver that will respond to
system wide events. The Context is also used to publish system-wide broadcasts.
-
2. LocalBroadcastManager – This is an API that is available through the Xamarin Support Library v4 NuGet
package. This class is used to keep broadcasts and broadcast receivers isolated in the context of the application
that is using them. This class can be useful for preventing other applications from responding to application-
only broadcasts or sending messages to private receivers.
A broadcast receiver may not display dialogs, and it is strongly discouraged to start an activity from within a
broadcast receiver. If a broadcast receiver must notify the user, then it should publish a notification.
It is not possible to bind to or start a service from within a broadcast receiver.
This guide will cover how to create a broadcast receiver and how to register it so that it may receive broadcasts.

Creating a Broadcast Receiver


To create a broadcast receiver in Xamarin.Android, an application should subclass the BroadcastReceiver class,
adorn it with the BroadcastReceiverAttribute , and override the OnReceive method:

[BroadcastReceiver(Enabled = true, Exported = false)]


public class SampleReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here.

String value = intent.GetStringExtra("key");


}
}

When Xamarin.Android compiles the class, it will also update the AndroidManifest with the necessary meta-data
to register the receiver. For a statically-registered broadcast receiver, the Enabled properly must be set to true ,
otherwise Android will not be able to create an instance of the receiver.
The Exported property controls whether the broadcast receiver can receive messages from outside the
application. If the property is not explicitly set, the default value of the property is determined by Android based on
if there are any intent-filters associated with the broadcast receiver. If there is at least one intent-filter for the
broadcast receiver then Android will assume that the Exported property is true . If there are no intent-filters
associated with the broadcast receiver, then Android will assume that the value is false .
The OnReceive method receives a reference to the Intent that was dispatched to the broadcast receiver. This
makes is possible for the sender of the intent to pass values to the broadcast receiver.
Statically registering a Broadcast Receiver with an Intent Filter
When a BroadcastReceiver is decorated with the IntentFilterAttribute , Xamarin.Android will add the necessary
<intent-filter> element to the Android manifest at compile time. The following snippet is an example of a
broadcast receiver that will run when a device has finished booting (if the appropriate Android permissions were
granted by the user):

[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class MyBootReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Work that should be done when the device boots.
}
}

It is also possible to create an intent filter that will respond to custom intents. Consider the following example:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "com.xamarin.example.TEST" })]
public class MySampleBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// Do stuff here
}
}

Apps that target Android 8.0 (API level 26) or higher may not statically register for an implicit broadcast. Apps
may still statically register for an explicit broadcast. There is a small list of of implicit broadcasts that are exempt
from this restriction. These exceptions are described in the Implicit Broadcast Exceptions guide in the Android
documentation. Apps that are interested in implicit broadcasts must do so dynamically using the RegisterReceiver
method. This is described next.
Context-Registering a Broadcast Receiver
Context-registration (also referred to as dynamic registration) of a receiver is performed by invoking the
RegisterReceiver method, and the broadcast receiver must be unregistered with a call to the UnregisterReceiver
method. To prevent leaking resources, it is important to unregister the receiver when it is no longer relevant for the
context (the Activity or service). For example, a service may broadcast an intent to inform an Activity that updates
are available to be displayed to the user. When the Activity starts, it would register for those Intents. When the
Activity is moved into the background and no longer visible to the user, it should unregister the receiver because
the UI for displaying the updates is no longer visible. The following code snippet is an example of how to register
and unregister a broadcast receiver in the context of an Activity:

[Activity(Label = "MainActivity", MainLauncher = true, Icon = "@mipmap/icon")]


public class MainActivity: Activity
{
MySampleBroadcastReceiver receiver;

protected override void OnCreate(Bundle savedInstanceState)


{
base.OnCreate(savedInstanceState);
receiver = new MySampleBroadcastReceiver()

// Code omitted for clarity


}

protected override OnResume()


{
base.OnResume();
RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
// Code omitted for clarity
}

protected override OnPause()


{
UnregisterReceiver(receiver);
// Code omitted for clarity
base.OnPause();
}
}

In the previous example, when the Activity comes into the foreground, it will register a broadcast receiver that will
listen for a custom intent by using the OnResume lifecycle method. As the Activity moves into the background, the
OnPause() method will unregister the receiver.
Publishing a Broadcast
A broadcast may be published to all apps installed on the device creating an Intent object and dispatching it with
the SendBroadcast or the SendOrderedBroadcast method.
1. Context.SendBroadcast methods – There are several implementations of this method. These methods
will broadcast the intent to the entire system. Broadcast receivers thatwill receive the intent in an
indeterminate order. This provides a great deal of flexibility but means that it is possible for other
applications to register and receive the intent. This can pose a potential security risk. Applications may need
to implement addition security to prevent unauthorized access. One possible solution is to use the
LocalBroadcastManager which will only dispatch messages within the private space of the app. This code
snippet is one example of how to dispatch an intent using one of the SendBroadcast methods:

Intent message = new Intent("com.xamarin.example.TEST");


// If desired, pass some values to the broadcast receiver.
intent.PutExtra("key", "value");
SendBroadcast(intent);

This snippet is another example of sending a broadcast by using the Intent.SetAction method to identify
the action:

Intent intent = new Intent();


intent.SetAction("com.xamarin.example.TEST");
intent.PutExtra("key", "value");
SendBroadcast(intent);

2. Context.SendOrderedBroadcast – This is method is very similar to Context.SendBroadcast , with the


difference being that the intent will be published one at time to receivers, in the order that the recievers
were registered.
LocalBroadcastManager
The Xamarin Support Library v4 provides a helper class called LocalBroadcastManager . The LocalBroadcastManager
is intended for apps that do not want to send or receive broadcasts from other apps on the device. The
LocalBroadcastManager will only publish messages within the context of the application, and only to those
broadcast receivers that are registered with the LocalBroadcastManager . This code snippet is an example of
registering a broadcast receiver with LocalBroadcastManager :

Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this). RegisterReceiver(receiver, new


IntentFilter("com.xamarin.example.TEST"));

Other apps on the device cannot receive the messages that are published with the LocalBroadcastManager . This
code snippet shows how to dispatch an Intent using the LocalBroadcastManager :

Intent message = new Intent("com.xamarin.example.TEST");


// If desired, pass some values to the broadcast receiver.
intent.PutExtra("key", "value");
Android.Support.V4.Content.LocalBroadcastManager.GetInstance(this).SendBroadcast(message);

Related Links
BroadcastReceiver
Context.RegisterReceiver
Context.SendBroadcast
Context.UnregisterReceiver
Intent
IntentFilter
LocalBroadcastManager
Local Notifications in Android
Android Support Library v4
Android Localization
5/7/2018 • 6 minutes to read • Edit Online

This document introduces the localization features of the Android SDK and how to access them with Xamarin.

Android Platform Features


This section describes the main localization features of Android. Skip to the next section to see specific code and
examples.
Locale
Users choose their language in Settings > Langauge & input. This selection controls both the language
displayed and regional settings used (eg. for date and number formatting).
The current locale can be queried via the current context's Resources :

var lang = Resources.Configuration.Locale; // eg. "es_ES"

This value will be a locale identifier that contains both a language code and a locale code, separated by an
underscore. For reference, here is a list of Java locales and Android-supported locales via StackOverflow.
Common examples include:
en_US for English (United Statees)
es_ES for Spanish (Spain)
ja_JP for Japanese (Japan)
zh_CN for Chinese (China)
zh_TW for Chinese (Taiwan)
pt_PT for Portuguese (Portugal)
pt_BR for Portuguese (Brazil)
LOCALE_CHANGED
Android generates android.intent.action.LOCALE_CHANGED when the user changes their language selection.
Activities can opt to handle this by setting the android:configChanges attribute on the activity, like this:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",


ConfigurationChanges = ConfigChanges.Locale | ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

Internationalization Basics in Android


Android's localization strategy has the following key parts:
Resource folders to contain localized strings, images, and other resources.
GetText method, which is used to retrieve localized strings in code
@string/id in AXML files, to automatically place localized strings in layouts.
Resource Folders
Android applications manage most content in resource folders, such as:
layout - contains AXML layout files.
drawable - contains images and other drawable resources.
values - contains strings.
raw - contains data files.
Most developers are already familiar with the use of dpi suffixes on the drawable directory to provide multiple
versions of an image, letting Android choose the correct version for each device. The same mechanism is used to
provide multiple language translations by suffixing resource directories with language and culture identifiers.

NOTE
When specifying a top-level language like es only two characters are required; however when specifying a full locale, the
directory name format requires a dash and lowercase r to separate the two parts, for example pt-rBR or zh-rCN. Compare
this to the value returned in code, which has an underscore (eg. pt_BR ). Both of these are different to the value .NET
CultureInfo class uses, which has a dash only (eg. pt-BR ). Keep these differences in mind when working across Xamarin
platforms.

Strings.xml file format


A localized values directory (eg. values-es or values-pt-rBR) should contain a file called Strings.xml that will
contain the translated text for that locale.
Each translatable string is an XML element with the resource ID specified as the name attribute and the translated
string as the value:

<string name="app_name">TaskyL10n</string>

You need to escape according to normal XML rules, and the name must be a valid Android resource ID (no spaces
or dashes). Here is an example of the default (English) strings file for the example:
values/Strings.xml
<resources>
<string name="app_name">TaskyL10n</string>
<string name="taskadd">Add Task</string>
<string name="taskname">Name</string>
<string name="tasknotes">Notes</string>
<string name="taskdone">Done</string>
<string name="taskcancel">Cancel</string>
</resources>

The Spanish directory values-es contains a file with the same name (Strings.xml) that contains the translations:
values-es/Strings.xml

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="app_name">TaskyLeon</string>
<string name="taskadd">agregar tarea</string>
<string name="taskname">Nombre</string>
<string name="tasknotes">Notas</string>
<string name="taskdone">Completo</string>
<string name="taskcancel">Cancelar</string>
</resources>

With the strings files set-up, the translated values can be referenced in both layouts and code.
AXML Layout Files
To reference localized strings in layout files, use the @string/id syntax. This XML snippet from the sample shows
text properties being set with localized resource IDs (some other attributes have been omitted):

<TextView
android:id="@+id/NameLabel"
android:text="@string/taskname"
... />
<CheckBox
android:id="@+id/chkDone"
android:text="@string/taskdone"
... />

GetText Method
To retrieve translated strings in code, use the GetText method and pass the resource ID:

var cancelText = Resources.GetText (Resource.String.taskcancel);

Quantity Strings
Android string resources also let you create quantity strings which allow translators to provide different
translations for different quantities, such as:
"There is 1 task left."
"There are 2 tasks still to do."
(rather than a generic "There are n task(s) left").
In the Strings.xml

<plurals name="numberOfTasks">
<!--
As a developer, you should always supply "one" and "other"
strings. Your translators will know which strings are actually
needed for their language.
-->
<item quantity="one">There is %d task left.</item>
<item quantity="other">There are %d tasks still to do.</item>
</plurals>

To render the complete string use the GetQuantityString method, passing the resource ID and the value to be
displayed (which is passed twice). The second parameter is used by Android to determine which quantity string
to use, the third parameter is the value actually substituted into the string (both are required).

var translated = Resources.GetQuantityString (


Resource.Plurals.numberOfTasks, taskcount, taskcount);`

Valid quantity switches are:


zero
one
two
few
many
other
They're described in more detail in the Android docs. If a given language does not require 'special' handling, those
quantity strings will be ignored (for example, English only uses one and other ; specifying a zero string will
have no effect, it will not be used).
Images
Localized images follow the same rules as strings files: all images referenced in the application should be placed in
drawable directories so there is a fallback.
Locale-specific images should then be placed in qualified drawable folders such as drawable-es or drawable-ja
(dpi specifiers can also be added).
In this screenshot, four images are saved in the drawable directory, but only one, flag.png, has localized copies
in other directories.
Other Resource Types
You can also provide other types of alternative, language-specific resources including layouts, animations, and raw
files. This means you could provide a specific screen layout for one or more of your target languages, for example
you could create a layout specifically for German that allows for very long text labels.
Android 4.2 introduced support for right to left (RTL ) languages if you set the application setting
android:supportsRtl="true" . The resource qualifier "ldrtl" can be included in a direcory name to contain
custom layouts that are designed for RTL display.
For more information on resource directory naming and fallback, refer to the Android docs for providing
alternative resources.
App name
The application name is easy to localize by using a @string/id in for the MainLauncher activity:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",


ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Locale)]

Right-to -Left (RTL ) Languages


Android 4.2 and newer provides full support for RTL layouts, described in detail in the Native RTL Support blog.
When using Android 4.2 (API level 17) and newer, aligment values can be specified with start and end instead
of left and right (for example android:paddingStart ). There are also new APIs like LayoutDirection ,
TextDirection , and TextAlignment to help build screens that adapt for RTL readers.

The following screenshot shows the localized Tasky sample in Arabic:

The next screenshot shows the localized Tasky sample in Hebrew:


RTL text is localized using Strings.xml files in the same way as LTR text.

Testing
Make sure to thoroughly test the default locale. Your application will crash if the default resources cannot be
loaded for some reason (i.e. they are missing).
Emulator Testing
Refer to Google's Testing on an Android Emulator section for instructions on how to set an emulator to a specific
locale using the ADB shell.

adb shell setprop persist.sys.locale fr-CA;stop;sleep 5;start

Device Testing
To test on a device, change the language in the Settings app. Tip: Make a note of the icons and location of the
menu items so that you can revert the language to the original setting.

Summary
This article covers the basics of localizing Android applications using the built-in resource handling. You can learn
more about i18n and L10n for iOS, Android and cross-platform (including Xamarin.Forms) apps in this cross-
platform guide.

Related Links
Tasky (localized in code) (sample)
Android Localizing with Resources
Cross-Platform Localization Overview
Xamarin.Forms Localization
iOS Localization
Permissions In Xamarin.Android
7/25/2018 • 9 minutes to read • Edit Online

Overview
Android applications run in their own sandbox and for security reasons do not have access to certain system
resources or hardware on the device. The user must explicitly grant permission to the app before it may use these
resources. For example, an application cannot access the GPS on a device without explicit permission from the
user. Android will throw a Java.Lang.SecurityException if an app tries to access a protected resource without
permission.
Permissions are declared in the AndroidManifest.xml by the application developer when the app is developed.
Android has two different workflows for obtaining the user's consent for those permissions:
For apps that targeted Android 5.1 (API level 22) or lower, the permission request occurred when the app was
installed. If the user did not grant the permissions, then the app would not be installed. Once the app is
installed, there is no way to revoke the permissions except by uninstalling the app.
Starting in Android 6.0 (API level 23), users were given more control over permissions; they can grant or
revoke permissions as long as the app is installed on the device. This screenshot shows the permission settings
for the Google Contacts app. It lists the various permissions and allows the user to enable or disable
permissions:

Android apps must check at run-time to see if they have permission to access a protected resource. If the app does
not have permission, then it must make requests using the new APIs provided by the Android SDK for the user to
grant the permissions. Permissions are divided into two categories:
Normal Permissions – These are permissions which pose little security risk to the user's security or privacy.
Android 6.0 will automatically grant normal permissions at the time of installation. Please consult the Android
documentation for a complete list of normal permissions.
Dangerous Permissions – In contrast to normal permissions, dangerous permissions are those that protect
the user's security or privacy. These must be explictly granted by the user. Sending or receiving an SMS
message is an example of an action requiring a dangerous permission.

IMPORTANT
The category that a permission belongs to may change over time. It is possible that a permission which was categorized as a
"normal" permission may be elevated in future API levels to a dangerous permission.
Dangerous permissions are further sub-divided into permission groups. A permission group will hold permissions
that are logically related. When the user grants permission to one member of a permission group, Android
automatically grants permission to all members of that group. For example, the STORAGE permission group holds
both the WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions. If the user grants permission to
READ_EXTERNAL_STORAGE , then the WRITE_EXTERNAL_STORAGE permission is automatically granted at the same time.

Before requesting one or more permissions, it is a best practice to provide a rationale as to why the app requires
the permission before requesting the permission. Once the user understands the rationale, the app can request
permission from the user. By understanding the rationale, the user can make an informed decision if they wish to
grant the permission and understand the repercussions if they do not.
The whole workflow of checking and requesting permissions is known as a run-time permissions check, and can
be summarized in the following diagram:

The Android Support Library backports some of the new APIs for permissions to older versions of Android.
These backported APIs will automatically check the version of Android on the device so it is not necessary to
perform an API level check each time.
This document will discuss how to add permissions to a Xamarin.Android application and how apps that target
Android 6.0 (API level 23) or higher should perform a run-time permission check.

NOTE
It is possible that permissions for hardware may affect how the app is filtered by Google Play. For example, if the app
requires permission for the camera, then Google Play will not show the app in the Google Play Store on a device that does
not have a camera installed.

Requirements
It is strongly recommended that Xamarin.Android projects include the Xamarin.Android.Support.Compat NuGet
package. This package will backport permission specific APIs to older versions of Android, providing one common
interface without the need to constantly check the version of Android that the app is running on.

Requesting System Permissions


The first step in working with Android permissions is to declare the permissions in the Android manifest file. This
must be done regardless of the API level that the app is targetting.
Apps that target Android 6.0 or higher cannot assume that because the user granted permission at some point in
the past, that the permission will be valid the next time. An app that targets Android 6.0 must always perform a
runtime permission check. Apps that target Android 5.1 or lower do not need to perform a run-time permission
check.

NOTE
Applications should only request the permissions that they require.

Declaring Permissions in the Manifest


Permissions are added to the AndroidManifest.xml with the uses-permission element. For example, if an
application is to locate the position of the device, it requires fine and course location permissions. The following
two elements are added to the manifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Visual Studio
Visual Studio for Mac
It is possible to declare the permissions using the tool support built into Visual Studio:
1. Double-click Properties in the Solution Explorer and select the Android Manifest tab in the Properties
window:
2. If the application does not already have an AndroidManifest.xml, click No AndroidManifest.xml found.
Click to add one as shown below:

3. Select any permissions your application needs from the Required permissions list and save:
Xamarin.Android will automatically add some permissions at build time to Debug builds. This will make
debugging the application easier. In particular, two notable permissions are INTERNET and READ_EXTERNAL_STORAGE .
These automatically-set permissions will not appear to be enabled in the Required permissions list. Release
builds, however, use only the permissions that are explicitly set in the Required permissions list.
For apps that target Android 5.1(API level 22) or lower, there is nothing more that needs to be done. Apps that will
run on Android 6.0 (API 23 level 23) or higher should proceed on to the next section on how to perform run time
permission checks.
Runtime Permission Checks in Android 6.0
The ContextCompat.CheckSelfPermission method (available with the Android Support Library) is used to check if a
specific permission has been granted. This method will return a Android.Content.PM.Permission enum which has
one of two values:
Permission.Granted – The specified permission has been granted.
Permission.Denied – The specified permission has not been granted.

This code snippet is an example of how to check for the Camera permission in an Activity:

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == (int)Permission.Granted)


{
// We have permission, go ahead and use the camera.
}
else
{
// Camera permission is not granted. If necessary display rationale & request.
}

It is a best practice to inform the user as to why a permission is necessary for an application so that an informed
decision can be made to grant the permission. An example of this would be an app that takes photos and geo-tags
them. It is clear to the user that the camera permission is necessary, but it might not be clear why the app also
needs the location of the device. The rationale should display a message to help the user understand why the
location permission is desirable and that the camera permission is required.
The ActivityCompat.ShouldShowRequestPermissionRational method is used to determine if the rationale should be
shown to the user. This method will return true if the rationale for a given permission should be displayed. This
screenshot shows an example of a Snackbar displayed by an application that explains why the app needs to know
the location of the device:

If the user grants the permission, the


ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int requestCode) method should be
called. This method requires the following parameters:
activity – This is the activity that is requesting the permissions and is to be informed by Android of the results.
permissions – A list of the permissions that are being requested.
requestCode – An integer value that is used to match the results of the permission request to a
RequestPermissions call. This value should be greater than zero.

This code snippet is an example of the two methods that were discussed. First, a check is made to determine if the
permission rationale should be shown. If the rationale is to be shown, then a Snackbar is displayed with the
rationale. If the user clicks OK in the Snackbar, then the app will request the permissions. If the user does not
accept the rationale, then the app should not proceed to request permissions. If the rationale is not shown, then
the Activity will request the permission:

if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation))
{
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");

var requiredPermissions = new String[] { Manifest.Permission.AccessFineLocation };


Snackbar.Make(layout,
Resource.String.permission_location_rationale,
Snackbar.LengthIndefinite)
.SetAction(Resource.String.ok,
new Action<View>(delegate(View obj) {
ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION);
}
)
).Show();
}
else
{
ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.Camera }, REQUEST_LOCATION);
}

RequestPermission can be called even if the user has already granted permission. Subsequent calls are not
necessary, but they provide the user with the opportunity to confirm (or revoke) the permission. When
RequestPermission is called, control is handed off to the operating system, which will display a UI for accepting the
permissions:
After the user is finished, Android will return the results to the Activity via a callback method,
OnRequestPermissionResult . This method is a part of the interface
ActivityCompat.IOnRequestPermissionsResultCallback which must be implemented by the Activity. This interface
has a single method, OnRequestPermissionsResult , which will be invoked by Android to inform the Activity of the
user's choices. If the user has granted the permission, then the app can go ahead and use the protected resource.
An example of how to implement OnRequestPermissionResult is shown below:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[]


grantResults)
{
if (requestCode == REQUEST_LOCATION)
{
// Received permission result for camera permission.
Log.Info(TAG, "Received response for Location permission request.");

// Check if the only required permission has been granted


if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
// Location permission has been granted, okay to retrieve the location of the device.
Log.Info(TAG, "Location permission has now been granted.");
Snackbar.Make(layout, Resource.String.permision_available_camera, Snackbar.LengthShort).Show();
}
else
{
Log.Info(TAG, "Location permission was NOT granted.");
Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
}
}
else
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

Summary
This guide discussed how to add and check for permissions in an Android device. The differences in how
permissions work between old Android apps (API level < 23) and new Android apps (API level > 22). It discussed
how to perform run-time permission checks in Android 6.0.

Related Links
List of Normal Permissions
Runtime Permissions Sample App
Handling Permissions in Xamarin.Android
Graphics and Animation
4/12/2018 • 17 minutes to read • Edit Online

Android provides a very rich and diverse framework for supporting 2D graphics and animations. This topic
introduces these frameworks and discusses how to create custom graphics and animations for use in a
Xamarin.Android application.

Overview
Despite running on devices that are traditionally of limited power, the highest rated mobile applications often have
a sophisticated User Experience (UX), complete with high quality graphics and animations that provide an intuitive,
responsive, dynamic feel. As mobile applications get more and more sophisticated, users have begun to expect
more and more from applications.
Luckily for us, modern mobile platforms have very powerful frameworks for creating sophisticated animations and
custom graphics while retaining ease of use. This enables developers to add rich interactivity with very little effort.
UI API frameworks in Android can roughly be split into two categories: Graphics and Animation.
Graphics are further split into different approaches for doing 2D and 3D graphics. 3D graphics are available via a
number of built in frameworks such as OpenGL ES (a mobile specific version of OpenGL ), and third-party
frameworks such as MonoGame (a cross platform toolkit compatible with the XNA toolkit). Although 3D graphics
are not within the scope of this article, we will examine the built-in 2D drawing techniques.
Android provides two different API's for creating 2D graphics. One is a high level declarative approach and the
other a programmatic low -level API:
Drawable Resources – These are used to create custom graphics either programmatically or (more
typically) by embedding drawing instructions in XML files. Drawable resources are typically defined as XML
files that contain instructions or actions for Android to render a 2D graphic.
Canvas – this is a low level API that involves drawing directly on an underlying bitmap. It provides very
fine-grained control over what is displayed.
In addition to these 2D graphics techniques, Android also provides several different ways to create animations:
Drawable Animations – Android also supports frame-by-frame animations known as Drawable
Animation. This is the simplest animation API. Android sequentially loads and displays Drawable resources
in sequence (much like a cartoon).
View Animations – View Animations are the original animation API's in Android and are available in all
versions of Android. This API is limited in that it will only work with View objects and can only perform
simple transformations on those Views. View animations are typically defined in XML files found in the
/Resources/anim folder.

Property Animations – Android 3.0 introduced a new set of animation API's known as Property
Animations. These new API's introduced an extensible and flexible system that can be used to animate the
properties of any object, not just View objects. This flexibility allows animations to be encapsulated in
distinct classes that will make code sharing easier.
View Animations are more suitable for applications that must support the older pre-Android 3.0 API's (API level
11). Otherwise applications should use the newer Property Animation API's for the reasons that were mentioned
above.
All of these frameworks are viable options, however where possible, preference should be given to Property
Animations, as it is a more flexible API to work with. Property Animations allow for animation logic to be
encapsulated in distinct classes that makes code sharing easier and simplifies code maintenance.

Accessibility
Graphics and animations help to make Android apps attractive and fun to use; however, it is important to
remember that some interactions occur via screenreaders, alternate input devices, or with assisted zoom. Also,
some interactions may occur without audio capabilities.
Apps are more usable in these situations if they have been designed with accessibility in mind: providing hints and
navigation assistance in the user-interface, and ensuring there is text-content or descriptions for pictorial elements
of the UI.
Refer to Google's Accessibility Guide for more information on how to utilize Android's accessibility APIs.

2D Graphics
Drawable Resources are a popular technique in Android applications. As with other resources, Drawable Resources
are declarative – they're defined in XML files. This approach allows for a clean separation of code from resources.
This can simplify development and maintenance because it is not necessary to change code to update or change
the graphics in an Android application. However, while Drawable Resources are useful for many simple and
common graphic requirements, they lack the power and control of the Canvas API.
The other technique, using the Canvas object, is very similar to other traditional API frameworks such as
System.Drawing or iOS's Core Drawing. Using the Canvas object provides the most control of how 2D graphics
are created. It is appropriate for situations where a Drawable Resource will not work or will be difficult to work
with. For example, it may be necessary to draw a custom slider control whose appearance will change based on
calculations related to the value of the slider.
Let's examine Drawable Resources first. They are simpler and cover the most common custom drawing cases.
Drawable Resources
Drawable Resources are defined in an XML file in the directory /Resources/drawable . Unlike embedding PNG or
JPEG's, it is not necessary to provide density-specific versions of Drawable Resources. At runtime, an Android
application will load these resources and use the instructions contained in these XML files to create 2D graphics.
Android defines several different types of Drawable Resources:
ShapeDrawable – This is a Drawable object that draws a primitive geometric shape and applies a limited set
of graphical effects on that shape. They are very useful for things such as customizing Buttons or setting the
background of TextViews. We will see an example of how to use a ShapeDrawable later in this article.
StateListDrawable – This is a Drawable Resource that will change appearance based on the state of a
widget/control. For example, a button may change its appearance depending on whether it is pressed or not.
LayerDrawable – This Drawable Resource that will stack several other drawables one on top of another. An
example of a LayerDrawable is shown in the following screenshot:

TransitionDrawable – This is a LayerDrawable but with one difference. A TransitionDrawable is able to


animate one layer showing up over top another.
LevelListDrawable – This is very similar to a StateListDrawable in that it will display an image based on
certain conditions. However, unlike a StateListDrawable, the LevelListDrawable displays an image based on
an integer value. An example of a LevelListDrawable would be to display the strength of a WiFi signal. As
the strength of the WiFi signal changes, the drawable that is displayed will change accordingly.
ScaleDrawable/ClipDrawable – As their name implies, these Drawables provide both scaling and clipping
functionality. The ScaleDrawable will scale another Drawable, while the ClipDrawable will clip another
Drawable.
InsetDrawable – This Drawable will apply insets on the sides of another Drawable resource. It is used when
a View needs a background that is smaller than the View's actual bounds.
XML BitmapDrawable – This file is a set of instructions, in XML, that are to be performed on an actual
bitmap. Some actions that Android can perform are tiling, dithering, and anti-aliasing. One of the very
common uses of this is to tile a bitmap across the background of a layout.
Drawable Example
Let's look at a quick example of how to create a 2D graphic using a ShapeDrawable . A ShapeDrawable can define
one of the four basic shapes: rectangle, oval, line, and ring. It is also possible to apply basic effects, such as gradient,
colour, and size. The following XML is a ShapeDrawable that may be found in the AnimationsDemo companion
project (in the file Resources/drawable/shape_rounded_blue_rect.xml ). It defines a rectangle with a purple gradient
background and rounded corners:

<?xml version="1.0" encoding="utf-8"?>


<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!-- Specify a gradient for the background -->
<gradient android:angle="45"
android:startColor="#55000066"
android:centerColor="#00000000"
android:endColor="#00000000"
android:centerX="0.75" />

<padding android:left="5dp"
android:right="5dp"
android:top="5dp"
android:bottom="5dp" />

<corners android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
</shape>

We can reference this Drawable Resource declaratively in a Layout or other Drawable as shown in the following
XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/shape_rounded_blue_rect"
android:text="@string/message_shapedrawable" />
</RelativeLayout>

Drawable Resources can also be applied programmatically. The following code snippet shows how to
programmatically set the background of a TextView:
TextView tv = FindViewById<TextView>(Resource.Id.shapeDrawableTextView);
tv.SetBackgroundResource(Resource.Drawable.shape_rounded_blue_rect);

To see what this would look like, run the AnimationsDemo project and select the Shape Drawable item from the
main menu. We should see something similar to the following screenshot:

For more details about the XML elements and syntax of Drawable Resources, consult Google's documentation.
Using the Canvas Drawing API
Drawables are powerful but have their limitations. Certain things are either not possible or very complex (for
example: applying a filter to a picture that was taken by a camera on the device). It would be very difficult to apply
red-eye reduction by using a Drawable Resource. Instead, the Canvas API allows an application to have very fine-
grained control to selectively change colors in a specific part of the picture.
One class that is commonly used with the Canvas is the Paint class. This class holds colour and style information
about how to draw. It is used to provide things such a color and transparency.
The Canvas API uses the painter's model to draw 2D graphics. Operations are applied in successive layers on top
of each other. Each operation will cover some area of the underlying bitmap. When the area overlaps a previously
painted area, the new paint will partially or completely obscure the old. This is the same way that many other
drawing APIs such as System.Drawing and iOS's Core Graphics work.
There are two ways to obtain a Canvas object. The first way involves defining a Bitmap object, and then
instantiating a Canvas object with it. For example, the following code snippet creates a new canvas with an
underlying bitmap:

Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);


Canvas canvas = new Canvas(b);

The other way to obtain a Canvas object is by the OnDraw callback method that is provided the View base class.
Android calls this method when it decides a View needs to draw itself and passes in a Canvas object for the View
to work with.
The Canvas class exposes methods to programmatically provide the draw instructions. For example:
Canvas.DrawPaint – Fills the entire canvas's bitmap with the specified paint.
Canvas.DrawPath – Draws the specified geometric shape using the specified paint.
Canvas.DrawText – Draws the text on the canvas with the specified colour. The text is drawn at location x,y
.
Drawing with the Canvas API
Let's see an example of the Canvas API in action. The following code snippet shows how to draw a view:
public class MyView : View
{
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint green = new Paint {
AntiAlias = true,
Color = Color.Rgb(0x99, 0xcc, 0),
};
green.SetStyle(Paint.Style.FillAndStroke);

Paint red = new Paint {


AntiAlias = true,
Color = Color.Rgb(0xff, 0x44, 0x44)
};
red.SetStyle(Paint.Style.FillAndStroke);

float middle = canvas.Width * 0.25f;


canvas.DrawPaint(red);
canvas.DrawRect(0, 0, middle, canvas.Height, green);
}
}

This code above first creates a red paint and a green paint object. It fills the content of the canvas with red, and
then instructs the canvas to draw a green rectangle that is 25% of the width of the canvas. An example of this can
be seen by in AnimationsDemo project that is included with the source code for this article. By starting up the
application and selecting the Drawing item from the main menu, we should a screen similar to the following:
Animation
Users like things that move in their applications. Animations are a great way to improve the user experience of an
application and help it stand out. The best animations are the ones that users don't notice because they feel natural.
Android provides the following three API's for animations:
View Animation – This is the original API. These animations are tied to a specific View and can perform
simple transformations on the contents of the View. Because of it's simplicity, this API still useful for things
like alpha animations, rotations, and so forth.
Property Animation – Property animations were introduced in Android 3.0. They enable an application to
animate almost anything. Property animations can be used to change any property of any object, even if
that object is not visible on the screen.
Drawable Animation – This a special Drawable resource that is used to apply a very simple animation
effect to layouts.
In general, property animation is the preferred system to use as it is more flexible and offers more features.
View Animations
View animations are limited to Views and can only perform animations on values such as start and end points,
size, rotation, and transparency. These types of animations are typically referred to as tween animations. View
animations can be defined two ways – programmatically in code or by using XML files. XML files are the preferred
way to declare view animations, as they are more readable and easier to maintain.
The animation XML files will be stored in the /Resources/anim directory of a Xamarin.Android project. This file
must have one of the following elements as the root element :
alpha – A fade-in or fade-out animation.
rotate – A rotation animation.
scale – A resizing animation.
translate – A horizontal and/or vertical motion.
set – A container that may hold one or more of the other animation elements.

By default, all animations in an XML file will be applied simultaneously. To make animations occur sequentially, set
the android:startOffset attribute on one of the elements defined above.
It is possible to affect the rate of change in an animation by using an interpolator. An interpolator makes it possible
for animation effects to be accelerated, repeated, or decelerated. The Android framework provides several
interpolators out of the box, such as (but not limited to):
AccelerateInterpolator / DecelerateInterpolator – these interpolators increase or decrease the rate of
change in an animation.
BounceInterpolator – the change bounces at the end.
LinearInterpolator – the rate of changes is constant.

The following XML shows an example of an animation file that combines some of these elements:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android=http://schemas.android.com/apk/res/android
android:shareInterpolator="false">

<scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillAfter="false"
android:duration="700" />

<set android:interpolator="@android:anim/accelerate_interpolator">
<scale android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />

<rotate android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />
</set>
</set>

This animation will perform all of the animations simultaneously. The first scale animation will stretch the image
horizontally and shrink it vertically, and then the image will simultaneously be rotated 45 degrees counter-
clockwise and shrink, disappearing from the screen.
The animation can be programmatically applied to a View by inflating the animation and then applying it to a View.
Android provides the helper class Android.Views.Animations.AnimationUtils that will inflate an animation resource
and return an instance of Android.Views.Animations.Animation . This object is applied to a View by calling
StartAnimation and passing the Animation object. The following code snippet shows an example of this:

Animation myAnimation = AnimationUtils.LoadAnimation(Resource.Animation.MyAnimation);


ImageView myImage = FindViewById<ImageView>(Resource.Id.imageView1);
myImage.StartAnimation(myAnimation);

Now that we have a fundamental understanding of how View Animations work, lets move to Property Animations.
Property Animations
Property animators are a new API that was introduced in Android 3.0. They provide a more extensible API that can
be used to animate any property on any object.
All property animations are created by instances of the Animator subclass. Applications do not directly use this
class, instead they use one of it's subclasses:
ValueAnimator – This class is the most important class in the entire property animation API. It calculates the
values of properties that need to be changed. The ViewAnimator does not directly update those values;
instead, it raises events that can be used to update animated objects.
ObjectAnimator – This class is a subclass of ValueAnimator . It is meant to simplify the process of animating
objects by accepting a target object and property to update.
AnimationSet – This class is responsible for orchestrating how animations run in relation to one another.
Animations may run simultaneously, sequentially, or with a specified delay between them.
Evaluators are special classes that are used by animators to calculate the new values during an animation. Out of
the box, Android provides the following evaluators:
IntEvaluator – Calculates values for integer properties.
FloatEvaluator – Calculates values for float properties.
ArgbEvaluator – Calculates values for colour properties.
If the property that is being animated is not a float , int or colour, applications may create their own evaluator
by implementing the ITypeEvaluator interface. (Implementing custom evaluators is beyond the scope of this
topic.)
Using the ValueAnimator
There are two parts to any animation: calculating animated values and then setting those values on properties on
some object. ValueAnimator will only calculate the values, but it will not operate on objects directly. Instead, objects
will be updated inside event handlers that will be invoked during the animation lifespan. This design allows several
properties to be updated from one animated value.
You obtain an instance of ValueAnimator by calling one of the following factory methods:
ValueAnimator.OfInt
ValueAnimator.OfFloat
ValueAnimator.OfObject

Once that is done, the ValueAnimator instance must have its duration set, and then it can be started. The following
example shows how to animate a value from 0 to 1 over the span of 1000 milliseconds:

ValueAnimator animator = ValueAnimator.OfInt(0, 100);


animator.SetDuration(1000);
animator.Start();

But itself, the code snippet above is not very useful – the animator will run but there is no target for the updated
value. The Animator class will raise the Update event when it decides that it is necessary to inform listeners of a
new value. Applications may provide an event handler to respond to this event as shown in the following code
snippet:

MyCustomObject myObj = new MyCustomObject();


myObj.SomeIntegerValue = -1;

animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) =>


{
int newValue = (int) e.Animation.AnimatedValue;
// Apply this new value to the object being animated.
myObj.SomeIntegerValue = newValue;
};
Now that we have an understanding of ValueAnimator , lets learn more about the ObjectAnimator .
Using the ObjectAnimator
ObjectAnimator is a subclass of ViewAnimator that combines the timing engine and value computation of the
ValueAnimator with the logic required to wire up event handlers. The ValueAnimator requires applications to
explicitly wire up an event handler – ObjectAnimator will take care of this step for us.
The API for ObjectAnimator is very similar to the API for ViewAnimator , but requires that you provide the object
and the name of the property to update. The following example shows an example of using ObjectAnimator :

MyCustomObject myObj = new MyCustomObject();


myObj.SomeIntegerValue = -1;

ObjectAnimator animator = ObjectAnimator.OfFloat(myObj, "SomeIntegerValue", 0, 100);


animator.SetDuration(1000);
animator.Start();

As you can see from the previous code snippet, ObjectAnimator can reduce and simplify the code that is necessary
to animate an object.
Drawable Animations
The final animation API is the Drawable Animation API. Drawable animations load a series of Drawable resources
one after the other and display them sequentially, similar to a flip-it cartoon.
Drawable resources are defined in an XML file that has an <animation-list> element as the root element and a
series of <item> elements that define each frame in the animation. This XML file is stored in the
/Resource/drawable folder of the application. The following XML is an example of a drawable animation:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/asteroid01" android:duration="100" />
<item android:drawable="@drawable/asteroid02" android:duration="100" />
<item android:drawable="@drawable/asteroid03" android:duration="100" />
<item android:drawable="@drawable/asteroid04" android:duration="100" />
<item android:drawable="@drawable/asteroid05" android:duration="100" />
<item android:drawable="@drawable/asteroid06" android:duration="100" />
</animation-list>

This animation will run through six frames. The android:duration attribute declares how long each frame will be
displayed. The next code snippet shows an example of creating a Drawable animation and starting it when the user
clicks a button on the screen:
AnimationDrawable _asteroidDrawable;

protected override void OnCreate(Bundle bundle)


{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

_asteroidDrawable = (Android.Graphics.Drawables.AnimationDrawable)
Resources.GetDrawable(Resource.Drawable.spinning_asteroid);

ImageView asteroidImage = FindViewById<ImageView>(Resource.Id.imageView2);


asteroidImage.SetImageDrawable((Android.Graphics.Drawables.Drawable) _asteroidDrawable);

Button asteroidButton = FindViewById<Button>(Resource.Id.spinAsteroid);


asteroidButton.Click += (sender, e) =>
{
_asteroidDrawable.Start();
};
}

At this point we have covered the foundations of the animation APIs available in an Android application.

Summary
This article introduced a lot of new concepts and API's to help add some graphics to an Android application. First it
discussed the various 2D graphics API's and demonstrated how Android allows applications to draw directly to the
screen using a Canvas object. We also saw some alternate techniques that allow graphics to be declaratively
created using XML files. Then we went on to discuss the old and new API's for creating animations in Android.

Related Links
Animation Demo (sample)
Animation and Graphics
Using Animations to Bring your Mobile Apps to Life
AnimationDrawable
Canvas
Object Animator
Value Animator
CPU Architectures
5/18/2018 • 3 minutes to read • Edit Online

Xamarin.Android supports several CPU architectures, including 32 -bit and 64 -bit devices. This article explains how
to target an app to one or more Android -supported CPU architectures.

CPU Architectures Overview


When you prepare your app for release, you must specify which platform CPU architectures your app supports. A
single APK can contain machine code to support multiple, different architectures. Each collection of architecture-
specific code is associated with an Application Binary Interface (ABI). Each ABI defines how this machine code is
expected to interact with Android at run time. For more information about how this works, see Multi-Core Devices
& Xamarin.Android.

How to Specify Supported Architectures


Visual Studio
Visual Studio for Mac
Typically, you explicitly select an architecture (or architectures) when your app is configured for Release. When
your app is configured for Debug, the Use Shared Runtime and Use Fast Deployment options are enabled,
which disable explicit architecture selection.
In Visual Studio, right-click on your project under the Solution Explorer and select Properties. Under the
Android Options page check the Packaging properties section and verify that Use Shared Runtime is
disabled (turning this off allows you to explicitly select which ABIs to support). Click the Advanced button and,
under Supported architectures, check the architectures that you want to support:

Xamarin.Android supports the following architectures:


armeabi – ARM -based CPUs that support at least the ARMv5TE instruction set. Note that armeabi is not
thread-safe and should not be used on multi-CPU devices.
armeabi-v7a – ARM -based CPUs with hardware floating-point operations and multiple CPU (SMP )
devices. Note that armeabi-v7a machine code will not run on ARMv5 devices.
arm64-v8a – CPUs based on the 64-bit ARMv8 architecture.
x86 – CPUs that support the x86 (or IA-32) instruction set. This instruction set is equivalent to that of the
Pentium Pro, including MMX, SSE, SSE2, and SSE3 instructions.
x86_64 CPUs that support the 64-bit x86 (also referred as x64 and AMD64) instruction set.
Xamarin.Android defaults to armeabi-v7a for Release builds. This setting provides significantly better
performance than armeabi . If you are targeting a 64-bit ARM platform (such as the Nexus 9), select arm64-v8a . If
you are deploying your app to an x86 device, select x86 . If the target x86 device uses a 64-bit CPU architecture,
select x86_64 .

Targeting Multiple Platforms


To target multiple CPU architectures, you can select more than one ABI (at the expense of larger APK file size).
You can use the Generate one package (.apk) per selected ABI option (described in Set Packaging Properties)
to create a separate APK for each supported architecture.
You do not have to select arm64-v8a or x86_64 to target 64-bit devices; 64-bit support is not required to run
your app on 64-bit hardware. For example, 64-bit ARM devices (such as the Nexus 9) can run apps configured for
armeabi-v7a . The primary advantage of enabling 64 -bit support is to make it possible for your app to address
more memory.

NOTE
64-bit runtime support is currently an experimental feature. Remember that 64-bit runtimes are not required to run your
app on 64-bit devices.

Additional Information
In some situations, you may need to create a separate APK for each architecture (to reduce the size of your APK,
or because your app has shared libraries that are specific to a particular CPU architecture). For more information
about this approach, see Build ABI-Specific APKs.
Handling Rotation
4/12/2018 • 8 minutes to read • Edit Online

This topic describes how to handle device orientation changes in Xamarin.Android. It covers how to work with the
Android resource system to automatically load resources for a particular device orientation as well as how to
programmatically handle orientation changes.

Overview
Because mobile devices are easily rotated, built-in rotation is a standard feature in mobile OSes. Android provides
a sophisticated framework for dealing with rotation within applications, whether the user interface is created
declaratively in XML or programmatically in code. When automatically handling declarative layout changes on a
rotated device, an application can benefit from the tight integration with the Android resource system. For
programmatic layout, changes must be handled manually. This allows finer control at runtime, but at the expense
of more work for the developer. An application can also choose to opt out of the Activity restart and take manual
control of orientation changes.
This guide examines the following orientation topics:
Declarative Layout Rotation – How to use the Android resource system to build orientation-aware
applications, including how to load both layouts and drawables for particular orientations.
Programmatic Layout Rotation – How to add controls programmatically as well as how to handle
orientation changes manually.

Handling Rotation Declaratively with Layouts


By including files in folders that follow naming conventions, Android automatically loads the appropriate files
when the orientation changes. This includes support for:
Layout Resources – Specifying which layout files are inflated for each orientation.
Drawable Resources – Specifying which drawables are loaded for each orientation.
Layout Resources
By default, Android XML (AXML ) files included in the Resources/layout folder are used for rendering views for
an Activity. This folder's resources are used for both portrait and landscape orientation if no additional layout
resources are provided specifically for landscape. Consider the project structure created by the default project
template:
This project creates a single Main.axml file in the Resources/layout folder. When the Activity's OnCreate
method is called, it inflates the view defined in Main.axml, which declares a button as shown in the XML below:

<?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">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>

If the device is rotated to landscape orientation, the Activity's OnCreate method is called again and the same
Main.axml file is inflated, as shown in the screenshot below:
Orientation-Specific Layouts
In addition to the layout folder (which defaults to portrait and can also be explicitly named layout-port by
including a folder named layout-land ), an application can define the views it needs when in landscape without
any code changes.
Suppose the Main.axml file contained the following XML:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is portrait"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>

If a folder named layout-land that contains an additional Main.axml file is added to the project, inflating the
layout when in landscape will now result in Android loading the newly added Main.axml. Consider the landscape
version of the Main.axml file that contains the following code (for simplicity, this XML is similar to the default
portrait version of the code, but uses a different string in the TextView ):

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is landscape"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>

Running this code and rotating the device from portrait to landscape demonstrates the new XML loading, as
shown below:
Drawable Resources
During rotation, Android treats drawable resources similarly to layout resources. In this case, the system gets the
drawables from the Resources/drawable and Resources/drawable-land folders, respectively.
For example, say the project includes an image named Monkey.png in the Resources/drawable folder, where the
drawable is referenced from an ImageView in XML like this:

<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/monkey"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />

Let's further assume that a different version of Monkey.png is included under Resources/drawable-land. Just
like with the layout files, when the device is rotated, the drawable changes for the given orientation, as shown
below:
Handling Rotation Programmatically
Sometimes we define layouts in code. This can happen for a variety of reasons, including technical limitations,
developer preference, etc. When we add controls programmatically, an application must manually account for
device orientation, which is handled automatically when we use XML resources.
Adding Controls in Code
To add controls programmatically, an application needs to perform the following steps:
Create a layout.
Set layout parameters.
Create controls.
Set control layout parameters.
Add controls to the layout.
Set the layout as the content view.
For example, consider a user interface consisting of a single TextView control added to a RelativeLayout , as
shown in the following code.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// create a layout
var rl = new RelativeLayout (this);

// set layout parameters


var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;

// create TextView control


var tv = new TextView (this);

// set TextView's LayoutParameters


tv.LayoutParameters = layoutParams;
tv.Text = "Programmatic layout";

// add TextView to the layout


rl.AddView (tv);

// set the layout as the content view


SetContentView (rl);
}

This code creates an instance of a RelativeLayout class and sets its LayoutParameters property. The LayoutParams
class is Android's way of encapsulating how controls are positioned in a reusable way. Once an instance of a
layout is created, controls can be created and added to it. Controls also have LayoutParameters , such as the
TextView in this example. After the TextView is created, adding it to the RelativeLayout and setting the
RelativeLayout as the content view results in the application displaying the TextView as shown:

Detecting Orientation in Code


If an application tries to load a different user interface for each orientation when OnCreate is called (this will
happen each time a device is rotated), it must detect the orientation, and then load the desired user interface code.
Android has a class called the WindowManager , which can be used to determine the current device rotation via the
WindowManager.DefaultDisplay.Rotation property, as shown below:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);

// create a layout
var rl = new RelativeLayout (this);

// set layout parameters


var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;

// get the initial orientation


var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
// create layout based upon orientation
RelativeLayout.LayoutParams tvLayoutParams;

if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation ==


SurfaceOrientation.Rotation180) {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);
} else {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);
tvLayoutParams.LeftMargin = 100;
tvLayoutParams.TopMargin = 100;
}

// create TextView control


var tv = new TextView (this);
tv.LayoutParameters = tvLayoutParams;
tv.Text = "Programmatic layout";

// add TextView to the layout


rl.AddView (tv);

// set the layout as the content view


SetContentView (rl);
}

This code sets the TextView to be positioned 100 pixels from the top left of the screen, automatically animating to
the new layout, when rotated to landscape, as shown here:
Preventing Activity Restart
In addition to handling everything in OnCreate , an application can also prevent an Activity from being restarted
when the orientation changes by setting ConfigurationChanges in the ActivityAttribute as follows:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation |


Android.Content.PM.ConfigChanges.ScreenSize)]

Now when the device is rotated, the Activity is not restarted. In order to manually handle the orientation change in
this case, an Activity can override the OnConfigurationChanged method and determine the orientation from the
Configuration object that is passed in, as in the new implementation of the Activity below:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation |


Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
TextView _tv;
RelativeLayout.LayoutParams _layoutParamsPortrait;
RelativeLayout.LayoutParams _layoutParamsLandscape;

protected override void OnCreate (Bundle bundle)


{
// create a layout
// set layout parameters
// get the initial orientation

// create portrait and landscape layout for the TextView


_layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,
ViewGroup.LayoutParams.WrapContent);

_layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent,


ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape.LeftMargin = 100;
_layoutParamsLandscape.TopMargin = 100;

_tv = new TextView (this);

if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation ==


SurfaceOrientation.Rotation180) {
_tv.LayoutParameters = _layoutParamsPortrait;
} else {
_tv.LayoutParameters = _layoutParamsLandscape;
}

_tv.Text = "Programmatic layout";


rl.AddView (_tv);
SetContentView (rl);
}

public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)


{
base.OnConfigurationChanged (newConfig);

if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
_tv.LayoutParameters = _layoutParamsPortrait;
_tv.Text = "Changed to portrait";
} else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
_tv.LayoutParameters = _layoutParamsLandscape;
_tv.Text = "Changed to landscape";
}
}
}

Here the TextView's layout parameters are initialized for both landscape and portrait. Class variables hold the
parameters, along with the TextView itself, since the Activity will not be re-created when orientation changes. The
code still uses the surfaceOrientartion in OnCreate to set the initial layout for the TextView . After that,
OnConfigurationChanged handles all subsequent layout changes.

When we run the application, Android loads the user interface changes as device rotation occurs, and does not
restart the Activity.

Preventing Activity Restart for Declarative Layouts


Activity restarts caused by device rotation can also be prevented if we define the layout in XML. For example, we
can use this approach if we want to prevent an Activity restart (for performance reasons, perhaps) and we don't
need to load new resources for different orientations.
To do this, we follow the same procedure that we use with a programmatic layout. Simply set
ConfigurationChanges in the ActivityAttribute , as we did in the CodeLayoutActivity earlier. Any code that does
need to run for the orientation change can again be implemented in the OnConfigurationChanged method.

Maintaining State During Orientation Changes


Whether handling rotation declaratively or programmatically, all Android applications should implement the same
techniques for managing state when device orientation changes. Managing state is important because the system
restarts a running Activity when an Android device is rotated. Android does this to make it easy to load alternate
resources, such as layouts and drawables that are designed specifically for a particular orientation. When it
restarts, the Activity loses any transient state it may have stored in local class variables. Therefore, if an Activity is
state reliant, it must persist its state at the application level. An application needs to handle saving and restoring
any application state that it wants to preserve across orientation changes.
For more information on persisting state in Android, refer to the Activity Lifecycle guide.

Summary
This article covered how to use Android's built-in capabilities to work with rotation. First, it explained how to use
the Android resource system to create orientation aware applications. Then it presented how to add controls in
code as well as how to handle orientation changes manually.

Related Links
Rotation Demo (sample)
Activity Lifecycle
Handling Runtime Changes
Fast Screen Orientation Change
Android Audio
4/12/2018 • 10 minutes to read • Edit Online

The Android OS provides extensive support for multimedia, encompassing both audio and video. This guide
focuses on audio in Android and covers playing and recording audio using the built-in audio player and recorder
classes, as well as the low -level audio API. It also covers working with Audio events broadcast by other
applications, so that developers can build well-behaved applications.

Overview
Modern mobile devices have adopted functionality that formerly would have required dedicated pieces of
equipment – cameras, music players and video recorders. Because of this, multimedia frameworks have become a
first-class feature in mobile APIs.
Android provides extensive support for multimedia. This article examines working with audio in Android, and
covers the following topics
1. Playing Audio with MediaPlayer – Using the built-in MediaPlayer class to play audio, including local
audio files and streamed audio files with the AudioTrack class.
2. Recording Audio – Using the built-in MediaRecorder class to record audio.
3. Working with Audio Notifications – Using audio notifications to create well-behaved applications that
respond correctly to events (such as incoming phone calls) by suspending or canceling their audio outputs.
4. Working with Low-Level Audio – Playing audio using the AudioTrack class by writing directly to
memory buffers. Recording audio using the AudioRecord class and reading directly from memory buffers.

Requirements
This guide requires Android 2.0 (API level 5) or higher. Please note that debugging audio on Android must be
done on a device.
It is necessary to request the RECORD_AUDIO permissions in AndroidManifest.XML:
Playing Audio with the MediaPlayer Class
The simplest way to play audio in Android is with the built-in MediaPlayer class. MediaPlayer can play either local
or remote files by passing in the file path. However, MediaPlayer is very state-sensitive and calling one of its
methods in the wrong state will cause an exception to be thrown. It's important to interact with MediaPlayer in the
order described below to avoid errors.
Initializing and Playing
Playing audio with MediaPlayer requires the following sequence:
1. Instantiate a new MediaPlayer object.
2. Configure the file to play via the SetDataSource method.
3. Call the Prepare method to initialize the player.
4. Call the Start method to start the audio playing.
The code sample below illustrates this usage:
protected MediaPlayer player;
public void StartPlayer(String filePath)
{
if (player == null) {
player = new MediaPlayer();
} else {
player.Reset();
player.SetDataSource(filePath);
player.Prepare();
player.Start();
}
}

Suspending and Resuming Playback


The playback can be suspended by calling the Pause method:

player.Pause();

To resume paused playback, call the Start method. This will resume from the paused location in the playback:

player.Start();

Calling the Stop method on the player ends an ongoing playback:

player.Stop();

When the player is no longer needed, the resources must be released by calling the Release method:

player.Release();

Using the MediaRecorder Class to Record Audio


The corollary to MediaPlayer for recording audio in Android is the MediaRecorder class. Like the MediaPlayer , it is
state-sensitive and transitions through several states to get to the point where it can start recording. In order to
record audio, the RECORD_AUDIO permission must be set. For instructions on how to set application permissions see
Working with AndroidManifest.xml.
Initializing and Recording
Recording audio with the MediaRecorder requires the following steps:
1. Instantiate a new MediaRecorder object.
2. Specify which hardware device to use to capture the audio input via the SetAudioSource method.
3. Set the output file audio format using the SetOutputFormat method. For a list of supported audio types see
Android Supported Media Formats.
4. Call the SetAudioEncoder method to set the audio encoding type.
5. Call the SetOutputFile method to specify the name of the output file that the audio data is written to.
6. Call the Prepare method to initialize the recorder.
7. Call the Start method to start recording.
The following code sample illustrates this sequence:

protected MediaRecorder recorder;


void RecordAudio (String filePath)
{
try {
if (File.Exists (filePath)) {
File.Delete (filePath);
}
if (recorder == null) {
recorder = new MediaRecorder (); // Initial state.
} else {
recorder.Reset ();
recorder.SetAudioSource (AudioSource.Mic);
recorder.SetOutputFormat (OutputFormat.ThreeGpp);
recorder.SetAudioEncoder (AudioEncoder.AmrNb);
// Initialized state.
recorder.SetOutputFile (filePath);
// DataSourceConfigured state.
recorder.Prepare (); // Prepared state
recorder.Start (); // Recording state.
}
} catch (Exception ex) {
Console.Out.WriteLine( ex.StackTrace);
}
}

Stopping recording
To stop the recording, call the Stop method on the MediaRecorder :

recorder.Stop();

Cleaning up
Once the MediaRecorder has been stopped, call the Reset method to put it back into its idle state:

recorder.Reset();

When the MediaRecorder is no longer needed, its resources must be released by calling the Release method:

recorder.Release();

Managing Audio Notifications


The AudioManager Class
The AudioManager class provides access to audio notifications that let applications know when audio events occur.
This service also provides access to other audio features, such as volume and ringer mode control. The
AudioManager allows an application to handle audio notifications to control audio playback.

Managing Audio Focus


The audio resources of the device (the built-in player and recorder) are shared by all running applications.
Conceptually, this is similar to applications on a desktop computer where only one application has the keyboard
focus: after selecting one of the running applications by mouse-clicking it, the keyboard input goes only to that
application.
Audio focus is a similar idea and prevents more than one application from playing or recording audio at the same
time. It is more complicated than keyboard focus because it is voluntary – the application can ignore that fact that it
does not currently have audio focus and play regardless – and because there are different types of audio focus that
can be requested. For example, if the requestor is only expected to play audio for a very short time, it may request
transient focus.
Audio focus may be granted immediately, or initially denied and granted later. For example, if an application
requests audio focus during a phone call, it will be denied, but focus may well be granted once the phone call is
finished. In this case, a listener is registered in order to respond accordingly if audio focus is taken away.
Requesting audio focus is used to determine whether or not it is OK to play or record audio.
For more information about audio focus, see Managing Audio Focus.
Registering the Callback for Audio Focus
Registering the FocusChangeListener callback from the IOnAudioChangeListener is an important part of obtaining
and releasing audio focus. This is because the granting of audio focus may be deferred until a later time. For
example, an application may request to play music while there is a phone call in progress. Audio focus will not be
granted until the phone call is finished.
For this reason, the callback object is passed as a parameter into the GetAudioFocus method of the AudioManager ,
and it is this call that registers the callback. If audio focus is initially denied but later granted, the application is
informed by invoking OnAudioFocusChange on the callback. The same method is used to tell the application that
audio focus is being taken away.
When the application has finished using the audio resources, it calls the AbandonFocus method of the AudioManager
, and again passes in the callback. This deregisters the callback and releases the audio resources, so that other
applications may obtain audio focus.
Requesting Audio Focus
The steps required to request the audio resources of the device are as follow:
1. Obtain a handle to the AudioManager system service.
2. Create an instance of the callback class.
3. Request the audio resources of the device by calling the RequestAudioFocus method on the AudioManager .
The parameters are the callback object, the stream type (music, voice call, ring etc.) and the type of the
access right being requested (the audio resources can be requested momentarily or for an indefinite period,
for example).
4. If the request is granted, the playMusic method is invoked immediately, and the audio starts to play back.
5. If the request is denied, no further action is taken. In this case, the audio will only play if the request is
granted at a later time.
The code sample below shows these steps:

Boolean RequestAudioResources(INotificationReceiver parent)


{
AudioManager audioMan = (AudioManager) GetSystemService(Context.AudioService);
AudioManager.IOnAudioFocusChangeListener listener = new MyAudioListener(this);
var ret = audioMan.RequestAudioFocus (listener, Stream.Music, AudioFocus.Gain );
if (ret == AudioFocusRequest.Granted) {
playMusic();
return (true);
} else if (ret == AudioFocusRequest.Failed) {
return (false);
}
return (false);
}
Releasing Audio Focus
When the playback of the track is complete, the AbandonFocus method on AudioManager is invoked. This allows
another application to gain the audio resources of the device. Other applications will receive a notification of this
audio focus change if they have registered their own listeners.

Low Level Audio API


The low -level audio APIs provide a greater control over audio playing and recording because they interact directly
with memory buffers instead of using file URIs. There are some scenarios where this approach is preferable. Such
scenarios include:
1. When playing from encrypted audio files.
2. When playing a succession of short clips.
3. Audio streaming.
AudioTrack Class
The AudioTrack class uses the low -level audio APIs for recording, and is the low -level equivalent of the
MediaPlayer class.

Initializing and Playing


To play audio, a new instance of AudioTrack must be instantiated. The argument list passed into the constructor
specifies how to play the audio sample contained in the buffer. The arguments are:
1. Stream type – Voice, ringtone, music, system or alarm.
2. Frequency – The sampling rate expressed in Hz.
3. Channel Configuration – Mono or stereo.
4. Audio format – 8 bit or 16 bit encoding.
5. Buffer size – in bytes.
6. Buffer mode – streaming or static.
After construction, the Play method of AudioTrack is invoked, to set it up to start playing. Writing the audio buffer
to the AudioTrack starts the playback:

void PlayAudioTrack(byte[] audioBuffer)


{
AudioTrack audioTrack = new AudioTrack(
// Stream type
Stream.Music,
// Frequency
11025,
// Mono or stereo
ChannelOut.Mono,
// Audio encoding
Android.Media.Encoding.Pcm16bit,
// Length of the audio clip.
audioBuffer.Length,
// Mode. Stream or static.
AudioTrackMode.Stream);

audioTrack.Play();
audioTrack.Write(audioBuffer, 0, audioBuffer.Length);
}

Pausing and Stopping the Playback


Call the Pause method to pause the playback:

audioTrack.Pause();

Calling the Stop method will terminate the playback permanently:

audioTrack.Stop();

Cleanup
When the AudioTrack is no longer needed, its resources must be released by calling Release:

audioTrack.Release();

The AudioRecord Class


The AudioRecord class is the equivalent of AudioTrack on the recording side. Like AudioTrack , it uses memory
buffers directly, in place of files and URIs. It requires that the RECORD_AUDIO permission be set in the manifest.
Initializing and Recording
The first step is to construct a new AudioRecord object. The argument list passed into the constructor provides all
the information required for recording. Unlike in AudioTrack , where the arguments are largely enumerations, the
equivalent arguments in AudioRecord are integers. These include:
1. Hardware audio input source such as microphone.
2. Stream type – Voice, ringtone, music, system or alarm.
3. Frequency – The sampling rate expressed in Hz.
4. Channel Configuration – Mono or stereo.
5. Audio format – 8 bit or 16 bit encoding.
6. Buffer size-in bytes
Once the AudioRecord is constructed, its StartRecording method is invoked. It is now ready to begin recording. The
AudioRecord continuously reads the audio buffer for input, and writes this input out to an audio file.
void RecordAudio()
{
byte[] audioBuffer = new byte[100000];
var audRecorder = new AudioRecord(
// Hardware source of recording.
AudioSource.Mic,
// Frequency
11025,
// Mono or stereo
ChannelIn.Mono,
// Audio encoding
Android.Media.Encoding.Pcm16bit,
// Length of the audio clip.
audioBuffer.Length
);
audRecorder.StartRecording();
while (true) {
try
{
// Keep reading the buffer while there is audio input.
audRecorder.Read(audioBuffer, 0, audioBuffer.Length);
// Write out the audio file.
} catch (Exception ex) {
Console.Out.WriteLine(ex.Message);
break;
}
}
}

Stopping the Recording


Calling the Stop method terminates the recording:

audRecorder.Stop();

Cleanup
When the AudioRecord object is no longer needed, calling its Release method releases all resources associated
with it:

audRecorder.Release();

Summary
The Android OS provides a powerful framework for playing, recording and managing audio. This article covered
how to play and record audio using the high-level MediaPlayer and MediaRecorder classes. Next, it explored how
to use audio notifications to share the audio resources of the device between different applications. Finally, it dealt
with how to playback and record audio using the low -level APIs, which interface directly with memory buffers.

Related Links
Working With Audio (sample)
Media Player
Media Recorder
Audio Manager
Audio Track
Audio Recorder
Notifications in Xamarin.Android
4/12/2018 • 2 minutes to read • Edit Online

Overview
This section explains how to implement notifications in Xamarin.Android. It describes the various UI elements of
an Android notification and discusses the API's involved with creating and displaying a notification.

Sections
Local Notifications In Android
This section explains how to implement local notifications in Xamarin.Android. It describes the various UI
elements of an Android notification and discuss the API's involved with creating and displaying a notification.
Walkthrough - Using Local Notifications in Xamarin.Android
This walkthrough covers how to use local notifications in a Xamarin.Android application. It demonstrates the
basics of creating and publishing a notification. When the user clicks on the notification in the notification drawer
it starts up a second Activity.

For Further Reading


Firebase Cloud Messaging – Firebase Cloud Messaging (FCM ) is a service that facilitates messaging between
mobile apps and server applications. Firebase Cloud Messaging can be used to implement remote notifications
(also called push notifications) in Xamarin.Android applications.
Notifications – This Android Developer topic is the definitive guide for Android notifications. It includes a design
considerations section that helps you design your notifications so that they conform to the guidelines of the
Android user interface. It provides more background information about preserviing navigation when starting an
Activity, and it explains how to display progress in a notification and control media playback on the Lock Screen.
NotificationListenerService – This Android service makes it possible for your app to listen to (and interact with) all
notifications posted on the Android device, not just the notifications that your app is registered to receive. Note
that the user must explicitly give permission to your app for it to be able to listen for notifications on the device.

Related Links
Local Notifications (sample)
Remote Notifications (sample)
Local Notifications
7/25/2018 • 30 minutes to read • Edit Online

This section shows how to implement local notifications in Xamarin.Android. It explains the various UI elements
of an Android notification and discusses the API's involved with creating and displaying a notification.

Local Notifications Overview


This topic explains how to implement local notifications in a Xamarin.Android application. It discusses the
various parts of an Android notification, it explains the different notification styles that are available to app
developers, and it introduces some of the APIs that are used to create and publish notifications.
Android provides two system-controlled areas for displaying notification icons and notification information to
the user. When a notification is first published, its icon is displayed in the notification area, as shown in the
following screen shot:

To obtain details about the notification, the user can open the notification drawer (which expands each
notification icon to reveal notification content) and perform any actions associated with the notifications. The
following screen shot shows a notification drawer that corresponds to the notification area displayed above:

Android notifications use two types of layouts:


Base layout – a compact, fixed presentation format.
Expanded layout – a presentation format that can expand to a larger size to reveal more information.
Each of these layout types (and how to create them) is explained in the following sections.
Base Layout
All Android notifications are built on the base layout format, which, at a minimum, includes the following
elements:
1. A notification icon, which represents the originating app, or the notification type if the app supports
different types of notifications.
2. The notification title, or the name of the sender if the notification is a personal message.
3. The notification message.
4. A timestamp.
These elements are displayed as illustrated in the following diagram:

Base layouts are limited to 64 density-independent pixels (dp) in height. Android creates this basic notification
style by default.
Optionally, notifications can display a large icon that represents the application or the sender's photo. When a
large icon is used in a notification in Android 5.0 and later, the small notification icon is displayed as a badge over
the large icon:

Beginning with Android 5.0, notifications can also appear on the lockscreen:

The user can double-tap the lockscreen notification to unlock the device and jump to the app that originated that
notification, or swipe to dismiss the notification. Apps can set the visibility level of a notification to control what is
shown on the lockscreen, and users can choose whether to allow sensitive content to be shown in lockscreen
notifications.
Android 5.0 introduced a high-priority notification presentation format called Heads-up. Heads-up notifications
slide down from the top of the screen for a few seconds and then retreat back up to the notification area:

Heads-up notifications make it possible for the system UI to put important information in front of the user
without disrupting the state of the currently running activity.
Android includes support for notification metadata so that notifications can be sorted and displayed intelligently.
Notification metadata also controls how notifications are presented on the lockscreen and in Heads-up format.
Applications can set the following types of notification metadata:
Priority – The priority level determines how and when notifications are presented. For example, In
Android 5.0, high-priority notifications are displayed as Heads-up notifications.
Visibility – Specifies how much notification content is to be displayed when the notification appears on
the lockscreen.
Category – Informs the system how to handle the notification in various circumstances, such as when the
device is in Do not Disturb mode.
Note: Visibility and Category were introduced in Android 5.0 and are not available in earlier versions of
Android. Beginning with Android 8.0, notification channels are used to control how notifications are presented to
the user.
Expanded Layouts
Beginning with Android 4.1, notifications can be configured with expanded layout styles that allow the user to
expand the height of the notification to view more content. For example, the following example illustrates an
expanded layout notification in contracted mode:

When this notification is expanded, it reveals the entire message:


Android supports three expanded layout styles for single-event notifications:
Big Text – In contracted mode, displays an excerpt of the first line of the message followed by two
periods. In expanded mode, displays the entire message (as seen in the above example).
Inbox – In contracted mode, displays the number of new messages. In expanded mode, displays the first
email message or a list of the messages in the inbox.
Image – In contracted mode, displays only the message text. In expanded mode, displays the text and an
image.
Beyond the Basic Notification (later in this article) explains how to create Big Text, Inbox, and Image notifications.

Notification Creation
To create a notification in Android, you use the Notification.Builder class. Notification.Builder was introduced
in Android 3.0 to simplify the creation of notification objects. To create notifications that are compatible with
older versions of Android, you can use the NotificationCompat.Builder class instead of Notification.Builder
(see Compatibility later in this topic for more information about using NotificationCompat.Builder ).
Notification.Builder provides methods for setting the various options in a notification, such as:

The content, including the title, the message text, and the notification icon.
The style of the notification, such as Big Text, Inbox, or Image style.
The priority of the notification: minimum, low, default, high, or maximum.
The visibility of the notification on the lockscreen: public, private, or secret.
Category metadata that helps Android classify and filter the notification.
An optional intent that indicates an activity to launch when the notification is tapped.
After you set these options in the builder, you generate a notification object that contains the settings. To publish
the notification, you pass this notification object to the Notification Manager. Android provides the
NotificationManager class, which is responsible for publishing notifications and displaying them to the user. A
reference to this class can be obtained from any context, such as an activity or a service.
How to Generate a Notification
To generate a notification in Android, follow these steps:
1. Instantiate a Notification.Builder object.
2. Call various methods on the Notification.Builder object to set notification options.
3. Call the Build method of the Notification.Builder object to instantiate a notification object.
4. Call the Notify method of the notification manager to publish the notification.
You must provide at least the following information for each notification:
A small icon (24x24 dp in size)
A short title
The text of the notification
The following code example illustrates how to use Notification.Builder to generate a basic notification. Notice
that Notification.Builder methods support method chaining; that is, each method returns the builder object so
you can use the result of the last method call to invoke the next method call:

// Instantiate the builder and set notification elements:


Notification.Builder builder = new Notification.Builder (this)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);

// Build the notification:


Notification notification = builder.Build();

// Get the notification manager:


NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;

// Publish the notification:


const int notificationId = 0;
notificationManager.Notify (notificationId, notification);

In this example, a new Notification.Builder object called builder is instantiated, the title and text of the
notification are set, and the notification icon is loaded from Resources/drawable/ic_notification.png. The call
to the notification builder's Build method creates a notification object with these settings. The next step is to call
the Notify method of the notification manager. To locate the notification manager, you call GetSystemService , as
shown above.
The Notify method accepts two parameters: the notification identifier and the notification object. The
notification identifier is a unique integer that identifies the notification to your application. In this example, the
notification identifier is set to zero (0); however, in a production application, you will want to give each
notification a unique identifier. Reusing the previous identifier value in a call to Notify causes the last
notification to be overwritten.
When this code runs on an Android 5.0 device, it generates a notification that looks like the following example:

The notification icon is displayed on the left hand side of the notification – this image of a circled “i” has an alpha
channel so that Android can draw a gray circular background behind it. You can also supply an icon without an
alpha channel. To display a photographic image as an icon, see Large Icon Format later in this topic.
The timestamp is set automatically, but you can override this setting by calling the SetWhen method of the
notification builder. For example, the following code example sets the timestamp to the current time:

builder.SetWhen (Java.Lang.JavaSystem.CurrentTimeMillis());

Enabling Sound and Vibration


If you want your notification to also play a sound, you can call the notification builder's SetDefaults method and
pass in the NotificationDefaults.Sound flag:
// Instantiate the notification builder and enable sound:
Notification.Builder builder = new Notification.Builder (this)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first notification!")
.SetDefaults (NotificationDefaults.Sound)
.SetSmallIcon (Resource.Drawable.ic_notification);

This call to SetDefaults will cause the device to play a sound when the notification is published. If you want the
device to vibrate rather than play a sound, you can pass NotificationDefaults.Vibrate to SetDefaults. If you
want the device to play a sound and vibrate the device, you can pass both flags to SetDefaults :

builder.SetDefaults (NotificationDefaults.Sound | NotificationDefaults.Vibrate);

If you enable sound without specifying a sound to play, Android uses the default system notification sound.
However, you can change the sound that will be played by calling the notification builder's SetSound method.
For example, to play the alarm sound with your notification (instead of the default notification sound), you can
get the URI for the alarm sound from the RingtoneManager and pass it to SetSound :

builder.SetSound (RingtoneManager.GetDefaultUri(RingtoneType.Alarm));

Alternatively, you can use the system default ringtone sound for your notification:

builder.SetSound (RingtoneManager.GetDefaultUri(RingtoneType.Ringtone));

After you create a notification object, it's possible to set notification properties on the notification object (rather
than configure them in advance through Notification.Builder methods). For example, instead of calling the
SetDefaults method to enable vibration on a notification, you can directly modify the bit flag of the notification's
Defaults property:

// Build the notification:


Notification notification = builder.Build();

// Turn on vibrate:
notification.Defaults |= NotificationDefaults.Vibrate;

This example causes the device to vibrate when the notification is published.
Updating a Notification
If you want to update the content of a notification after it has been published, you can reuse the existing
Notification.Builder object to create a new notification object and publish this notification with the identifier of
the last notification. For example:

// Update the existing notification builder content:


builder.SetContentTitle ("Updated Notification");
builder.SetContentText ("Changed to this message.");

// Build a notification object with updated content:


notification = builder.Build();

// Publish the new notification with the existing ID:


notificationManager.Notify (notificationId, notification);

In this example, the existing Notification.Builder object is used to create a new notification object with a
different title and message. The new notification object is published using the identifier of the previous
notification, and this updates the content of the previously-published notification:

The body of the previous notification is reused – only the title and the text of the notification changes while the
notification is displayed in the notification drawer. The title text changes from "Sample Notification" to "Updated
Notification" and the message text changes from "Hello World! This is my first notification!" to "Changed to this
message."
A notification remains visible until one of three things happens:
The user dismisses the notification (or taps Clear All).
The application makes a call to NotificationManager.Cancel , passing in the unique notification ID that was
assigned when the notification was published.
The application calls NotificationManager.CancelAll .
For more about updating Android notifications, see Modify a Notification.
Starting an Activity from a Notification
In Android, it's common for a notification to be associated with an action – an activity that's launched when the
user taps the notification. This activity can reside in another application or even in another task. To add an action
to a notification, you create a PendingIntent object and associate the PendingIntent with the notification. A
PendingIntent is a special type of intent that allows the recipient application to run a predefined piece of code
with the permissions of the sending application. When the user taps the notification, Android starts up the
activity specified by the PendingIntent .
The following code snippet illustrates how to create a notification with a PendingIntent that will launch the
activity of the originating app, MainActivity :

// Set up an intent so that tapping the notifications returns to this app:


Intent intent = new Intent (this, typeof(MainActivity));

// Create a PendingIntent; we're only using one PendingIntent (ID = 0):


const int pendingIntentId = 0;
PendingIntent pendingIntent =
PendingIntent.GetActivity (this, pendingIntentId, intent, PendingIntentFlags.OneShot);

// Instantiate the builder and set notification elements, including pending intent:
Notification.Builder builder = new Notification.Builder(this)
.SetContentIntent (pendingIntent)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first action notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);

// Build the notification:


Notification notification = builder.Build();

// Get the notification manager:


NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;

// Publish the notification:


const int notificationId = 0;
notificationManager.Notify (notificationId, notification);
This code is very similar to the notification code in the previous section, except that a PendingIntent is added to
the notification object. In this example, the PendingIntent is associated with the activity of the originating app
before it is passed to the notification builder's SetContentIntent method. The PendingIntentFlags.OneShot flag is
passed to the PendingIntent.GetActivity method so that the PendingIntent is used only once. When this code
runs, the following notification is displayed:

Tapping this notification takes the user back to the originating activity.
In a production app, your app must handle the back stack when the user presses the Back button within the
notification activity (if you are not familiar with Android tasks and the back stack, see Tasks and Back Stack). In
most cases, navigating backward out of the notification activity should return the user out of the app and back to
Home screen. To manage the back stack, your app uses the TaskStackBuilder class to create a PendingIntent
with a back stack.
Another real-world consideration is that the originating activity may need to send data to the notification activity.
For example, the notification may indicate that a text message has arrived, and the notification activity (a
message viewing screen), requires the ID of the message to display the message to the user. The activity that
creates the PendingIntent can use the Intent.PutExtra method to add data (for example, a string) to the intent so
that this data is passed to the notification activity.
The following code sample illustrates how to use TaskStackBuilder to manage the back stack, and it includes an
example of how to send a single message string to a notification activity called SecondActivity :
// Setup an intent for SecondActivity:
Intent secondIntent = new Intent (this, typeof(SecondActivity));

// Pass some information to SecondActivity:


secondIntent.PutExtra ("message", "Greetings from MainActivity!");

// Create a task stack builder to manage the back stack:


TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);

// Add all parents of SecondActivity to the stack:


stackBuilder.AddParentStack (Java.Lang.Class.FromType (typeof (SecondActivity)));

// Push the intent that starts SecondActivi