Jon Douglas The rantings of a developer

MSBuild Basics

MSBuild Basics

MSBuild is the music conductor of build tooling. It is extremely powerful for understanding and customizing your build process.

Quick Installation

You should have MSBuild installed already on your computer. Ensure you are in the correct path or add the msbuild path to your Environment Variables.

Basic MSBuild command:

msbuild [INPUT].csproj /t:[TARGET]

Project File (.csproj is the MSBuild file)

<Project xmlns="">

Xamarin.Android Example:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="">

All content will be placed inside of the <Project> tag. This includes, properties, items, targets, etc.

Think of this as the files being build, parameters for build, and much more.


MSBuild properties are key-value pairs. The key is the name that you use to refer the property. The value is the value of the property.

When declaring a property, they must be contained inside a <PropertyGroup> element. This element must be inside of the <Project> element.

Note: You can have separate properties as long as they are in their own element.

Xamarin.Android Example:

    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

Tasks and Targets


A Task is the smallest unit of work. Typically known as an action or routine.

Example of a Task:

<Message Text="Hello Support Team Members!" />


A Target is a series of executable steps/tasks.

Example of an empty Target:

<Target Name="HelloSupportTeam">

Default Tasks

Copy, Move, Exec, ResGen, Csc - Copy Files, Move Files, Execute a program, Generate Resources, C# Compiler

Message - Sends a message to the loggers that are listening in the build process.

<Target Name="HelloSupportTeam">
    <Message Text="Hello Support Team Members!" />

Running a Target

A Target can be run in MSBuild simply by the following syntax

msbuild MyProject.csproj /t:<TargetName> or msbuild MyProject.csproj /target:<TargetName>

Let’s try running the HelloSupportTeam target now.

msbuild MyProject.csproj /t:HelloSupportTeam

You should see the following output:

  Hello Support Team Members!

Properties inside a Task

Let’s now define a <PropertyGroup> with our message instead.

    <HelloSupportTeamMessage>Hello again brownbaggers!</HelloSupportTeamMessage>

Now we need to use the property variable instead. Let’s edit our <Message> Task. The syntax for a property in MSBuild is $(PropertyName):

<Target Name="HelloSupportTeam">
    <Message Text="$(HelloSupportTeamMessage)" />

Items (Aka Files)

Items are file-based references. Similar to <PropertyGroup>, you define them by using an <ItemGroup> instead.

Xamarin.Android Example:

    <Compile Include="MainActivity.cs" />
    <Compile Include="Resources\Resource.Designer.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />

To evaulate an item, you would use the @(ItemType) syntax. Let’s now spit out a Message to see what is all going to be compiled here.

<Target Name="PrintCompileInfo">
    <Message Text="Compile: @(Compile)" />

Item Metadata

Items have metadata to them as well. There are many well-known metadata items that we can query, however I will not be going into detail on them all. Here is a sample of getting the directory of an item:

<Target Name="PrintMetadata">
    <Message Text="%40(Compile-> '%25(Directory)'): @(Compile->'%(Directory)')" />

Conditions (

Condition are used to evaluate a true or false condition.

Xamarin.Android Example:

  <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

You can check multiple types of conditions such as:

  • == - Equality
  • != - Inequality
  • Exists - If something exists
  • !Exists - If something does not exist

Conditions are especially useful for adding an Item based on a condition such as a $(Configuration) being Debug or Release

Initial Targets

You may be asking yourself…How the hell do we know what Target get executed first? Well the truth is, I slipped a detail past you really quickly. Let’s go back to our original definition of our <Project>:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="">

This will default any Target named Build will be the default target if no other Target is defined when invoking.

Extending MSBuild

Okay now for the actual fun part. Extending the build process.

There’s a few ways to extend the MSBuild process in the sense of a pre or post build action.

  1. Pre and Post build events
  2. Override BeforeBuild / AfterBuild target
  3. Extend the BuildDependsOn list
<Target Name="BeforeBuild">

<Target Name="AfterBuild">

Common files names

.proj or .csproj

.proj is the generic. .csproj is a C# specific. .vbproj is the Visual Basic specific


.targets is a file that contains shared targets which are imported into other files


.props is a file that contains settings for the build process


.tasks is a file that contains UsingTask definitions

Intellisense of items

There’s a few xsd files that are used in VS for general intellisense. You can also look for an item directly by opening the schema:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Xml\Schemas\1033\MSBuild

Debugging Tasks

Three main ways:

  1. Use logs of logging statements and examine the logger
  2. Use Debugger.Launch() to prompt for a debugger attachment
  3. Start MSBuild as an external program, and then debug normally

Other Resources

The most invaluable resource you’ll have on MSBuild is Sayed’s book:

Video Resources:

Xamarin.Android Proguard Notes


So you’ve heard of this tool called “Proguard” which can Shrink and Optimize unused code from our apps and the libraries they reference. Little did you know that you actually have to do a bit of work so Proguard can work for you.

Holy Notes Batman!

Have you ever enabled Proguard in your project and now your Build Output is plagued by logs of Note:?

Here’s a sample of a Build Output of a project that has the Xamarin Android Support Library - Design( installed. This of course has a large list of dependencies on other support libraries.

You may notice hundreds of notes saying

Note: the configuration doesn't specify which class members to keep for class `package.ClassName`

Proguard Summary

However let’s first get some numbers about just how much is affecting us. At the bottom of our Proguard Task, we will find a summary that let’s us know exactly how much.

1>  Note: there were 109 references to unknown classes. (TaskId:247)
1>        You should check your configuration for typos. (TaskId:247)
1>        ( (TaskId:247)
1>  Note: there were 1 classes trying to access generic signatures using reflection. (TaskId:247)
1>        You should consider keeping the signature attributes (TaskId:247)
1>        (using '-keepattributes Signature'). (TaskId:247)
1>        ( (TaskId:247)
1>  Note: there were 10 unkept descriptor classes in kept class members. (TaskId:247)
1>        You should consider explicitly keeping the mentioned classes (TaskId:247)
1>        (using '-keep'). (TaskId:247)
1>        ( (TaskId:247)
1>  Note: there were 5 unresolved dynamic references to classes or interfaces. (TaskId:247)
1>        You should check if you need to specify additional program jars. (TaskId:247)
1>        ( (TaskId:247)
1>  Note: there were 6 accesses to class members by means of introspection. (TaskId:247)
1>        You should consider explicitly keeping the mentioned class members (TaskId:247)
1>        (using '-keep' or '-keepclassmembers'). (TaskId:247)
1>        ( (TaskId:247)

Proguard Reminder

Before jumping into these items one by one, let’s first understand what’s going on when we are calling Proguard.

Simply put, we are calling the Proguard.jar and providing various Configuration files that depict how Proguard should process the shrinking.

The three main files to care about are the following:


These are rules unique to Xamarin. Such as ensuring to keep the mono, android, and java classes that Xamarin.Android relies on.



These are rules that are generated based on the ACW(Android Callable Wrappers) of your references. In this case the Xamarin.Android.Support.Design library and it’s dependencies.



These are rules that are generated based on your Application.


Custom proguard.cfg

Finally it will include your custom Proguard.cfg file which is defined with the Build Action of ProguardConfiguration.

Let’s break these notes down one by one:

references to unknown classes

1>  Note: there were 109 references to unknown classes. (TaskId:247)
1>        You should check your configuration for typos. (TaskId:247)
1>        ( (TaskId:247)

Your configuration refers to the name of a class that is not present in the program jars or library jars. You should check whether the name is correct. Notably, you should make sure that you always specify fully-qualified names, not forgetting the package names.

We can now search for the keywords unknown class within our Build Output and see what type of classes it’s throwing this Note: for.

EX: Note: the configuration refers to the unknown class ''

So it is saying that our configuration refers to this unknown class, but if we did a bit of searching, we don’t see this class anywhere within our .cfg files above. Let’s add some diagnostics by adding the -printconfiguration config.txt rule into our custom Proguard.cfg file.

If we now look through this config.txt file, we will see the rule caught red handed:

-keep public class

Unfortunately this is a limitation of generation of Proguard rules. Some of these will be completely out of your control.

access generic signatures using reflection

1>  Note: there were 1 classes trying to access generic signatures using reflection. (TaskId:247)
1>        You should consider keeping the signature attributes (TaskId:247)
1>        (using '-keepattributes Signature'). (TaskId:247)
1>        ( (TaskId:247)

Your code uses reflection to access metadata from the code, with an invocation like “class.getAnnotations()”. You then generally need to preserve optional class file attributes, which ProGuard removes by default. The attributes contain information about annotations, enclosing classes, enclosing methods, etc. In a summary in the log, ProGuard provides a suggested configuration, like -keepattributes Annotation. If you’re sure the attributes are not necessary, you can switch off these notes by specifying the -dontnote option.

This one however is straight forward by just adding the -keepattributes Signature to our Custom Proguard.cfg file.

unkept descriptor classes in kept class members.

1>  Note: there were 10 unkept descriptor classes in kept class members. (TaskId:247)
1>        You should consider explicitly keeping the mentioned classes (TaskId:247)
1>        (using '-keep'). (TaskId:247)
1>        ( (TaskId:247)

Your configuration contains a -keep option to preserve the given method (or field), but no -keep option for the given class that is an argument type or return type in the method’s descriptor. You may then want to keep the class too. Otherwise, ProGuard will obfuscate its name, thus changing the method’s signature. The method might then become unfindable as an entry point, e.g. if it is part of a public API. You can automatically keep such descriptor classes with the -keep option modifier includedescriptorclasses (-keep,includedescriptorclasses …). You can switch off these notes by specifying the -dontnote option.

You know the process now, let’s search for “descriptor class” in our Build Output.

EX: Note: the configuration keeps the entry point '$SnackbarBaseLayout { void setOnLayoutChangeListener($OnLayoutChangeListener); }', but not the descriptor class '$OnLayoutChangeListener'

Again, search the config.txt for the first class to ensure it’s there:

i.e. -keep class$SnackbarBaseLayout

We do see it inside. So it’s saying we need a -keep rule for$OnLayoutChangeListener. Let’s now add that to our Custom Proguard.cfg file:

-keep class$OnLayoutChangeListener

unresolved dynamic references to classes or interfaces.

1>  Note: there were 5 unresolved dynamic references to classes or interfaces. (TaskId:247)
1>        You should check if you need to specify additional program jars. (TaskId:247)
1>        ( (TaskId:247)

ProGuard can’t find a class or interface that your code is accessing by means of introspection. You should consider adding the jar that contains this class.

Let’s search for dynamically referenced class in our Build Output.

EX: Note: can't find dynamically referenced class

Unfortunately this one isn’t that straight forward as something is referencing classes or interfaces that are not present in our project. To solve this, we would have to find the dependency and add it via NuGet.

accesses to class members by means of introspection.

1>  Note: there were 6 accesses to class members by means of introspection. (TaskId:247)
1>        You should consider explicitly keeping the mentioned class members (TaskId:247)
1>        (using '-keep' or '-keepclassmembers'). (TaskId:247)
1>        ( (TaskId:247)

Your code uses reflection to find a fields or a method, with a construct like “.getField(“myField”)”. Depending on your application, you may need to figure out where the mentioned class members are defined and keep them with an option like “-keep class MyClass { MyFieldType myField; }”. Otherwise, ProGuard might remove or obfuscate the class members, since it can’t know which ones they are exactly. It does list possible candidates, for your information. You can switch off these notes by specifying the -dontnote option.

EX: Note: accesses a declared field 'icon' dynamically

We may just want to let Proguard know “Hey please don’t note me on this”. We can use the -dontnote rule for this specific class. Let’s add this to our Custom Proguard.cfg file:



Now you should know the basics of how Proguard shrinks our code and how we can adjust to the notes that proguard gives us. For the most part, Proguard does a great job of documenting what is going on and how you can fix certain scenarios. Take the time to read through your Proguard logs to optimize the ruleset so Proguard can work for you!

As a bonus, you can always start off with some of these community created Proguard rules to help give you a jump start with these libraries and proguard.

If you enjoyed this post, please consider subscribing to my upcoming book’s email list:

You can signup at the following link: Programming Xamarin.Android Email List

Xamarin.Android Linker Tricks Part 1 - Bitdiffer


The linker used in Xamarin.Android applications has historically been a painpoint for developers.

This is mainly because as developers, we only use a small portion of the assemblies we consume. For the rest of those assemblies, we consider using a linker mechanism so we reap the benefits of having a smaller assembly at the end of the day.

To give a real world example of what the linker does, I’ve created three .apk files with the different linker options:

  • None
  • Sdk Assemblies Only
  • Sdk and User Assemblies
04/13/2017  11:15 AM        52,160,463 LinkerSample.None.apk
04/13/2017  11:12 AM        21,995,031 LinkerSample.SDK.apk
04/13/2017  11:16 AM        10,130,214 LinkerSample.UserAndSDK.apk

Note: This project includes a reference to the Xamarin.Android.Support.Design NuGet to demonstrate something more than “Hello World”

As you can see, we see the size of 52mb(None), 21mb(SDK), and 10mb(User and SDK). What this means is that in a perfect world, we would want to use Sdk and User Assemblies so we can keep our .apk size down. However using that setting is considered the most aggressive linker setting and it can strip away things that you need to use in your application. Finding out exactly what it strips out is a bit difficult and we should fallback to other tooling.

Using bitdiffer

bitdiffer is a tool that helps compare assembly files. It is extremely useful in the sense of a practical GUI/CLI that lets us see the difference between assemblies. You can download it here:

One of the most useful things bitdiffer does is allows you to add not only 2 assemblies, but a full list for comparison. This is extremely useful for us as developers to see what exactly each linker option does to our assembly.

Consider the following example with the three .apk we created earlier comparing against the Mono.Android.dll assembly. They are ordered None, Sdk Assemblies Only, Sdk and User Assemblies in the tabs:

You can notice off a quick glance that we had quite a difference in Members Changed or Removed between the linker setting None -> Sdk Assemblies Only -> Sdk and User Assemblies.

Now that’s not the only cool feature of this tool, you can also dive down into a specific class to see the diff between your assemblies:

And finally we can dig into what the difference is between members in our class:

Although this is only part 1 of various linker tricks I use to diagnose a problem, this is one of the more powerful ways to approach any linker issues in your project to understand the problem.

If you enjoyed this post, please consider subscribing to my upcoming book’s email list:

You can signup at the following link: Programming Xamarin.Android Email List

APK Tools

APK Tools

I’ve found many APK tools to be quite useful for diagnosing issues with Xamarin.Android. Here is a small list of tools that I find helpful.


apktool is a tool for reverse engineering Android applications. It can be used to decode resources to nearly original form and rebuild them after making some modifications.


One of the most useful usecases of apktool is to ensure your generated .apk is correct. You can use the decode / d method to take an .apk and “unzip” it’s original contents.

usage: apktool d MyApplication.apk


The other usecase is to build a .apk after making a couple of modifications. You can use the build / b method to build an .apk

usage: apktool b foo

Which will build a folder named foo into an .apk file.

Note: If you aren’t using the wrapper script, you may need to invoke it via java -jar apktool.jar


aapt provides a couple of useful tools for our .apk files. You can find aapt inside of your Android SDK’s build-tools folder.


aapt list - shows the contents of the package.

usage: aapt list MyApplication.apk



aapt dump - provides values of individual elements or parts of a package. There are a few different items we can dump:

badging - dumps badging information like the versions, sdk targets, etc

usage: aapt dump badging MyApplication.apk

package: name='MyApplication.MyApplication' versionCode='1' versionName='1.0' platformBuildVersionName='7.1.1'
application: label='' icon='res/drawable/icon.png'
launchable-activity: name='md5ef8aabbe49b48f4362a43abcfb4dce14.MainActivity'  label='MyApplication' icon='res/drawable/icon.png'
feature-group: label=''
  uses-feature: name='android.hardware.faketouch'
  uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
densities: '160'
native-code: 'armeabi-v7a'

permissions - dumps permission information such as what uses-permissions are in use

usage: aapt dump permissions MyApplication.apk

package: MyApplication.MyApplication
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.READ_CALENDAR'
uses-permission: name='android.permission.READ_CONTACTS'

resources - dumps resources in each resource category such as string/array/layout/etc

usage: aapt dump resources MyApplication.apk

Package Groups (1)
Package Group 0 id=0x7f packageCount=1 name=MyApplication.MyApplication
  Package 0 id=0x7f name=MyApplication.MyApplication
    type 1 configCount=1 entryCount=1
      spec resource 0x7f020000 MyApplication.MyApplication:drawable/icon: flags=0x00000000
      config (default):
        resource 0x7f020000 MyApplication.MyApplication:drawable/icon: t=0x03 d=0x00000000 (s=0x0008 r=0x00)
    type 2 configCount=1 entryCount=1
      spec resource 0x7f030000 MyApplication.MyApplication:layout/main: flags=0x00000000
      config (default):
        resource 0x7f030000 MyApplication.MyApplication:layout/main: t=0x03 d=0x00000001 (s=0x0008 r=0x00)
    type 3 configCount=1 entryCount=2
      spec resource 0x7f040000 MyApplication.MyApplication:string/Hello: flags=0x00000000
      spec resource 0x7f040001 MyApplication.MyApplication:string/ApplicationName: flags=0x00000000
      config (default):
        resource 0x7f040000 MyApplication.MyApplication:string/Hello: t=0x03 d=0x00000002 (s=0x0008 r=0x00)
        resource 0x7f040001 MyApplication.MyApplication:string/ApplicationName: t=0x03 d=0x00000003 (s=0x0008 r=0x00)

configurations - dumps any configuration that has been setup

usage: aapt dump configurations MyApplication.apk

imsi=0/0 lang=-- reg=-- orient=0 touch=0 dens=160 kbd=0 nav=0 input=0 scrnW=0 scrnH=0 sz=0 long=0 vers=0.0
imsi=0/0 lang=-- reg=-- orient=0 touch=0 dens=240 kbd=0 nav=0 input=0 scrnW=0 scrnH=0 sz=0 long=0 vers=0.0
imsi=0/0 lang=-- reg=-- orient=0 touch=0 dens=0 kbd=0 nav=0 input=0 scrnW=0 scrnH=0 sz=0 long=0 vers=0.0

xmltree - dumps the xml parse tree for an xml file in a package

usage: aapt dump xmltree MyApplication.apk res/layout/main.xml

N: android=
  E: LinearLayout (line=1)
    A: android:orientation(0x010100c4)=(type 0x10)0x1
    A: android:layout_width(0x010100f4)=(type 0x10)0xffffffff
    A: android:layout_height(0x010100f5)=(type 0x10)0xffffffff

xmlstrings - dumps all strings inside for an xml file in a package

usage: aapt dump xmlstrings MyApplication.apk res/layout/main.xml

String pool of 7 unique UTF-8 non-sorted strings, 7 entries and 0 styles using 176 bytes:
String #0: orientation
String #1: layout_width
String #2: layout_height
String #3: android
String #4:
String #5:
String #6: LinearLayout


ClassyShark is a binary inspection tool that can help you find information such as your total dex count, decompilation of .class files, and much more. It supports .dex, .aar, .so, .apk, .jar, .class, .xml files for further inspection.

usage: java -jar classyshark.jar

You should see a program like the following:

You can then inspect any aspect of your binary such as decompiling a class, viewing what’s inside of a dex file, and much more.


You can view what’s inside of your main dex list. Also known as the classes.dex file that is generated in the Android build process.

Methods Count

You can also see the current method count of the classes.dex list from an overview


Although this blog post only showcases 3 tools, there are so many ways to get information from your binaries to diagnose issues such as multidex, versioning, etc in you Xamarin.Android application!

If you enjoyed this post, please consider subscribing to my upcoming book’s email list:

You can signup at the following link: Programming Xamarin.Android Email List

Xamarin.Android - Things

All the Android Things - Weather Station

When Android Things was first announced, my inner inventor came out. I wanted to start prototyping all of these ideas that have been spinning around my head. I wanted to be the next Red Green.

(If you aren’t familiar. He was the main character of The Red Green Show, which was a popular Canadian parody of a typical DIY/home improvement show. In the show, they would have some zany premise of automating things that are often painful like mowing your lawn, rolling down manual car windows, and serving beverages).

Android Things

Android Things provides the same Android development tools that we know and love to work with embedded devices. You can see a quick overview of this here:

There are two main components of the Things Support Library that we need to know before starting a prototype.

Peripheral I/O API

The Peripheral I/O APIs let your apps communicate with sensors and actuators using industry standard protocols and interfaces. The following interfaces are supported: GPIO, PWM, I2C, SPI, UART.

User Driver API

User drivers extend existing Android framework services and allow apps to inject hardware events into the framework that other apps can access using the standard Android APIs.

What you’ll need

Optional: You can also pick up a Pimoroni Rainbow HAT for a plug-and-play buffet of inputs, sensors, etc to explore Android Things.

Getting Started

Once you’ve gathered your materials, you’ll need to flash your device. After you’ve flashed your device, you will need to setup a network connection. You can follow the various instructions for doing this here:

Set Up Your Development Environment

After you’ve flashed your device and have it connected to your network, we want to ensure it’s available via adb. You can use the following command to ensure this:

adb devices

When you bootup the Android Things device, you can either have it connected to an ethernet cord, or to your wireless network. Either way, you will want to use adb connect <ip address> to connect to the device.

Android Weather Station Sample

This sample is an integration of multiple peripheral sensors to analyze and display current weather information.

You can find the source code of this sample here:



Displays the current weather situation. Sunny, Cloudy, or Rainy.

Raspberry Pi 3

Displays the current realtime temperature in Celsius. Here’s a video of it in action:


Android Things is really fun to tinker around with. Let your inner Red Green or Tim “The Tool Man” Taylor shine!