<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Android - Greg Shackles]]></title><description><![CDATA[Android - Greg Shackles]]></description><link>https://gregshackles.com/</link><image><url>https://gregshackles.com/favicon.png</url><title>Android - Greg Shackles</title><link>https://gregshackles.com/</link></image><generator>Ghost 4.32</generator><lastBuildDate>Tue, 09 Jun 2026 21:40:26 GMT</lastBuildDate><atom:link href="https://gregshackles.com/tag/android/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Getting Started with Estimote Nearables and Xamarin]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;ve been a big fan of Estimote (and beacons in general) for awhile now, but only just recently had a chance to finally play around with their nearables, dubbed <a href="https://community.estimote.com/hc/en-us/articles/203323543-What-are-Estimote-Stickers-">Estimote Stickers</a>. These stickers are similar to beacons, except that their primary purpose is to be attached to physical</p>]]></description><link>https://gregshackles.com/getting-started-with-estimote-nearables-and-xamarin/</link><guid isPermaLink="false">61ce48a0437e8200017d4132</guid><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Beacons]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Tue, 29 Sep 2015 19:01:51 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;ve been a big fan of Estimote (and beacons in general) for awhile now, but only just recently had a chance to finally play around with their nearables, dubbed <a href="https://community.estimote.com/hc/en-us/articles/203323543-What-are-Estimote-Stickers-">Estimote Stickers</a>. These stickers are similar to beacons, except that their primary purpose is to be attached to physical objects, and in addition to proximity also broadcast more contextual information about the object. This extra information contains a bunch of interesting details such as temperature, orientation, and motion in three dimensions.</p>
<h1 id="gettingstarted">Getting Started</h1>
<p>With these stickers in my possession, the first step was seeing what was involved in getting set up with Estimote&apos;s SDK for interacting with the stickers. Thankfully this is as trivial as it gets. Simply head over to the Xamarin Component Store, grab the components for <a href="http://components.xamarin.com/view/estimotesdkios">iOS</a> and <a href="http://components.xamarin.com/view/estimotesdkandroid">Android</a>, and you&apos;re good to go!</p>
<h2 id="ios">iOS</h2>
<p>With that installed, it&apos;s just as easy to start detecting nearables:</p>
<pre><code class="language-language-csharp">var manager = new NearableManager();

manager.RangedNearables += (sender, e) =&gt;
{
	foreach (var nearable in e.Nearables ?? Enumerable.Empty&lt;Nearable&gt;())
	    Console.WriteLine(nearable);
};
manager.StartRangingForType(NearableType.All);
</code></pre>
<p>On iOS8+ you also need to specify a value for <code>NSLocationAlwaysUsageDescription</code> or <code>NSLocationWhenInUseUsageDescription</code> in your <code>Info.plist</code> file in order to get access to the iOS location APIs, which Estimote sits on top of.</p>
<p>If you&apos;re only looking for a specific nearable type you can alternatively specify that in the call to <code>StartRangingForType()</code>, instead of always scanning for all types. Other types available as of right now include <code>Dog</code>, <code>Fridge</code>, <code>Door</code>, <code>Generic</code>, and more. That&apos;s all you need to initiate basic scanning for nearables, and you will get access to all the discovered nearables in the <code>RangedNearables</code> callback.</p>
<h2 id="android">Android</h2>
<p>The Android SDK is also easy to get up and running with, though I do find it a bit lacking compared to the iOS one (more on that later). Here is an activity that starts scanning for nearables when it loads up:</p>
<pre><code class="language-language-csharp">[Activity(Label = &quot;Nearables!&quot;, MainLauncher = true, Icon = &quot;@mipmap/icon&quot;)]
public class MainActivity : Activity, BeaconManager.IServiceReadyCallback
{
    private BeaconManager _beaconManager;

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

        _beaconManager = new BeaconManager(this);
        _beaconManager.Nearable += (sender, e) =&gt;
        {
            foreach (var nearable in e.Nearables ?? Enumerable.Empty&lt;Nearable&gt;())
                Console.WriteLine(nearable);
        };

        _beaconManager.Connect(this);
    }

    public void OnServiceReady()
    {
        _beaconManager.StartNearableDiscovery();
    }
}
</code></pre>
<p>Easy enough. Where on iOS we were able to limit scanning by nearable type, that doesn&apos;t seem to be exposed in the Android SDK. In Fact, despite there being a <a href="http://estimote.github.io/Android-SDK/JavaDocs/com/estimote/sdk/cloud/model/NearableType.html"><code>NearableType</code></a> enum in the SDK, that doesn&apos;t even seem to be exposed as a property on a <a href="http://estimote.github.io/Android-SDK/JavaDocs/com/estimote/sdk/Nearable.html"><code>Nearable</code></a> object.</p>
<h1 id="triggers">Triggers</h1>
<p>One of the other nice things about the iOS SDK that is not currently available in the Android SDK is the ability to specify rules and triggers for when you get a callback from a nearable. While it&apos;s not the end of the world to have to compose these things by hand, this makes it trivial to define the scenarios you care about in your apps.</p>
<p>For example, let&apos;s say you attached the <code>Dog</code> sticker to your dog and wanted to detect when the dog rolled over. All you need to do is define an orientation rule for that nearable type and create a trigger based on it:</p>
<pre><code class="language-language-csharp">var triggerManager = new TriggerManager();
    
var dogRollsOverRule = OrientationRule.OrientationEquals(NearableOrientation.HorizontalUpsideDown, NearableType.Dog);
var dogRollsOverTrigger = new Trigger(new [] { dogRollsOverRule }, &quot;dog rolls over&quot;);

triggerManager.ChangedState += (sender, e) =&gt; 
{
    if (!e.Trigger.State)
        return;

    if (e.Trigger.Identifier == dogRollsOverTrigger.Identifier)
        new UIAlertView(null, &quot;dog rolled over&quot;, null, &quot;Ok&quot;, null).Show();
};

triggerManager.StartMonitoringForTrigger(dogRollsOverTrigger);
</code></pre>
<p>In the <code>ChangedState</code> callback, <code>e.Trigger.State</code> indicates whether the trigger is currently active.</p>
<p>In addition to <code>OrientationRule</code> there are several other built-in rules you can use, such as <code>DateRule</code>, <code>ProximityRule</code>, <code>TemperatureRule</code>, and <code>MotionRule</code>. You can also define your own rule classes that create any scenarios you&apos;d like.</p>
<h2 id="composingrules">Composing Rules</h2>
<p>You&apos;re also not limited to a single rule for a trigger, so you can compose multiple rules together to form a more interesting scenario. Let&apos;s say that you attached a sticker to your refrigerator and want to detect when it opens late at night to cut back on late night snacking. With Estimote&apos;s trigger API this is trivial:</p>
<pre><code class="language-language-csharp">var fridgeDoorMovesRule = MotionRule.MotionStateEquals(true, NearableType.Fridge);
var afterMidnightRule = DateRule.HourBetween(0, 5);
var lateNightSnackingTrigger = new Trigger(new Rule[] { fridgeDoorMovesRule, afterMidnightRule }, &quot;fridge door moves after midnight&quot;);

triggerManager.ChangedState += (sender, e) =&gt; 
{
    if (!e.Trigger.State)
        return;

    if (e.Trigger.Identifier == lateNightSnackingTrigger.Identifier)
        new UIAlertView(null, &quot;late night snacking!&quot;, null, &quot;Ok&quot;, null).Show();
};

triggerManager.StartMonitoringForTrigger(lateNightSnackingTrigger);
</code></pre>
<p>Simply compose a <code>DateRule</code> with a <code>MotionRule</code> and you&apos;re done!</p>
<h1 id="summary">Summary</h1>
<p>Obviously this just scratches the surface of what you can do with nearables, but the exciting part to me is how easy it is to build smart, contextual experiences. Estimote is an awesome company as well, so I suspect they will close the SDK gaps between iOS in Android over time to make things easy across the board.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Testing Xamarin Apps: Getting Started with xUnit]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>It&apos;s no secret that I&apos;m a big proponent of testing, and lately I&apos;ve been getting a lot of questions around how to approach getting started and what technologies to use. While I have a good amount of content coming out around this, <a href="https://university.xamarin.com/guestlectures">some already</a></p>]]></description><link>https://gregshackles.com/testing-xamarin-apps-getting-started-with-xunit/</link><guid isPermaLink="false">61ce48a0437e8200017d4130</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Fri, 25 Sep 2015 12:58:25 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>It&apos;s no secret that I&apos;m a big proponent of testing, and lately I&apos;ve been getting a lot of questions around how to approach getting started and what technologies to use. While I have a good amount of content coming out around this, <a href="https://university.xamarin.com/guestlectures">some already announced</a>, some to be announced soon, I thought I would also try to take some time to put together a few posts on the subject as well.</p>
<p>In this post I&apos;m going to focus on setting up unit testing for Xamarin apps using the xUnit framework. If you&apos;ve followed my testing content in the past, you might remember me recommending the usage of NUnitLite a few years back as the framework of choice. At the time that was the best option, but these days xUnit has a far superior cross-platform story (major props to <a href="https://twitter.com/onovotny">Oren Novotny</a> for helping drive that forward!), in addition to just being a more modern framework in general. The biggest downside, at least at the time of writing this, is that there isn&apos;t any sort of integration with Xamarin Studio, but hopefully that story will improve as well.</p>
<h1 id="creatingthetestproject">Creating The Test Project</h1>
<p>To start off, create a portable class library for your tests to live in. Alternatively you could also go with a shared project if you&apos;d prefer, but unless you need it I recommend sticking with a PCL. Using a PCL will enable you to easily run the tests in any xUnit test runner, such as Visual Studio, the command line, iOS, Android, or Windows Phone.</p>
<p>Once that&apos;s created, add the xUnit.net NuGet package:</p>
<p><img src="https://gregshackles.com/content/images/2015/09/testing1.png" alt="NuGet" loading="lazy"></p>
<p>As of the time of this post I recommend installing the pre-release version of xUnit, as pictured here, which brings with it improved Mono support. Similiarly, Xamarin&apos;s Alpha channel currently ships with an updated version of Mono that improves xUnit support. Both of these should hit the stable channels soon so this recommendation will be short-lived, but I wanted to point it out in the meantime.</p>
<p>In addition to the main xUnit package, also go ahead and install the console runner package. If you&apos;d also like to run the tests in Visual Studio, you can add the Visual Studio runner package as well.</p>
<p>With those installed, let&apos;s create some tests:</p>
<pre><code class="language-language-csharp">using System;
using System.Threading.Tasks;
using Xunit;

namespace TestDemo
{
    public class TestsAreGood
    {
        [Fact]
        public void ThisShouldPass()
        {
            Assert.True(true);
        }

        [Fact]
        public async Task ThisShouldFail()
        {
            await Task.Run(() =&gt; { throw new Exception(&quot;boom&quot;); });
        }
    }
}
</code></pre>
<p>Obviously these are pretty trivial, but as you can see xUnit has support for async tests. In fact, it has much better support for async tests than the version of NUnit that ships with Mono/Xamarin Studio, which is another awesome advantage to going with xUnit.</p>
<h1 id="runnerconsole">Runner: Console</h1>
<p>Now that we have tests, let&apos;s start by running them from the console:</p>
<pre><code>&gt; mono packages/xunit.runner.console.2.1.0-rc2-build3176/tools/xunit.console.exe TestDemo/bin/Debug/TestDemo.dll

xUnit.net Console Runner (32-bit .NET 4.0.30319.17020)
  Discovering: TestDemo
  Discovered:  TestDemo
  Starting:    TestDemo
    TestDemo.TestsAreGood.ThisShouldFail [FAIL]
      System.Exception : boom
      Stack Trace:
        &lt;trimmed&gt;
  Finished:    TestDemo
=== TEST EXECUTION SUMMARY ===
   TestDemo  Total: 2, Errors: 0, Failed: 1, Skipped: 0, Time: 0.100s
</code></pre>
<p>As expected, we had one test pass and one fail. I suggest creating a script to allow you to easily and quickly run these tests to lower the friction to running the tests going forward. You could even set up a monitor on the DLL file and automatically re-run your tests each time you compile!</p>
<h1 id="runnerios">Runner: iOS</h1>
<p>The console runner is great and all, but we&apos;re doing mobile development here, so it really only matters if our code works in that environment. Lucky for us the xUnit cross platform story is awesome, so it&apos;s nice and easy to get these tests running there as well.</p>
<p>Start off by creating a new single view iOS project, and then delete the generated storyboard and view controller files. Also make sure go into your <code>Info.plist</code> file and remove the &quot;main interface&quot; references to the storyboard. Next, add a project reference to the main PCL test project from before.</p>
<p>With that set up, add the xUnit.net for Devices NuGet package:</p>
<p><img src="https://gregshackles.com/content/images/2015/09/testing2.png" alt="NuGet" loading="lazy"></p>
<p>That NuGet package will add a new file to your solution named <code>AppDelegate.cs.txt</code>. Go ahead and copy the contents of that file and replace the contents of <code>AppDelegate.cs</code> with it. After that you can go ahead and delete the <code>AppDelegate.cs.txt</code> file if you like.</p>
<p>if you take a look in the code now in <code>AppDelegate.cs</code>, you&apos;ll see some references to a function named <code>AddTestAssembly()</code>. This is what you can use to tell xUnit which assemblies to scan for tests. By default it will include an instruction to scan the current assembly, but in our case that won&apos;t return anything since our tests are in a separate library. If you had been using a shared code project, this default scan would be sufficient.</p>
<p>Replace the existing <code>AddTestAssembly()</code> call with:</p>
<pre><code class="language-language-csharp">AddTestAssembly(typeof(TestsAreGood).Assembly);
</code></pre>
<p>Set the iOS project as the solution&apos;s startup project and run it:</p>
<p><img src="https://gregshackles.com/content/images/2015/09/testing3-1.png" alt="iOS Runner" loading="lazy"></p>
<p>Your tests are now running in iOS without having to change anything! You can run them either in the simulator or on a device to validate that your code truly works across the board.</p>
<h1 id="runnerandroid">Runner: Android</h1>
<p>With iOS out of the way, let&apos;s also get these tests running on Android. The process here is very similar to setting up iOS. Create a new Android project, add a reference to the test library, and add the same xUnit.net for Devices NuGet package that we added to iOS.</p>
<p>Just like with iOS, the package will add a <code>MainActivity.cs.txt</code> file to your solution. Take the contents of that file and overwrite what&apos;s in <code>MainActivity.cs</code>. Update the <code>AddTestAssembly()</code> call in there with the same line as before:</p>
<pre><code class="language-language-csharp">AddTestAssembly(typeof(TestsAreGood).Assembly);
</code></pre>
<p>Set the Android runner as the startup project, fire up your favorite emulator or device, and voil&#xE0;!</p>
<p><img src="https://gregshackles.com/content/images/2015/09/testing4.png" alt loading="lazy"></p>
<h1 id="summary">Summary</h1>
<p>Setting up these runners are just a one-time thing, as they will continue to pick up new tests you add each time you run them. With just a few minutes of effort you can set up an environment where not only can you verify that your code runs properly on the full .NET or Mono frameworks, but also that they run on the device environments that really count here. In future posts I&apos;ll explore some other tips for unit testing your apps, as well as step into other areas like UI testing, Test Cloud, and more.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Create Modern Android Apps with the Design Support Library]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>With the release of Android 5.0, also known as Lollipop, Google introduced its new material design style.</p>
<p>Material Design is a huge step forward for Android apps, bringing with it a total overhaul of theming, as well as a bunch of new UI components you can use in your</p>]]></description><link>https://gregshackles.com/create-modern-android-apps-with-the-design-support-library/</link><guid isPermaLink="false">61ce48a0437e8200017d412d</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Mon, 24 Aug 2015 14:25:43 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>With the release of Android 5.0, also known as Lollipop, Google introduced its new material design style.</p>
<p>Material Design is a huge step forward for Android apps, bringing with it a total overhaul of theming, as well as a bunch of new UI components you can use in your apps. To make things even better, Google also released the Android Design Support Library, which allows you to take advantage of material design in versions of Android going all the way back to Android 2.1.</p>
<p>In this article I&apos;ll walk-through some of the new components available in this library, and show how easy they are to introduce into an app.</p>
<hr>
<p>Read the rest of the article over at <a href="https://visualstudiomagazine.com/articles/2015/08/01/create-modern-android-apps.aspx">Visual Studio Magazine</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Android's ActionBarActivity and the Hardware Back Button]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="http://gregshackles.com/changing-the-android-toolbars-back-arrow-color/">my last post</a> I talked about one of the roadblocks I hit when upgrading to Android&apos;s new <code>ActionBarActivity</code>. That was definitely a major pain, but there&apos;s one other issue I&apos;ve run into so far that I wanted to call attention to as well.</p>]]></description><link>https://gregshackles.com/back-button-gotcha-in-androids-actionbaractivity/</link><guid isPermaLink="false">61ce48a0437e8200017d4124</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sun, 08 Mar 2015 03:21:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="http://gregshackles.com/changing-the-android-toolbars-back-arrow-color/">my last post</a> I talked about one of the roadblocks I hit when upgrading to Android&apos;s new <code>ActionBarActivity</code>. That was definitely a major pain, but there&apos;s one other issue I&apos;ve run into so far that I wanted to call attention to as well. This one didn&apos;t cost us nearly as much time as that last one did, but it was certainly unexpected.</p>
<p>Our apps make use of a single activity and fragments for each separate screen within the app. After updating this activity to extend from <code>ActionBarActivity</code> we noticed that suddenly the hardware back button was causing the host activity to finish, even when there were multiple fragments in the backstack. Prior to this change we could rely on the hardware back button to pop fragments off the stack first, and only finish the activity if there was nothing left in the stack.</p>
<p>I figured this was just a documented change, but a look at Android&apos;s documentation for <a href="http://developer.android.com/reference/android/support/v7/app/ActionBarActivity.html#onBackPressed()"><code>onBackPressed()</code></a> says:</p>
<blockquote>
<p>Take care of popping the fragment back stack or finishing the activity as appropriate.</p>
</blockquote>
<p>This description lines up with the behavior I would have expected, but unfortunately the observed behavior is not the same.</p>
<p><img src="http://i.imgur.com/KlWrMtj.jpg" alt="&quot;appropriate&quot;" loading="lazy"></p>
<p>The fix for this in the host activity is simple enough:</p>
<pre><code class="language-language-csharp">public override void OnBackPressed()
{
    if (FragmentManager.BackStackEntryCount &gt; 0)
        FragmentManager.PopBackStack();
    else 
        base.OnBackPressed();
}
</code></pre>
<p>All in all it&apos;s certainly not the end of the world to add this small amount of code to work around the issue here. I was just surprised by the change in behavior, and wanted to call attention to it in case it helps one of you solve the issue in your apps before they make it out to the Play store.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Changing the Android Toolbar's Back Arrow Color]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As part of updating our apps to use the latest Android support library to bring in some of the nice material design classes in there, we also started switching over to using a <code>Toolbar</code> as our action bar. If you&apos;re just getting started in making the same upgrades</p>]]></description><link>https://gregshackles.com/changing-the-android-toolbars-back-arrow-color/</link><guid isPermaLink="false">61ce48a0437e8200017d4123</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Tue, 03 Mar 2015 03:52:57 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As part of updating our apps to use the latest Android support library to bring in some of the nice material design classes in there, we also started switching over to using a <code>Toolbar</code> as our action bar. If you&apos;re just getting started in making the same upgrades in your app I suggest starting with <a href="http://blog.xamarin.com/android-tips-hello-material-design-v7-appcompat/">this excellent post</a> on Xamarin&apos;s blog that outlines what you need to do.</p>
<p>Getting things migrated was easy enough but we unexpectedly hit some snags in trying to customize the color of the back button shown in the upper left of the toolbar consistently across Android versions. After spending far longer on this than I&apos;d care to admit and countless permutations of styles and settings, I wanted to share what we settled on in hopes of saving someone else that pain. I also want to give <a href="https://twitter.com/sashany1983">my colleague Sasha</a> a hat tip here because when I say that &quot;we&quot; went through some pain here, I mostly mean her.</p>
<h1 id="oursolution">Our Solution</h1>
<p>After some digging we ended up on <a href="http://stackoverflow.com/questions/26788464/how-to-change-color-of-the-back-arrow-in-the-new-material-theme">this Stackoverflow post</a> that offers a variety of potential solutions to the problem. Our initial preference was to keep things contained entirely in the style XML. <a href="http://stackoverflow.com/a/27517878/170333">This answer</a> seemed promising, but despite working in Android 4.x, Lollipop always seemed to completely ignore anything we set. Frustrating.</p>
<p>Feeling defeated, we opted to try the code solution mentioned in <a href="http://stackoverflow.com/a/26837072/170333">this answer</a>. Success! A bit hacky, but hey, it works. #yolo</p>
<p>Translated to Xamarin.Android it looks like this:</p>
<pre><code class="language-language-csharp">var upArrow = Resources.GetDrawable(Resource.Drawable.abc_ic_ab_back_mtrl_am_alpha);

upArrow.SetColorFilter(Resources.GetColor(Resource.Color.actionbartext), PorterDuff.Mode.SrcIn);

SupportActionBar.SetHomeAsUpIndicator(upArrow);
</code></pre>
<p>On a related note, that has to be one of the worst named resources I&apos;ve ever seen.</p>
<h1 id="butwaittheresmore">But Wait, There&apos;s More</h1>
<p>Unfortunately that wasn&apos;t where the pain ended for us. Our apps make use of a <code>DrawerLayout</code>, where on the root view of the app the home indicator in the toolbar is the standard menu icon. As you navigate away from the root view the indicator changes to the back button we just talked about. Our host activity monitors for changes to the fragment backstack and updates this indicator accordingly. Despite having set the color filter earlier, we found that it was being lost and defaulting back to black.</p>
<p>The culprit? Updating the <code>DrawerIndicatorEnabled</code> property on our <code>ActionBarDrawerToggle</code>, which <a href="https://android.googlesource.com/platform/frameworks/support/+/1949ae9aeaadf52ad7bd7bb74ca5419c67ea7f65/v7/appcompat/src/android/support/v7/app/ActionBarDrawerToggle.java#356">resets this drawable to the value set by the theme</a>. Since we&apos;re doing the tinting in code, we just needed to make sure to reset the indicator when showing it. The resulting code boils down to something like this:</p>
<pre><code class="language-language-csharp">FragmentManager.BackStackChanged += (sender, e) =&gt;
{
    if (FragmentManager.BackStackEntryCount == 0)
    {
        _drawerToggle.DrawerIndicatorEnabled = true;
    }
    else
    {
        _drawerToggle.DrawerIndicatorEnabled = false;
        
        SupportActionBar.SetHomeAsUpIndicator(upArrow);
    }
};
</code></pre>
<p>There are undoubtedly ways to solve this more elegantly, but this approach is working well enough for us for the time being. It also passed a run through Test Cloud to try and smoke out any version/device incompatibilities. All that to change the color of a button...Android is fun sometimes.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Write Automated UI Tests for iOS and Android Apps]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Previously in this column, I&apos;ve written about unit testing iOS apps, but what can you do when unit tests just won&apos;t cut it? If you&apos;re a Web developer you&apos;re probably already familiar with libraries like Selenium, which allow you to drive automated</p>]]></description><link>https://gregshackles.com/write-automated-ui-tests-for-ios-and-android-apps/</link><guid isPermaLink="false">61ce48a0437e8200017d4122</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Automation]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Mon, 23 Feb 2015 14:52:02 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Previously in this column, I&apos;ve written about unit testing iOS apps, but what can you do when unit tests just won&apos;t cut it? If you&apos;re a Web developer you&apos;re probably already familiar with libraries like Selenium, which allow you to drive automated testing of your Web app&apos;s front-end.</p>
<p>Xamarin offers a library named Xamarin.UITest that enable the similar possibilities for your iOS and Android apps. In addition to being able to run those tests locally on an emulator or device, you can even push the same tests out to Xamarin&apos;s Test Cloud, allowing you to validate your tests across more than a thousand different devices.</p>
<p>Read the full article over on <a href="http://visualstudiomagazine.com/articles/2015/02/17/automated-unit-tests-ios-android.aspx">Visual Studio Magazine</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Tips For Uploading Apps to Organizations in HockeyApp]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Like many others right now, we&apos;re in the process of migrating our testing infrastructure from TestFlight to HockeyApp before the TestFlight shutdown next week. As we did in the past with Xamarin and HipChat, we also open sourced <a href="https://github.com/fsharp/FAKE/pull/656">the FAKE helper we made</a> for uploading builds to HockeyApp.</p>]]></description><link>https://gregshackles.com/uploading-apps-to-organizations-in-hockeyapp/</link><guid isPermaLink="false">61ce48a0437e8200017d4121</guid><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Automation]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sat, 21 Feb 2015 22:47:41 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Like many others right now, we&apos;re in the process of migrating our testing infrastructure from TestFlight to HockeyApp before the TestFlight shutdown next week. As we did in the past with Xamarin and HipChat, we also open sourced <a href="https://github.com/fsharp/FAKE/pull/656">the FAKE helper we made</a> for uploading builds to HockeyApp.</p>
<p>For example, to upload a build to HockeyApp and then send a notification to a room in HipChat you can do:</p>
<pre><code class="language-language-fsharp">HockeyApp (fun p -&gt;
  {p with 
    ApiToken = Environment.GetEnvironmentVariable(&quot;HockeyAppApiToken&quot;)
    File = ipaOrApkPath
  })
|&gt; fun response -&gt;
    HipChatNotification(fun p -&gt;
      {p with 
          AuthToken = Environment.GetEnvironmentVariable(&quot;HipChatAuthToken&quot;)
          RoomId = Environment.GetEnvironmentVariable(&quot;HipChatNotificationRoom&quot;)
          Message = (&quot;Successfully deployed to HockeyApp: &quot; + response.ConfigUrl)
          Color = &quot;green&quot;
      }) |&gt; ignore
</code></pre>
<p>As part of the transition, we created an organization for the company, and a couple teams within that organization. We then proceeded to run into a few stumbling blocks in getting things working properly, which I wanted to share to hopefully help others avoid the aggravation we went through. It&apos;s also entirely possible that we were just doing something wrong or missing something entirely - if that&apos;s the case, please do let me know!</p>
<h1 id="apitokensandownership">API Tokens and Ownership</h1>
<p>All of our uploads happen through automated CI builds, so the next thing we did was go to create an API token to use. I was a little disappointed to see that API tokens are managed at the user level, rather than the organization. It&apos;s not the end of the world, but it would be nicer if that lived under the organization so that multiple people can manage the same tokens.</p>
<p>The main problem we hit as a result of this is that builds uploaded using this API token would be tied to the user that created the key and not the organization. This makes sense based on the fact that the token is tied to a user and not the organization, but the documentation for uploading a build makes no mention of a way to set the owner for an app. It&apos;s possible to transfer the app to the organization on the website through a series of somewhat clunky steps, but this really wouldn&apos;t scale well for the volume of apps we process in our system.</p>
<p>Thankfully when I raised the question on Twitter earlier today, HockeyApp was nice enough to <a href="https://twitter.com/hockeyapp/status/569227201083797504">respond very quickly</a> with a way to achieve what we needed. The solution is to pass in an <code>owner_id</code> parameter with the upload payload, which can be used to set the owner for the app using its ID. You can get the ID out of the URL when viewing the organization on the site. Here&apos;s what that looks like in cURL syntax:</p>
<pre><code>-F &quot;owner_id=3141592&quot; \
</code></pre>
<p>Hopefully they add this to their documentation soon. We&apos;ll also be publishing an update to the FAKE helper soon that will include the ability to set this ID from your build scripts.</p>
<h1 id="visibilitytousers">Visibility to Users</h1>
<p>Once we got the organization ownership working the next thing we realized was that despite our assumptions, the builds weren&apos;t visible to anyone else on my team, despite the fact that I&apos;d added them to the Owners team. There are a couple ways you can go here. First, HockeyApp does have an endpoint at <a href="http://support.hockeyapp.net/kb/api/api-teams-app-users#add-team-to-app"><code>/api/2/apps/APP_ID/app_teams/ID</code></a> that you can use to assign a team to an app programmatically. This is fine, but what we really wanted was for people in the owners group to automatically get access to everything.</p>
<p>After some digging we came across this checkbox when you&apos;re adding/editing an owner for an organization:</p>
<p><img src="https://gregshackles.com/content/images/2015/02/Screen-Shot-2015-02-21-at-5-36-51-PM.png" alt="User settings" loading="lazy"></p>
<p>Somehow we&apos;d overlooked that option when initially setting things up. Personally I think this should be the default behavior, since to me an &quot;owner&quot; should be someone with full admin rights across the organization.</p>
<p>Overall things seem to work pretty well in HockeyApp but the user experience definitely leaves quite a bit to be desired, especially given that it&apos;s a paid product. Hopefully we&apos;ll see some nice updates coming to HockeyApp in the coming months now that they&apos;re part of Microsoft.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Presenters in MvvmCross: Navigating Android with Fragments]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In my last couple posts on this subject I&apos;ve mentioned using fragments on Android for navigation. By default MvvmCross will use activities on Android, but as I hope you&apos;ve learned by now, you can use presenters to customize this sort of thing as much as you&</p>]]></description><link>https://gregshackles.com/presenters-in-mvvmcross-navigating-android-with-fragments/</link><guid isPermaLink="false">61ce48a0437e8200017d411f</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[MvvmCross]]></category><category><![CDATA[Presenters]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Fri, 16 Jan 2015 12:44:08 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In my last couple posts on this subject I&apos;ve mentioned using fragments on Android for navigation. By default MvvmCross will use activities on Android, but as I hope you&apos;ve learned by now, you can use presenters to customize this sort of thing as much as you&apos;d like. I&apos;ve found it very difficult (or impossible) to properly achieve the types of fine-grained navigation control I want in my apps by using activities for all my views, which is one of several reasons I&apos;ve switched to using fragments for everything.</p>
<p>Ultimately what this ends up looking like is somewhat similar to a Single Page Application on the web: a single container activity with a fragment stack containing the actual views of the app. You can mix and match here if you&apos;d like too, as I&apos;ll show later in my sample presenter.</p>
<h1 id="viewsandviewmodels">Views and View Models</h1>
<p>First let&apos;s quickly set up the basic app essentials here, starting with the view models:</p>
<pre><code class="language-language-csharp">using Cirrious.MvvmCross.ViewModels;

namespace PresenterDemo.Core.ViewModels
{
    public class FirstViewModel : MvxViewModel
    {
		public IMvxCommand NavigateCommand
		{
			get { return new MvxCommand(() =&gt; ShowViewModel&lt;SecondViewModel&gt; ()); }
		}
    }

    public class SecondViewModel : MvxViewModel
	{
	}
}
</code></pre>
<p>Nothing crazy here, just a view model that can navigate to a second view model. Next we&apos;ll define the view markup, starting with <code>FirstView.axml</code>:</p>
<pre><code class="language-language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:local=&quot;http://schemas.android.com/apk/res-auto&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;&gt;
    &lt;Button
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:text=&quot;Navigate&quot;
        local:MvxBind=&quot;Click NavigateCommand&quot; /&gt;
&lt;/LinearLayout&gt;
</code></pre>
<p>and <code>SecondView.axml</code>:</p>
<pre><code class="language-language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:local=&quot;http://schemas.android.com/apk/res-auto&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;&gt;
    &lt;TextView
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:text=&quot;Second view&quot; /&gt;
&lt;/LinearLayout&gt;
</code></pre>
<p>As I mentioned earlier, the app will use a single activity that hosts the fragments, so we&apos;ll also define a layout named <code>Container.axml</code>:</p>
<pre><code class="language-language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:local=&quot;http://schemas.android.com/apk/res-auto&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;&gt;
    &lt;FrameLayout
        android:id=&quot;@+id/contentFrame&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot; /&gt;
&lt;/LinearLayout&gt;
</code></pre>
<p>Finally we need our fragments:</p>
<pre><code class="language-language-csharp">using Android.OS;
using Android.Views;
using Cirrious.MvvmCross.Binding.Droid.BindingContext;
using Cirrious.MvvmCross.Droid.FullFragging.Fragments;

namespace PresenterDemo.Droid
{
	public class InitialFragment : MvxFragment
	{
		public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
		{
			base.OnCreateView(inflater, container, savedInstanceState);

			return this.BindingInflate(Resource.Layout.FirstView, null);
		}
	}

	public class SecondView : MvxFragment
	{
		public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
		{
			base.OnCreateView(inflater, container, savedInstanceState);

			return this.BindingInflate(Resource.Layout.SecondView, null);
		}
	}
}
</code></pre>
<p>I&apos;ll get back to the activity itself a little later.</p>
<h1 id="fragmentlookup">Fragment Lookup</h1>
<p>As with most things there are an endless number of ways you can implement this sort of thing, but in this example we&apos;re going to create a class that scans the assembly for fragment views and create a mapping that can be used to match them up with view models by name. This will follow the standard convention of matching a <code>FooViewModel</code> view model with a view named <code>FooView</code>.</p>
<pre><code class="language-language-csharp">using System;
using System.Collections.Generic;
using System.Linq;
using Cirrious.CrossCore.IoC;
using Cirrious.MvvmCross.Droid.FullFragging.Fragments;

namespace PresenterDemo.Droid
{
	public interface IFragmentTypeLookup
	{
		bool TryGetFragmentType(Type viewModelType, out Type fragmentType);
	}

	public class FragmentTypeLookup : IFragmentTypeLookup
	{
		private readonly IDictionary&lt;string, Type&gt; _fragmentLookup = new Dictionary&lt;string, Type&gt;(); 

		public FragmentTypeLookup()
		{
			_fragmentLookup = 
				(from type in GetType().Assembly.ExceptionSafeGetTypes ()
			     where !type.IsAbstract 
					&amp;&amp; !type.IsInterface 
					&amp;&amp; typeof(MvxFragment).IsAssignableFrom(type)
					&amp;&amp; type.Name.EndsWith(&quot;View&quot;)
			     select type).ToDictionary(getStrippedName);
		}

		public bool TryGetFragmentType(Type viewModelType, out Type fragmentType)
		{
			var strippedName = getStrippedName(viewModelType);

			if (!_fragmentLookup.ContainsKey(strippedName))
			{
				fragmentType = null;

				return false;
			}

			fragmentType = _fragmentLookup[strippedName];

			return true;
		}

		private string getStrippedName(Type type)
		{
			return type.Name
					   .TrimEnd(&quot;View&quot;.ToCharArray())
					   .TrimEnd(&quot;ViewModel&quot;.ToCharArray());
		}
	}
}
</code></pre>
<h1 id="thepresenter">The Presenter</h1>
<p>With that mapping implemented, now we can actually work on the presenter itself. This implementation will keep things simple, but you could easily extend it with fancier navigation patterns like the ones shown in previous posts here. Let&apos;s start with the basic outline for the class:</p>
<pre><code class="language-language-csharp">using System;
using Android.App;
using Cirrious.MvvmCross.Droid.FullFragging.Fragments;
using Cirrious.MvvmCross.Droid.Views;
using Cirrious.MvvmCross.ViewModels;

namespace PresenterDemo.Droid
{
	public class DroidPresenter : MvxAndroidViewPresenter
	{
		private readonly IMvxViewModelLoader _viewModelLoader;
		private readonly IFragmentTypeLookup _fragmentTypeLookup;
		private FragmentManager _fragmentManager;

		public DroidPresenter(IMvxViewModelLoader viewModelLoader, IFragmentTypeLookup fragmentTypeLookup)
		{
			_fragmentTypeLookup = fragmentTypeLookup;
			_viewModelLoader = viewModelLoader;
		}
	}
}
</code></pre>
<p>The presenter takes in the fragment mapping and a view model loader as dependencies, which can be used later during navigation to inflate the proper fragments.</p>
<p>Now, this next part is the one thing here that feels somewhat dirty, but its scope is pretty limited. Since the container activity is what is going to be started initially, we&apos;ll make it so that activity has some knowledge of the presenter, and registers its fragment manager and an initial fragment to show with the presenter:</p>
<pre><code class="language-language-csharp">public void RegisterFragmentManager(FragmentManager fragmentManager, MvxFragment initialFragment)
{
	_fragmentManager = fragmentManager;

	showFragment(initialFragment, false);
}
</code></pre>
<p>This isn&apos;t quite as clean of a separation as you get on iOS, but it&apos;s not bad. Next we&apos;ll handle when a new view model request comes in:</p>
<pre><code class="language-language-csharp">public override void Show(MvxViewModelRequest request)
{
	Type fragmentType;
	if (_fragmentManager == null || !_fragmentTypeLookup.TryGetFragmentType(request.ViewModelType, out fragmentType))
	{
		base.Show(request);

		return;
	}
		
	var fragment = (MvxFragment)Activator.CreateInstance(fragmentType);
	fragment.ViewModel = _viewModelLoader.LoadViewModel(request, null);

	showFragment(fragment, true);
}
</code></pre>
<p>The main thing to notice here is that if no corresponding fragment is found in the map, we fall back to the base presenter&apos;s implementation. This means that if a request comes in for <code>ThirdViewModel</code>, it will actually go look for an activity named <code>ThirdView</code>, since it won&apos;t match anything in the fragment type map. This allows you to switch between activities and fragments if you wish.</p>
<p>Both of these last two methods call a private method to actually show the fragment:</p>
<pre><code class="language-language-csharp">private void showFragment(MvxFragment fragment, bool addToBackStack)
{
	var transaction = _fragmentManager.BeginTransaction();

	if (addToBackStack)
		transaction.AddToBackStack(fragment.GetType().Name);

	transaction
		.Replace(Resource.Id.contentFrame, fragment)
		.Commit();
}
</code></pre>
<p>For the initial fragment we don&apos;t want to add it to the backstack, because then you&apos;d be able to hit back on the initial view and see an empty screen, rather than back out of the app as expected. This is also where you could add things like transition animations if you wanted.</p>
<p>Finally, we need to handle when Close requests come in:</p>
<pre><code class="language-language-csharp">public override void Close(IMvxViewModel viewModel)
{
	var currentFragment = _fragmentManager.FindFragmentById(Resource.Id.contentFrame) as MvxFragment;
	if (currentFragment != null &amp;&amp; currentFragment.ViewModel == viewModel)
	{
		_fragmentManager.PopBackStackImmediate();

		return;
	}

	base.Close(viewModel);
}
</code></pre>
<p>Again, this implementation allows for mixing fragments and activities. If the request comes in from the current fragment it will be popped off the stack, but if not it will defer to the base implementation to close the view model.</p>
<h1 id="wiringitup">Wiring It Up</h1>
<p>Now all that&apos;s left is to wire up our dependencies and connect the activity to the presenter:</p>
<pre><code class="language-language-csharp">using Android.Content;
using Cirrious.CrossCore;
using Cirrious.MvvmCross.Droid.Platform;
using Cirrious.MvvmCross.Droid.Views;
using Cirrious.MvvmCross.ViewModels;

namespace PresenterDemo.Droid
{
    public class Setup : MvxAndroidSetup
    {
        public Setup(Context applicationContext) : base(applicationContext)
        {
        }

        protected override IMvxApplication CreateApp()
        {
            return new Core.App();
        }

		protected override IMvxAndroidViewPresenter CreateViewPresenter()
		{
			var presenter = Mvx.IocConstruct&lt;DroidPresenter&gt;();

			Mvx.RegisterSingleton&lt;IMvxAndroidViewPresenter&gt;(presenter);

			return presenter;
		}
		
		protected override void InitializeIoC()
		{
			base.InitializeIoC();

			Mvx.ConstructAndRegisterSingleton&lt;IFragmentTypeLookup, FragmentTypeLookup&gt;();
		}
    }
}
</code></pre>
<p>With that in place we can create our container activity and connect the presenter:</p>
<pre><code class="language-language-csharp">using Android.App;
using Android.OS;
using Cirrious.CrossCore;
using Cirrious.MvvmCross.Droid.Views;

namespace PresenterDemo.Droid.Views
{
	[Activity(Label = &quot;Presenter Demo&quot;, 
			  MainLauncher = true,
		      Icon = &quot;@drawable/icon&quot;)]
    public class FirstView : MvxActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            SetContentView(Resource.Layout.Container);

			var presenter = (DroidPresenter)Mvx.Resolve&lt;IMvxAndroidViewPresenter&gt;();
			var initialFragment = new InitialFragment { ViewModel = ViewModel };

			presenter.RegisterFragmentManager(FragmentManager, initialFragment);
        }
    }
}
</code></pre>
<p>In this example we simply pass the view model from the activity into the first fragment, but you could customize this as necessary of course.</p>
<p>That&apos;s all you need to set up basic fragment-based navigation in your Android apps. I highly recommend using fragments when possible, both for the flexibility around navigation and also just for the ability for reuse in different layout configurations. There are a number of different approaches to fragment presenters out there, but I wanted to share one approach I&apos;ve found that has worked very well in my apps and has given me a lot of flexibility.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Presenters in MvvmCross: Controlling the Back Stack]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="http://gregshackles.com/presenters-in-mvvmcross-using-presentation-values/">my last presenter post</a> I showed how you can use presentation hints to tell the presenter to clear the view stack prior to showing the next view. That is probably the most common custom navigation pattern I&apos;ve seen used in MvvmCross apps, but I also wanted to</p>]]></description><link>https://gregshackles.com/presenters-in-mvvmcross-manipulating-the-back-stack/</link><guid isPermaLink="false">61ce48a0437e8200017d411e</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[MvvmCross]]></category><category><![CDATA[Presenters]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sun, 11 Jan 2015 19:45:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In <a href="http://gregshackles.com/presenters-in-mvvmcross-using-presentation-values/">my last presenter post</a> I showed how you can use presentation hints to tell the presenter to clear the view stack prior to showing the next view. That is probably the most common custom navigation pattern I&apos;ve seen used in MvvmCross apps, but I also wanted to note another similar pattern I&apos;ve used as well.</p>
<p>When I&apos;m mapping out the navigation paths through my apps, I try to be very conscious of the state of the back stack at any given time. Often navigation through an app is pretty linear which makes this a non-issue, but it&apos;s also easy to come across scenarios that are more problematic. Using our apps as an example, once you have a basket in progress the app will show you a persistent shortcut in the top bar that will bring you back to it from anywhere in the app. Once you do so, you end up on a screen that lets you perform some different actions, one of which is the option to return to the menu to add more items. During the initial flow through the app this would simply mean going back one screen in the stack, but if the user just jumped here from somewhere else, that view doesn&apos;t exist on the stack.</p>
<p>To solve this we introduced the presentation concept of navigating &quot;back or in place&quot;. This tells the presenter to start by checking the back stack for the existence of a view of the same type we&apos;re navigating to. If found, it rewinds the stack back to that view. If not found, it pops the current view, then creates and navigates to the destination view. This allows us to map out any paths we want through the app without needing to sorry about showing the other views first.</p>
<p>Navigating with this mode is handled the same way shown in the last post:</p>
<pre><code class="language-language-csharp">var presentationBundle = new MvxBundle(new Dictionary&lt;string, string&gt; { { &quot;NavigationMode&quot;, &quot;BackOrInPlace&quot; } });

ShowViewModel&lt;MyViewModelType&gt;(presentationBundle: presentationBundle);
</code></pre>
<h1 id="ios">iOS</h1>
<p>Here&apos;s what the implementation on iOS might look like:</p>
<pre><code class="language-language-csharp">public override void Show(MvxViewModelRequest request)  
{
    if (request.PresentationValues != null)
    {
        if (request.PresentationValues.ContainsKey(&quot;NavigationMode&quot;) &amp;&amp; request.PresentationValues[&quot;NavigationMode&quot;] == &quot;BackOrInPlace&quot;)
        {
        	var nextViewController = (UIViewController)_viewCreator.Value.CreateView(request);
			var existingViewController = MasterNavigationController.ViewControllers.FirstOrDefault(vc =&gt; vc.GetType() == nextViewController.GetType() &amp;&amp; vc != CurrentTopViewController);

			if (existingViewController != null)
			{
				MasterNavigationController.PopToViewController(existingViewController, true);
			}
			else
			{
				var transition = new CATransition
				{
					Duration = 0.3,
					Type = CAAnimation.TransitionPush,
					Subtype = CAAnimation.TransitionFade
				};

				MasterNavigationController.PopViewControllerAnimated(false);
				MasterNavigationController.View.Layer.AddAnimation (transition, null);
				MasterNavigationController.PushViewController(nextViewController, false);
			}

			return;
		}
    }

    base.Show(request);
}
</code></pre>
<p>In cases where the target view isn&apos;t already in the stack, this will provide a little fade transition into the new view, rather than making it look like a normal navigation push. I find this to be a nice visual cue to the user on what happened, and avoid the expectation that the previous view is still there on the back stack.</p>
<h1 id="android">Android</h1>
<p>The implementation looks pretty similar on Android, except that again we&apos;re using fragments to give us finer control over the stack:</p>
<pre><code class="language-language-csharp">public override void Show(MvxViewModelRequest request)  
{
    if (vmRequest.PresentationValues != null)
    {
        if (request.PresentationValues.ContainsKey(&quot;NavigationMode&quot;) &amp;&amp; request.PresentationValues[&quot;NavigationMode&quot;] == &quot;BackOrInPlace&quot;)
        {
        	var hasFragmentTypeInStack = 
                Enumerable.Range(0, _fragmentManager.BackStackEntryCount - 1)
                          .Reverse()
                          .Any(index =&gt; _fragmentManager.GetBackStackEntryAt(index).Name == fragmentType.Name);

            if (hasFragmentTypeInStack)
            {
                while (CurrentFragment.GetType() != fragmentType)
                    _fragmentManager.PopBackStackImmediate();

                return;
            }

            _fragmentManager.PopBackStackImmediate();
		}
    }

    // ...
}
</code></pre>
<p>This is just one example of what you might want to do with the back stack in your apps. I encourage you to think about the state of the stack as you build up navigation flows through your apps, in order to provide the most sensible experience possible for users.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Presenters in MvvmCross: Using Presentation Values]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As shown in my last post, a <code>MvxViewModelRequest</code> contains a dictionary named <code>PresentationValues</code> that can be very useful in passing around data that your presenter might find useful. Let&apos;s say you that in your view model you know that when you request to show a view model you</p>]]></description><link>https://gregshackles.com/presenters-in-mvvmcross-using-presentation-values/</link><guid isPermaLink="false">61ce48a0437e8200017d411d</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[MvvmCross]]></category><category><![CDATA[Presenters]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sat, 03 Jan 2015 18:52:57 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As shown in my last post, a <code>MvxViewModelRequest</code> contains a dictionary named <code>PresentationValues</code> that can be very useful in passing around data that your presenter might find useful. Let&apos;s say you that in your view model you know that when you request to show a view model you know that you want to clear the app&apos;s back stack before showing it, such as after a login operation so that the login screen is no longer in the stack.</p>
<p><a href="https://github.com/MvvmCross/MvvmCross/blob/3.2/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNavigatingObject.cs#L39-L120">All overloads of <code>ShowViewModel()</code></a> in MvvmCross contain an optional <code>IMvxBundle</code> parameter named <code>presentationBundle</code>. It&apos;s easy to create a bundle from a dictionary and then pass that into the show request:</p>
<pre><code class="language-language-csharp">var presentationBundle = new MvxBundle(new Dictionary&lt;string, string&gt; { { &quot;NavigationMode&quot;, &quot;ClearStack&quot; } });

ShowViewModel&lt;MyViewModelType&gt;(presentationBundle: presentationBundle);
</code></pre>
<p>When your platform&apos;s presenter gets that request, the values you passed in with the presentation bundle will be available in the <code>PresentationValues</code> property described earlier. With that in place, let&apos;s implement the clear operation on both iOS and Android.</p>
<h2 id="ios">iOS</h2>
<p>For this example I&apos;m going to assume the presenter inherits from the standard <code>MvxTouchViewPresenter</code> class provided in MvvmCross, which manages a <code>UINavigationController</code> stored in a property named <code>MasterNavigationController</code>. All our presenter needs to do is detect the hint we sent in the request and react accordingly:</p>
<pre><code class="language-language-csharp">public override void Show(MvxViewModelRequest request)
{
	if (request.PresentationValues != null)
	{
		if (request.PresentationValues.ContainsKey(&quot;NavigationMode&quot;) &amp;&amp; request.PresentationValues[&quot;NavigationMode&quot;] == &quot;ClearStack&quot;)
			MasterNavigationController.PopToRootViewController(false);
	}

	base.Show(request);
}
</code></pre>
<p>I&apos;m using magic strings here to keep things simple, but you could use constants/enums/whatever works for your application if you want to formalize things a bit more. The <code>false</code> sent in to <code>PopToRootViewController()</code> says not to animate so that it happens immediately. You can easily get yourself into trouble with <code>UINavigationController</code> if you have competing navigations, so definitely be careful there. I&apos;ll dig into that topic further in a future post.</p>
<h2 id="android">Android</h2>
<p>Now let&apos;s look at Android. I&apos;m going to assume a presenter that&apos;s using fragments for all views and has a <code>FragmentManager</code> field it uses to manage them. In a future post I&apos;ll talk in more detail on how to implement this model in Android, but that&apos;s a bit off topic here. With that aside, the Android implementation ends up looking pretty similar to iOS:</p>
<pre><code class="language-language-csharp">public override void Show(MvxViewModelRequest request)
{
    if (vmRequest.PresentationValues != null)
    {
        if (request.PresentationValues.ContainsKey(&quot;NavigationMode&quot;) &amp;&amp; request.PresentationValues[&quot;NavigationMode&quot;] == &quot;ClearStack&quot;)
            _fragmentManager.PopBackStackImmediate(null, PopBackStackFlags.Inclusive);
    }

    // ...
}
</code></pre>
<p>This is just one thing you can do with presentation values, so it&apos;s really up to you and what makes sense in your apps. If you have some knowledge in your view models that are of use to the presenter during a request, these values provide an easy way to pass that knowledge along with it.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Driving Xamarin's Android Player from the Command Line]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As part of our effort to <a href="http://gregshackles.com/generating-app-screenshots-using-xamarin-uitest/">automate taking screenshots</a>, we also need the ability to spin up Android emulators via the command line. This all needs to run headless, so it&apos;s necessary to be able to spin up Android emulators from the command line. A quick look at</p>]]></description><link>https://gregshackles.com/driving-xamarins-android-player-from-the-command-line/</link><guid isPermaLink="false">61ce48a0437e8200017d411c</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[Automation]]></category><category><![CDATA[F#]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Wed, 31 Dec 2014 17:26:41 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As part of our effort to <a href="http://gregshackles.com/generating-app-screenshots-using-xamarin-uitest/">automate taking screenshots</a>, we also need the ability to spin up Android emulators via the command line. This all needs to run headless, so it&apos;s necessary to be able to spin up Android emulators from the command line. A quick look at my <code>ps</code> output showed this to be even simpler a task than I&apos;d anticipated.</p>
<p>To launch a new instance of the Android Player from the command line, all you need to do is run:</p>
<pre><code>&quot;/Applications/Xamarin Android Player.app/Contents/Helpers/Xamarin Android Player.app/Contents/MacOS/Xamarin Android Player&quot; --name &quot;Nexus 5 (KitKat)&quot;
</code></pre>
<p>You can substitute the name there for whichever image you want to spin up. Once it finishes launching it&apos;ll be in a locked state. From the command line you can unlock it by using the <code>adb</code> command:</p>
<pre><code>adb shell input keyevent 82
</code></pre>
<p>Here&apos;s a little F# script I put together to run through this sequence. If it finds any Android Player processes running, it assumes one is already running and skips that step. If you have the main Xamarin Android app running, even without having started any emulators from within it, this check will treat that as if an emulator is running. If none are found, it launches one and waits for 30 seconds before trying to unlock. Crude, but it does the job for now.</p>
<pre><code class="language-language-fsharp">let startAndroidEmulator = fun (emulatorName:string) -&gt;
    let xamarinPlayerPath = &quot;/Applications/Xamarin Android Player.app/Contents/Helpers/Xamarin Android Player.app/Contents/MacOS/Xamarin Android Player&quot;
    let exec = fun file args -&gt;
        let info = new ProcessStartInfo()
        info.FileName &lt;- file
        info.Arguments &lt;- args

        let proc = new Process()
        proc.StartInfo &lt;- info
        proc.Start() |&gt; ignore

    if Process.GetProcessesByName(&quot;Xamarin Android&quot;).Length = 0 then
        exec xamarinPlayerPath (String.Format(&quot;--name \&quot;{0}\&quot;&quot;, emulatorName))

        Async.Sleep(30 * 1000) |&gt; Async.RunSynchronously

    exec &quot;adb&quot; &quot;shell input keyevent 82&quot;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[NYC Code Camp 8: Mobile Apps]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The next edition of the NYC Code Camp is coming up this weekend, and I have pushed out companion apps for iOS, Android, and Windows Phone that are all available now.</p>
<p>I&#x2019;m pretty pressed for time right now so I&#x2019;ll keep this short and sweet. You</p>]]></description><link>https://gregshackles.com/nyc-code-camp-8-mobile-apps/</link><guid isPermaLink="false">61ce48a0437e8200017d4113</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[Windows Phone]]></category><category><![CDATA[iOS]]></category><category><![CDATA[MvvmCross]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Thu, 12 Sep 2013 13:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The next edition of the NYC Code Camp is coming up this weekend, and I have pushed out companion apps for iOS, Android, and Windows Phone that are all available now.</p>
<p>I&#x2019;m pretty pressed for time right now so I&#x2019;ll keep this short and sweet. You can find the apps by searching the appropriate app store, or you can use these links:</p>
<ul>
<li><a href="https://itunes.apple.com/us/app/nyc-code-camp-8/id691712340">iOS</a></li>
<li><a href="https://play.google.com/store/apps/details?id=com.gregshackles.nyccodecamp8">Android</a></li>
<li><a href="http://www.windowsphone.com/en-us/store/app/nyc-code-camp-8/8ca0adbf-7f9c-402a-899c-688c1a586f81">Windows Phone</a></li>
</ul>
<p>If you&#x2019;re interested, the source for all three apps is also <a href="https://github.com/gshackles/nyccodecamp8">available on GitHub</a>. I will be giving a talk at the camp (at 9:15 AM, so get there bright and early!) on MVVM, and will be going over how I built these apps.</p>
<p>Enjoy!</p>
<p><img src="https://gregshackles.com/content/images/2014/12/ss1.jpeg" alt="Screenshot 1" loading="lazy"></p>
<p><img src="https://gregshackles.com/content/images/2014/12/ss2.jpeg" alt="Screenshot 2" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Using SignalR in MonoTouch and Mono for Android Apps]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you haven&#x2019;t checked out <a href="http://signalr.net/">SignalR</a> yet, what are you waiting for? SignalR is a .NET library that makes it really easy to build realtime applications. The server can be hosted inside a web application, or even in a simple console app. On the client side, you can</p>]]></description><link>https://gregshackles.com/using-signalr-in-monotouch-and-mono-for-android-apps/</link><guid isPermaLink="false">61ce48a0437e8200017d410e</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[iOS]]></category><category><![CDATA[SignalR]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sat, 28 Jul 2012 13:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you haven&#x2019;t checked out <a href="http://signalr.net/">SignalR</a> yet, what are you waiting for? SignalR is a .NET library that makes it really easy to build realtime applications. The server can be hosted inside a web application, or even in a simple console app. On the client side, you can access the server from the browser through JavaScript, a console application, or even from mobile apps. Naturally my first instinct was to try and get a SignalR client working that can be used from MonoTouch and Mono for Android applications.</p>
<p><strong>UPDATE 4/30/2013: Please see this more recent post for more up to date information: <a href="https://gregshackles.com/updates-on-my-signalr-fork-and-xamarin-support/">Updates On My SignalR Fork and Xamarin Support</a></strong></p>
<h2 id="buildingtheclient">Building the Client</h2>
<p>I&#x2019;d be lying if I said it took a ton of effort to get things working under Xamarin&#x2019;s tools. In fact, it turned out to be a great case study in the power of the Xamarin platform. Since MonoTouch and Mono for Android expose a profile very similar to that of Windows Phone, I was able to use the Windows Phone client project as a starting point. By adding in some conditional compilation symbols in many of the same places Windows Phone had them, I quickly had a set of projects that compiled for MonoTouch and Mono for Android.</p>
<p>The one tricky part with iOS is that features of .NET that rely on JIT compilations will not work on a device, despite the fact that they will work in the simulator. Because of this, I added a handful of workarounds to the MonoTouch build to help work around these limitations. This included some usages of ConcurrentDictionary and some Json.NET features that relied on JIT. This was not necessary for the Android build, since Android allows for JIT compilation.</p>
<p>Besides the JIT workarounds, that&#x2019;s really all it took to get the clients working. Think about that for a second: that means I was able to reuse all of the existing SignalR client code, and leverage it on entirely new platforms! If that&#x2019;s not a great example of the power of using C# across all platforms, I&#x2019;m not sure what is.</p>
<p>You can find my <a href="https://github.com/gshackles/SignalR">fork of SignalR on GitHub</a>.</p>
<h2 id="sampleapps">Sample Apps</h2>
<p>Of course, a client library is not useful without apps that use it, so I went ahead and added a simple example app for both MonoTouch and Mono for Android to verify that everything is working as expected. You can find both of these in the samples folder in the repository. To keep things simple, both of these samples make use of the SignalR.Hosting.Self.Samples sample that comes as part of SignalR. This is a console application that listens on port 8081 for incoming connections. Make sure you fire that app up before running the samples to make sure things work correctly. Depending on how your network is set up, you may also want to update the IP addresses used by the samples to point to the correct place.</p>
<h3 id="ios">iOS</h3>
<p>To simplify the UI creation, this sample also makes use of the MonoTouch.Dialog library. All of the work happens in the AppDelegate class in the app:</p>
<pre><code class="language-language-csharp">using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.Dialog;
 
namespace SignalR.Client.MonoTouch.Sample
{
	[Register (&quot;AppDelegate&quot;)]
	public partial class AppDelegate : UIApplicationDelegate
	{
		UIWindow window;
 
		public override bool FinishedLaunching(UIApplication app, NSDictionary options)
		{
			window = new UIWindow (UIScreen.MainScreen.Bounds);
 
			var message = new EntryElement(&quot;Message&quot;, &quot;Type your message here&quot;, &quot;&quot;);
			var sendMessage = new StyledStringElement(&quot;Send Message&quot;)
			{
				Alignment = UITextAlignment.Center,
				BackgroundColor = UIColor.Green
			};
			var receivedMessages = new Section();
			var root = new RootElement(&quot;&quot;) 
			{
				new Section() { message, sendMessage },
				receivedMessages
			};
 
			var connection = new Connection(&quot;http://localhost:8081/echo&quot;);
 
			sendMessage.Tapped += delegate 
			{
				if (!string.IsNullOrWhiteSpace(message.Value) &amp;&amp; connection.State == ConnectionState.Connected)
				{
					connection.Send(&quot;iOS: &quot; + message.Value);
 
					message.Value = &quot;&quot;;
					message.ResignFirstResponder(true);
				}
			};
 
			connection.Received += data =&gt;
			{
				InvokeOnMainThread(() =&gt;
					receivedMessages.Add(new StringElement(data)));
			};
				
 
			connection.Start().ContinueWith(task =&gt;
                connection.Send(&quot;iOS: Connected&quot;));
 
			var viewController = new DialogViewController(root);
			window.RootViewController = viewController;
 
			window.MakeKeyAndVisible ();
			
			return true;
		}
	}
}
</code></pre>
<p>When the app starts up it will create a connection to the server, broadcasting a message saying it has connected once the connection is open. The use of SignalR here is extremely simple. To broadcast a message to all clients, the Send() method on the connection is used. Whenever a message is broadcast, the Received event is fired, letting us know a new message has arrived. It&#x2019;s possible to send more complicated messages, but in this case we just send and receive simple strings.</p>
<p><img src="https://gregshackles.com/content/images/2014/12/SignalR-sample-iOS.png" alt="iOS screenshot" loading="lazy"></p>
<h3 id="android">Android</h3>
<p>For the layout, all the app needs is a text field, button, and list of messages received from the server:</p>
<pre><code class="language-langauge-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;&gt;
    &lt;EditText
        android:layout_width=&quot;fill_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:id=&quot;@+id/Message&quot; /&gt;
    &lt;Button
        android:id=&quot;@+id/SendMessage&quot;
        android:layout_width=&quot;fill_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:text=&quot;Send Message&quot; /&gt;
    &lt;ListView
        android:minWidth=&quot;25px&quot;
        android:minHeight=&quot;25px&quot;
        android:layout_width=&quot;fill_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:id=&quot;@+id/Messages&quot; /&gt;
&lt;/LinearLayout&gt;
</code></pre>
<p>With that in place, the DemoActivity class takes care of the rest of the work:</p>
<pre><code class="language-language-csharp">using System.Collections.Generic;
using Android.App;
using Android.OS;
using Android.Widget;
 
namespace SignalR.Client.MonoDroid.Sample
{
    [Activity(Label = &quot;SignalR.Client.MonoDroid.Sample&quot;, MainLauncher = true, Icon = &quot;@drawable/icon&quot;)]
    public class DemoActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
 
            SetContentView(Resource.Layout.Main);
 
            var messageListAdapter = new ArrayAdapter&lt;string&gt;(this, Android.Resource.Layout.SimpleListItem1, new List&lt;string&gt;());
            var messageList = FindViewById&lt;ListView&gt;(Resource.Id.Messages);
            messageList.Adapter = messageListAdapter;
 
            var connection = new Connection(&quot;http://10.0.2.2:8081/echo&quot;);
            connection.Received += data =&gt; 
                RunOnUiThread(() =&gt; messageListAdapter.Add(data));
 
            var sendMessage = FindViewById&lt;Button&gt;(Resource.Id.SendMessage);
            var message = FindViewById&lt;TextView&gt;(Resource.Id.Message);
 
            sendMessage.Click += delegate
            {
                if (!string.IsNullOrWhiteSpace(message.Text) &amp;&amp; connection.State == ConnectionState.Connected)
                {
                    connection.Send(&quot;Android: &quot; + message.Text);
 
                    RunOnUiThread(() =&gt; message.Text = &quot;&quot;);
                }
            };
 
            connection.Start().ContinueWith(task =&gt; connection.Send(&quot;Android: connected&quot;));
        }
    }
}
</code></pre>
<p>Outside of the Android-specific pieces, the code here is almost identical to that of the MonoTouch app, using the same Send() method and Received event on the connection.</p>
<p><img src="https://gregshackles.com/content/images/2014/12/SignalR-sample-Android.png" alt="Android screenshot" loading="lazy"></p>
<h2 id="summary">Summary</h2>
<p>My goal for my SignalR fork is to keep it up to date with any point releases from the main SignalR project. It tends to be a fast moving project so I won&#x2019;t pretend to be able to keep up with the master branch all the time, but whenever there&#x2019;s an actual new version I will try to keep my fork in line with that. As of right now, my fork is on SignalR version 0.6. SignalR has a ton of power and potential, so I hope some of you find it useful to be able to create clients in MonoTouch and Mono for Android apps!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[C# To Go: Version 1.2 Released]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Version 1.2 of C# To Go is now live in the <a href="https://market.android.com/details?id=com.gregshackles.csharptogo">Android Market</a>. I also submitted the update to <a href="http://www.amazon.com/gp/product/B005GG15X4">Amazon&#x2019;s Android marketplace</a> for approval, with any luck that will go through soon as well.</p>
<p>This is a small release of C# To Go, but does come with</p>]]></description><link>https://gregshackles.com/c-to-go-version-1-2-released-2/</link><guid isPermaLink="false">61ce48a0437e8200017d410d</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Sat, 31 Dec 2011 14:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Version 1.2 of C# To Go is now live in the <a href="https://market.android.com/details?id=com.gregshackles.csharptogo">Android Market</a>. I also submitted the update to <a href="http://www.amazon.com/gp/product/B005GG15X4">Amazon&#x2019;s Android marketplace</a> for approval, with any luck that will go through soon as well.</p>
<p>This is a small release of C# To Go, but does come with some cool additions. Most importantly, it includes support for Android 4.0 (Ice Cream Sandwich). I had received many reports from users that the app would crash on startup on Ice Cream Sandwich, so those issues should be cleared up now.</p>
<p>The one real feature addition in this release is that I added multi-line editing support. This was by far the most requested feature (and most common complaint in user reviews). If you prefer to keep the old style, the option is still available in the application&#x2019;s settings.</p>
<p>Aside from that, this version does include some performance enhancements thanks to improvements in newer versions of Mono for Android. The most noticeable  improvement there is that startup time for the application has been cut down by a lot. I also added a splash screen shown during startup to make it feel a little nicer.</p>
<p>I have some more improvements I&#x2019;d like to make to the app as I have time, but I wanted to make sure I got this out ASAP since I didn&#x2019;t want to leave Ice Cream Sandwich users hanging. I hope you all enjoy the update, and happy New Year!</p>
<p><img src="https://gregshackles.com/content/images/2014/12/1.png" alt="C# To Go screenshot" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[NYC Code Camp 6: Mobile Apps]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Headed to the NYC Code Camp this weekend? The official mobile app for the camp is now available for Android, iOS and Windows Phone 7!</p>
<p>First things first, here are the links:</p>
<ul>
<li><a href="http://itunes.apple.com/us/app/nyc-code-camp-6/id463192274?mt=8">iOS</a></li>
<li><a href="https://market.android.com/details?id=com.gregshackles.nyccodecamp6">Android</a></li>
<li><a href="http://www.windowsphone.com/en-US/apps/7dd3aaa6-f1f2-4df5-aa45-3f3f98d4f385">Windows Phone 7</a></li>
</ul>
<p>You should also be able to find all of them by searching for</p>]]></description><link>https://gregshackles.com/nyc-code-camp-6-mobile-apps/</link><guid isPermaLink="false">61ce48a0437e8200017d410b</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Android]]></category><category><![CDATA[Windows Phone]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Greg Shackles]]></dc:creator><pubDate>Wed, 28 Sep 2011 13:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Headed to the NYC Code Camp this weekend? The official mobile app for the camp is now available for Android, iOS and Windows Phone 7!</p>
<p>First things first, here are the links:</p>
<ul>
<li><a href="http://itunes.apple.com/us/app/nyc-code-camp-6/id463192274?mt=8">iOS</a></li>
<li><a href="https://market.android.com/details?id=com.gregshackles.nyccodecamp6">Android</a></li>
<li><a href="http://www.windowsphone.com/en-US/apps/7dd3aaa6-f1f2-4df5-aa45-3f3f98d4f385">Windows Phone 7</a></li>
</ul>
<p>You should also be able to find all of them by searching for &#x201C;nyc code camp&#x201D; in the marketplace.</p>
<p>I will be using these apps as a reference in my session <a href="http://www.codecampnyc.org/speakers-sessions/#SG">Cross Platform Mobile Development with .NET</a>, where I&#x2019;ll talk about my approach in building them entirely in .NET, using MonoTouch and Mono for Android for iOS and Android. I won&#x2019;t get into the technical aspects in this post (perhaps I will explore that in a future post), but if you&#x2019;re interested the source code is all available on <a href="https://github.com/gshackles/NycCodeCamp6">GitHub</a>.</p>
<p>Some usage notes about the app:</p>
<ul>
<li>The app can pull down schedule updates throughout the day, but due to time constraints it is a manual process. A refresh button is available from the Overview screen that will check for updates and download them. The first time you launch the app the schedule will be pulled down automatically.</li>
<li>Unfortunately the floor maps have changed a bit since the apps were submitted. The app does not include the map for the third floor, and incorrectly marks where the sponsor tables will be located. Aside from that they are still accurate.</li>
</ul>
<p>Other than that, I hope you all find the apps useful, and I hope to see some of you at my session! To sweeten the deal, I&#x2019;ll also have some stuffed Mono monkeys to give out to attendees as well as a discount code for the Mono products.</p>
<p><img src="https://gregshackles.com/content/images/2014/12/cc-ios.jpg" alt="iOS screenshot" loading="lazy"><br>
<img src="https://gregshackles.com/content/images/2014/12/cc-android.png" alt="Android screenshot" loading="lazy"><br>
<img src="https://gregshackles.com/content/images/2014/12/cc-wp.png" alt="Windows Phone screenshot" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>