Archive

Monthly Archives: October 2015

Intro

I really do enjoy working with MSTest to validate the business logic that I write. A decision was made recently by the architect of a project that I’m working on to use NUnit for our unit tests. I have to admit, I was not comfortable with abandoning MSTest. However, configuring NUnit was very straight forward. In addition, I’ve learned that the workflow doesn’t change at all between the two.

Steps

The following are the steps that I took to get up and running with NUnit:

1. Download NUnit from the NUnit website.
2. Download the NUnit Test Project Template.

NUnit_Test_Project

3. In Visual Studio, add a NUnit Test Project.

NUnit_SlnExplorer

4. Display the editor for the default unit test file under the recently created project.

NUnit_Code
5. Run the test and observe results.

NUnit_TestExplorer

Conclusion

In conclusion, I really do enjoy working with MSTest to validate the business logic that I write. A decision was made recently by the architect of a project that I’m working on to use NUnit for our unit tests. I have to admit, I was not comfortable with abandoning MSTest. However, configuring NUnit was very straight forward. In addition, I’ve learned that the workflow doesn’t change at all between the two.

Intro

In the last post, I wrote a tutorial on how to integrate Google Maps and GPS services into a Xamarin.Forms app. This post will focus on camera integration with Xamarin.Forms. In this post I will provide code (referenced from XF Labs) that will enable your Xamarin.Forms app to take and view photos.

The following image results from this tutorial when taking a picture with an Android device:

CamaraIntegration

Xamarin Labs

The code that I’m going to share was borrowed from a Xamarin.Forms Labs sample project. This sample can be found here.

Steps

  1. Ensure the following Nuget packages are installed on your Xamarin.Forms project and Android project:
  • Xamarin.Forms
  • XLabs.Forms
  • XLabs.IoC

2.   Update your MainActivity class to look like the following:

public class MainActivity : XFormsApplicationDroid
{
    bool _initialized = false;
 
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
 
        if (!_initialized) SetIoc();
 
        global::Xamarin.Forms.Forms.Init(this, bundle);
        Xamarin.FormsMaps.Init(this, bundle);
        LoadApplication(new App());
    }
 
    void SetIoc()
    {
        var resolverContainer = new SimpleContainer();
 
        var app = new XFormsAppDroid();
        app.Init(this);
 
        resolverContainer.Register<IDevice>(t => AndroidDevice.CurrentDevice)
            .Register<IDisplay>(t => t.Resolve<IDevice>().Display)
            .Register<IDependencyContainer>(resolverContainer)
            .Register<IXFormsApp>(app);
        Resolver.SetResolver(resolverContainer.GetResolver());
 
        _initialized = true;
    }
}

3.   Implement the following view-model:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    IMediaPicker _mediaPicker = null;
    readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
 
    public ViewModel()
    {
        TakePictureCommand = new DelegateCommand(async obj => await TakePicture());
        SelectPictureCommand = new DelegateCommand(async obj => await SelectPicture());
    }
 
    ImageSource _imageSource = null;
    public ImageSource ImageSource
    {
        get { return _imageSource; }
        set
        {
            if (_imageSource != value)
            {
                _imageSource = value;
                OnPropertyChanged();
            }
        }
    }
 
    DelegateCommand _takePictureCommand = null;
    public DelegateCommand TakePictureCommand
    {
        get { return _takePictureCommand; }
 
        set
        {
            if (_takePictureCommand != value)
            {
                _takePictureCommand = value;
                OnPropertyChanged();
            }
        }
    }
 
    DelegateCommand _selectPictureCommand = null;
 
    public DelegateCommand SelectPictureCommand
    {
        get { return _selectPictureCommand; }
        set
        {
            if (_selectPictureCommand != value)
            {
                _selectPictureCommand = value;
                OnPropertyChanged();
            }
        }
    }
 
    void Setup()
    {
        if (_mediaPicker != null) return;
 
        var device = Resolver.Resolve<IDevice>();
 
        _mediaPicker = DependencyService.Get<IMediaPicker>();
        //RM: hack for working on windows phone? 
        if (_mediaPicker == null) _mediaPicker = device.MediaPicker;
    }
 
    async Task TakePicture()
    {
        Setup();
 
        ImageSource = null;
 
        await _mediaPicker.TakePhotoAsync(new CameraMediaStorageOptions { DefaultCamera = CameraDevice.Front, MaxPixelDimension = 400 }).ContinueWith(t =>
        {
            if (t.IsFaulted) { var s = t.Exception.InnerException.ToString(); }
 
            else if (t.IsCanceled) { var canceled = true; }
 
            else
            {
                var mediaFile = t.Result;
                ImageSource = ImageSource.FromStream(() => mediaFile.Source);
 
                return mediaFile;
            }
 
            return null;
        }, _scheduler);
    }
 
    async Task SelectPicture()
    {
        Setup();
 
        ImageSource = null;
        try
        {
            var mediaFile = await _mediaPicker.SelectPhotoAsync(new CameraMediaStorageOptions
            {
                DefaultCamera = CameraDevice.Front,
                MaxPixelDimension = 400
            });
            ImageSource = ImageSource.FromStream(() => mediaFile.Source);
        }
 
        catch (System.Exception ex) { Debug.WriteLine(ex.Message); }
    }
 
    void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

4.   Implement following XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Pickup;assembly=Pickup"
             x:Class="Pickup.TakePhotoView">
 
  <ContentPage.BindingContext>
    <local:ViewModel />
  </ContentPage.BindingContext>
  
  <StackLayout>
    <Button Text="Take Picture" Command="{Binding TakePictureCommand}" />
    <Button Text="Select Image from Picture Library" Command="{Binding SelectPictureCommand}" />
    <Button Text="Select Video from Picture Library " Command="{Binding SelectVideoCommand}" />
    <Image Source="{Binding ImageSource}" VerticalOptions="CenterAndExpand" />
    <Entry Text="{Binding VideoInfo}" VerticalOptions="CenterAndExpand" />
  </StackLayout>
         </ContentPage>

Conclusion

In conclusion, I shared some code with that will enable a developer to integrate a camera on an Android device with a Xamarin.Forms app.

Intro

Within Xamarn.Forms, we may find ourselves having to implement a feature that’s dependent on a map and/or GPS. In order to implement this for Android and provide other controls to manage related services, we must implement a native Android page within our Xamarin.Forms app. In this post I will demonstrate how to load a native android page that contains a map that leverages GPS to identify a phones location.

Steps

1. Get access to the Google Maps API

2. Add a new class to your Xamarin.Forms project and call it “CustomPage”.
Solution Explorer:

SolutionExplorer_customPage

Class:

using Xamarin.Forms;
 
namespace Pickup
{
    public class CustomPage : ContentPage { }
}

2. In your Xamarin.Forms project, add a XAML file.

SolutionExplorer_xamlFile

Implement the following XAML:

<?xml version="1.0" encoding="utf-8" ?>
<local:CustomPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps" xmlns:local="clr-namespace:Pickup;assembly=Pickup" x:Class="Pickup.MapPage" />

3. Add a Layout folder to your Android project as well as an axml file.

SolutionExplorer_axmlFile

4. Implement the axml file as the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="200dp" android:layout_height="200dp" class="com.google.android.gms.maps.MapFragment" />

  <TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="top"/>
  
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <Button android:id="@+id/button_code" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Locate Me!" />
</LinearLayout>

5. Add a new class named LocationService under your Android project:

LocationService

Provide the following implementation:

    using static Bizmonger.Patterns.MessageBus;

    public class LocationService : Java.Lang.Object, ILocationListener
    {
        LocationManager _locationManager = null;

        public void GetLocation()
        {
            _locationManager = Application.Context.GetSystemService(Context.LocationService) as LocationManager;

            var locationCriteria = new Criteria();

            locationCriteria.Accuracy = Accuracy.Coarse;
            locationCriteria.PowerRequirement = Power.Medium;

            var locationProvider = _locationManager.GetBestProvider(locationCriteria, true);

            if (locationProvider != null)
            {
                _locationManager.RequestLocationUpdates(locationProvider, 2000, 1, this);
            }
        }

        public void OnLocationChanged(Location location) =>
            Publish(Messages.LOCATION_CHANGED, new Core.Location(location.Latitude, location.Longitude));

        public void OnProviderDisabled(string provider)
        {
            throw new NotImplementedException();
        }

        public void OnProviderEnabled(string provider)
        {
            throw new NotImplementedException();
        }

        public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
        {
            throw new NotImplementedException();
        }
    }

6. Add a custom renderer to your Android project by adding a new class.
SolutionExplorer_maprenderer

7. Implement the renderer with the following code:

using static Bizmonger.Patterns.MessageBus;

[assembly: ExportRenderer(typeof(CustomPage),
                          typeof(MapPageRenderer))]
namespace Pickup.Droid
{
    public class MapPageRenderer : PageRenderer
    {
        Core.Location _location;
        Android.Views.View _view;
        GoogleMap _map;

        public MapPageRenderer()
        {
            Subscribe(Messages.LOCATION_CHANGED, obj =>
                {
                    _location = obj as Core.Location;

                    LatLng location = new LatLng(_location.Latitude, _location.Longitude);
                    CameraPosition.Builder builder = CameraPosition.InvokeBuilder();
                    builder.Target(location);
                    builder.Zoom(18);
                    CameraPosition cameraPosition = builder.Build();
                    CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);

                    var activity = this.Context as Activity;
                    MapFragment mapFrag = (MapFragment)activity.FragmentManager.FindFragmentById(Resource.Id.map);
                    _map = mapFrag.Map;
                    _map?.MoveCamera(cameraUpdate);

                    var textview = _view.FindViewById<Android.Widget.TextView>(Resource.Id.textView);
                    textview.Text = $"{_location.Latitude} , {_location.Longitude}";
                });
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);

            var activity = this.Context as Activity;
            _view = activity.LayoutInflater.Inflate(Resource.Layout.MapLayout, this, false);

            var mapFragment = activity.FragmentManager.FindFragmentById<MapFragment>(Resource.Id.map);

            var codeButton = _view.FindViewById<Android.Widget.Button>(Resource.Id.button_code);
            codeButton.Click += OnButtonTapped;

            AddView(_view);
        }

        void OnButtonTapped(object sender, EventArgs e)
        {
            var locationService = new LocationService();
            locationService.GetLocation();
        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
            _view.Measure(msw, msh);
            _view.Layout(0, 0, r - l, b - t);
        }
    }

8. When you run your app, you should see something like this:

defaultMap

9. Click the “Locate Me!” button and observe the map’s navigation to your location.

app_screenshot

Conclusion

In conclusion, we may find ourselves having to implement a feature that’s dependent on a map and/or GPS. In order to implement this for Android and provide other controls to manage related services, we must implement a native Android page within our Xamarin.Forms app. In this post I demonstrated how to load a native android page that contains a map that leverages GPS to identify a phones location.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net

Intro

Within Xamarn.Forms, we may find ourselves having to show a custom page per device platform (i.e. IOS, Android, etc.) In my case, I needed to display a content page that had a map along with some other controls. In this post I will demonstrate how to load a native android page within a Xamarin.Forms app.

Steps

  1. Add a new class to your Xamarin.Forms project and call it “CustomPage”.

Solution Explorer:

SolutionExplorer_customPage

Class:

using Xamarin.Forms;
 
namespace Pickup
{
    public class CustomPage : ContentPage { }
}

2. In your Xamarin.Forms project, add a XAML file.

SolutionExplorer_xamlFile

Implement the following XAML:

<?xml version="1.0" encoding="utf-8" ?>
<local:CustomPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:Pickup;assembly=Pickup" 
x:Class="Pickup.MapPage" />

3. Add a Layout folder to your Android project as well as an axml file.

SolutionExplorer_axmlFile

4. Implement the axml file as the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="200dp" android:layout_height="200dp" class="com.google.android.gms.maps.MapFragment" />

  <TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="top"/>
  
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <Button android:id="@+id/button_code" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Locate Me!" />
</LinearLayout>

5. Add a custom renderer to your Android project by adding a new class.
SolutionExplorer_maprenderer

6. Implement the renderer with the following code:

[assembly: ExportRenderer(typeof(CustomPage),
                          typeof(MapPageRenderer))]
namespace Pickup.Droid
{
    public class MapPageRenderer : PageRenderer
    {
        Android.Views.View _view;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);
 
            var activity = this.Context as Activity;
            _view = activity.LayoutInflater.Inflate(Resource.Layout.MapLayout, this, false);
 
            AddView(_view);
        }
 
        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
            _view.Measure(msw, msh);
            _view.Layout(0, 0, r - l, b - t);
        }
    }
}

7. When you run your app, you should see something like this:

defaultMap

Conclusion

In conclusion, we may find ourselves having to show a custom page with Xamarin.Forms per device platform (i.e. IOS, Android, etc.) In my case, I needed to display a content page that had a map along with some other controls. In this post I demonstrated how to load a native android page within a Xamarin.Forms app.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net

podcast[1]

Intro

A couple of years ago, after listening to an episode on Dot Net Rocks, I made a promise to myself:

“Instead of listening to other guests on this podcast, one day I’m going to be listening to myself.”

I fulfilled this prophesy on October 7th. I recorded a show with Richard Campbell and Carl Franklin. The show was centered on Software Craftsmanship.

This is what I did to get on their show:

  • Developed an expertise on specific areas of software development
  • Routinely commented on Dot Net Rocks and other software development websites (blogs, podcasts, etc.).
  • Created a technical blog
  • Reached out to Dot Net Rocks

Areas of Expertise

I knew that in order to be a guest on any podcast program, I would have to be an expert at something related to software development. As a result, I decided that I would to convey expertise in XAML, Test Automation, and Software Craftsmanship, In addition, I would try to answer at least one question on StackOverflow.com every day until I reached 1000 points. Whenever I would solve a really tough problem, I would immediately search stackoverflow.com to see if there were any posted questions to the problem I just solved. I would then post my solution to every question I could find on the site.

Sharing my Thoughts

I knew that in order to be perceived as a thought leader, I would have to take massive and consistent action in proliferating my thoughts to the software development community. As a result, I deposited my ideas everywhere I could find a medium to host them. That included stackoverflow.com, DotNetRocks.com, HanselMinutes.com, SimpleProgrammer.com, LinkedIn.com, local user groups, my own technical blog, etc. Thus, I didn’t just post comments. Comments are typically short and limited. Instead I would post essays on people’s sites. Sometimes, I would copy and paste an entire article that I wrote for my blog and post it as a comment to someone else’s blog or podcast. I just didn’t care. If my content was related to a topic then I considered myself killing multiple birds with one stone.

Maintaining a Technical Blog

As I mentioned earlier, I maintained a technical blog. I viewed having a technical blog as my own personal repository for my solutions to technical problems as well as it being a depot for my philosophical thoughts on software development. I would then copy and paste my articles from my technical blog to LinkedIn.com in order to create an additional channel for discovery.

Reaching Out

After creating a professional web footprint that I could be proud of, I decided that it was time for me to reach out to DotNetRocks. After all, all they could do is just ignore my email. So I simply emailed the hosts of the show and asked if I could be prescreened for a show regarding software development practices. They soon responded to my email with a date to do the show. I couldn’t believe it. What took about two years of preparation only took a couple of days to setup. As a result, the show I recorded with them will be posted on November 5th 2015.

Conclusion

In conclusion, a couple of years ago, after listening to an episode on Dot Net Rocks, I made a promise to myself:

“Instead of listening to other guests on this podcast, one day I’m going to be listening to myself.”

I fulfilled this prophesy on October 7th. I recorded a show with Richard Campbell and Carl Franklin. The show was centered on Software Craftsmanship. It will air November 5th 2015.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net

courtyard-ghetto[1]

Most young black people from lower income areas see success as an entertainer (athletes, rappers, singers, etc.) on T.V. or a drug dealer on the block. Software Development just isn’t visible for most of us from low income areas. What’s a gift and a curse is that minorities from this demographic are known to be extremely competitive (i.e. sports, drug turf, etc.). Just imagine that passion and aggression directed towards tech startups. Just imagine if we showed millionaire startup founders who just happen to be minorities. That “success” could be shown to people that never even knew it was an option.

Based on this revelation, I will be reaching out to the Miami Dade County Public Schools.

I’m done talking about it.

I’m going to actually do something about it…

This post is dedicated to the late Dennis Omlor.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net

Intro

Software isn’t deployed. It’s launched.

As human beings, we are prone to making mistakes. In fact, we make so many mistakes that even religions have attempted to provide reasons to why we are so error prone.

To combat this human flaw, we humans now rely on checklists to support our decision making process when launching mission critical operations. Notice how I used the term “launching” and not the term “deploying”.

Deploy vs Launch

Deploy: to organize and send out (people or things) to be used for a particular purpose

Launch: to set in motion

To deploy software would suggest that we know what we’re doing and have a backup plan for every possible scenario of how that software would be used regardless of its intent.

Notice the difference between the two words in regards to their definition. Hence, to deploy is to send out and to be used for a particular purpose. However, to launch is to just set something in motion. Therefore, when we launch something, we cannot be certain of the end result. Apple “deployed” the IPhone to solve people’s problems and make people’s lives simpler. However, since the launching of the IPhone, mankind has devolved. The majority of people are now mobile-tethered zombies. They are obsessed with selfies and social media. As a result of this launch, new laws have been created to stem the abuse of the technology.

Conclusion

In conclusion, I don’t think software is deployed. Till this day, the majority of software releases are still treated as special events. As a result, we humans don’t really deploy software based on its definition. Instead, we cross our fingers and launch it. We then go into firefighter mode shortly after and patch any security concerns that have been exposed after the launch and any other anomalies that have been exposed by the launch. Hopefully, we are able to have retrospectives after each launch so that we can create and or extend our checklist before launching the next piece of software. In addition to reviewing our checklist, we should aspire to execute our checklist as automated tests to further remove human error from the process.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net