Xamarin Component Review: ModernHttpClient

These reviews consist of a Pros/Cons, some things developers might need to be aware of before using or during the use of a given component, and a quick code sample that might help people get started.

Links:
Component https://components.xamarin.com/view/modernhttpclient
Nuget – https://www.nuget.org/packages/modernhttpclient/
Github – https://github.com/paulcbetts/ModernHttpClient

Pros:

  • Increase HTTP request speeds.
    This really does make a noticeable difference from using the base
    HttpWebRequest,HttpClient, or WebClient. By using native libraries, it can skip through the Mono runtime bottleneck.
  • Ease of Use.
    Probably the easiest to use component you’re going to find, especially if you are already using HttpClient for your requests. It’s a simple one line drop on each instantiation of HttpClient.
new HttpClient(new NativeMessageHandler());
  • Lightweight.
    A common issue with components is that they increase the overall size of your app. Bigger apps get uninstalled quicker if they don’t do anything important for the user.

Cons:

  • Component conflict.
    Most people won’t run into this issue, and it is most prevalent on Android (at least it is the only place I’ve run into it). The problem arises because of ModernHttpClient’s use of OkHttp from SquareThe way they include this library is different from some others that are dependent on it. You’ll find components such as Picasso or Rounded Image View that also use OkHttp handle it differently, so that at build time, you’ll get a very deceiving error message.

Things to know:

The only things that I have been made aware of so far in my use of ModernHttpClient are a few out of place errors or bugs I’ve run across. Note that these are only found on Android.
1. The component conflict issue (as stated above): You can see an example from a thread here on this type of issue.
2. Android “crash” while debugging. This is an issue apparent with OkHttp that seems to cause crashes while debugging an Android app, while still maintaining the debugger. It is important to note that this does NOT cause this type of crash if the debugger is not attached. Also, after a crash, upon re-opening the app, the debugger remains attached and usable. Something along the lines of

F/libc( 1044): Fatal signal 5 (SIGTRAP), code -6 in tid 1131 (OkHttp Dispatch)

I haven’t tried the pro version, since the free license does exactly what I need, but if anyone has any insight into the pro license, let me know.

Sample:

...
using ModernHttpClient;
...

public class WebRequestUtils
{
    public async Task<string> GetResponseString(url)
    {
// Instantiate HttpClient with ModernHttpClient handler
using(var client = new HttpClient(new NativeMessageHandler())
        {
            var result = await client.GetAsync(url);
            return await result.Content.ReadAsStringAsync();
        }
    }
}

Make sure to keep an eye out for more component reviews as I get around to playing with more in real life situations.

Advertisements

Creating Google Hangouts Style Images in Xamarin iOS

If you haven’t seen it yet, there is this nifty style of thumbnail, icon, image, etc that Google does in their Hangouts app along with some of their others.

hangouts
Google Hangouts

Notice the second image and the last one where they take images from members of your hangout and lay  them together in an orderly fashion based on the number of people you have.

Here is the logic:

  1. One other person – Show the other user’s image
  2. Two other people – Show both other user’s images diagonally from each other
  3. Three other people – Show the three images in a triangle or pyramid shape
  4. Four or more people – Show 4 images in a square

This logic is straightforward with platforms like Windows and Android where you can create the layouts for each one and switch which one is visible based on the number of members. In this case, however, we are going to explore my favorite way to do it in iOS while still using the standard UITableViewCell.

This means rather than using multiple UIImageViews to display each one, we need to create the image in ONE UIImageView. Here is a simple method I use to do something like this:

  private UIImage GetHangoutImage(HangoutVM hangout, UIView container)
        {
            var members = hangout.Members
                    .Where(im => CurrentUser.FullName != im.Name)
                    .Where(im => !string.IsNullOrEmpty(im.ImageUrl))
                    .Take(4)
                    .ToList();
            if (!string.IsNullOrEmpty(hangout.ImageUrl))
            {
                //if the hangout has an image, use that url
                return Extensions.UIImageFromUrl(hangout.ImageUrl);
            }
            else if (members.Count == 0)
            {
                //if no other members, show self
                return Extensions.GetRoundImage(Extensions.UIImageFromUrl(CurrentUser.ImageUrl));
            }
            else if (members.Count == 1)
            {
                //show the one other member's image
                return Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[0].ImageUrl));
            }
            else if (members.Count == 2)
            {
                //if 2 other members, show both their images diagonally
                UIGraphics.BeginImageContext(new CoreGraphics.CGSize(container.Frame.Height, container.Frame.Height));
                UIImage image1;
                UIImage image2;
                UIImage combinedImage;
                image1 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[0].ImageUrl));
                image2 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[1].ImageUrl));

                image1.Draw(new RectangleF(22, 0, 22, 22));
                image2.Draw(new RectangleF(0, 22, 22, 22));
                combinedImage = UIGraphics.GetImageFromCurrentImageContext();
                UIGraphics.EndImageContext();
                return combinedImage;
            }
            else if (members.Count == 3)
            {
                //if 3 other members, show all three images in a triangle
                UIGraphics.BeginImageContext(new CoreGraphics.CGSize(container.Frame.Height, container.Frame.Height));

                UIImage image1;
                UIImage image2;
                UIImage image3;
                UIImage combinedImage;
                image1 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[0].ImageUrl));
                image2 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[1].ImageUrl));
                image3 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[2].ImageUrl));
                image1.Draw(new RectangleF(0, 0, 22, 22));
                image2.Draw(new RectangleF(22, 0, 22, 22));
                image3.Draw(new RectangleF(11, 22, 22, 22));
                combinedImage = UIGraphics.GetImageFromCurrentImageContext();

                UIGraphics.EndImageContext();
                return combinedImage;
            }
            else
            {
                //if 4 or more show first 4 in square
                UIGraphics.BeginImageContext(new CoreGraphics.CGSize(container.Frame.Height, container.Frame.Height));

                UIImage image1;
                UIImage image2;
                UIImage image3;
                UIImage image4;
                UIImage combinedImage;
                image1 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[0].ImageUrl));
                image2 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[1].ImageUrl));
                image3 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[2].ImageUrl));
                image4 = Extensions.GetRoundImage(Extensions.UIImageFromUrl(members[3].ImageUrl));

                image1.Draw(new RectangleF(0, 0, 22, 22));
                image2.Draw(new RectangleF(22, 0, 22, 22));
                image3.Draw(new RectangleF(0, 22, 22, 22));
                image4.Draw(new RectangleF(22, 22, 22, 22));

                combinedImage = UIGraphics.GetImageFromCurrentImageContext();
                UIGraphics.EndImageContext();
                return combinedImage;
            }
        }

In this situation I’m using some hard coded values for the sake of readability. The height of my UITableViewCell is 44 (hence seeing the 22’s everywhere for splitting it in half).

Also, I use a static extensions class to get images from a url and also to create round images. I talked about these in previous blog posts here:

  1. Creating Round Images in Xamarin.iOS
  2. Creating a UIImage from a URL

So now that we have our means of getting the image, we can create it in our GetCell override method in our TableViewSource class we are using to populate our UITableView:

  public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            var cellIdentifier = _hangouts[indexPath.Row].ID.ToString();
            var currentHangout = _hangouts[indexPath.Row];

            UITableViewCell cell = tableView.DequeueReusableCell(cellIdentifier);

            //// if there are no cells to reuse, create a new one
            if (cell == null)
                cell = new InstanceTableViewCell(currentInstance);
            cell = new UITableViewCell(UITableViewCellStyle.Subtitle, cellIdentifier);
            cell.TextLabel.Text = currentHangout.DisplayName;
            cell.DetailTextLabel.Text = string.Format("{0}{1}", currentHangout.LastMessageMember, currentHangout.LastMessage);
            cell.ImageView.Image = GetHangoutImage(currentHangout, cell.ImageView); // Get the Hangout Style Image
            return cell;
        }

That’s really as far as it goes! Now using that, you’ll get something looking like this:
instancesscreenshotioscropped

The lack of spacing may be misleading, but you’ll notice the first cell has 2 other members, the second has one, the third has 4+, the 4th has 3, etc.

Feel free to comment if you have any questions or want more advice on how to make something like this more appealing!

Xamarin iOS Creating Round Table Cell Images

One more freebie to be referenced in a later post. Here is how I create rounded images to be used in iOS table cells:

 public static UIImage GetRoundImage(UIImage im)
        {
            if (im == null)
                return null;
            UIGraphics.BeginImageContextWithOptions(new SizeF((float)im.Size.Width / 2, (float)im.Size.Height / 2), false, 0);
            UIBezierPath.FromRoundedRect(
                new RectangleF(0, 0, (float)im.Size.Width / 2, (float)im.Size.Height / 2),
                im.Size.Width / 2
            ).AddClip();
            im.Draw(new RectangleF(0, 0, (float)im.Size.Width / 2, (float)im.Size.Height / 2));
            UIImage im1 = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();
            return im1;
        }

Creating a UIImage with a URL in Xamarin iOS

Here is another freebie that I’m going to reference in a later blog post. This is the way I create UIImages from web URLs:

public static UIImage UIImageFromUrl(string uri)
{
    using (var url = new NSUrl(uri))
    using (var data = NSData.FromUrl(url))
        return UIImage.LoadFromData(data);
}

Creating a Circular Image in Xamarin.Android

If you’re working with mobile applications, sometimes something as simple as creating a circular image can be a bit more time consuming than it should be. Here is the snippet I use to create Circular Images in Xamarin.Android to follow up with my post about Creating Circular Images in XAML.

CircleDrawable:


public class CircleDrawable : Drawable
 {

     Bitmap bmp;
     BitmapShader bmpShader;
     Paint paint;
     RectF oval;

    public CircleDrawable(Bitmap bmp)
     {
         this.bmp = bmp;
         this.bmpShader = new BitmapShader (bmp, Shader.TileMode.Clamp, Shader.TileMode.Clamp);
         this.paint = new Paint () { AntiAlias = true };
         this.paint.SetShader (bmpShader);
         this.oval = new RectF ();
     }

    public override void Draw (Canvas canvas)
     {
         canvas.DrawOval (oval, paint);
     }

    protected override void OnBoundsChange (Rect bounds)
     {
         base.OnBoundsChange (bounds);
         oval.Set (0, 0, bounds.Width (), bounds.Height ());
     }

    public override int IntrinsicWidth
    {
         get
         {
             return bmp.Width;
         }
     }

    public override int IntrinsicHeight {
         get {
             return bmp.Height;
         }
     }

     public override void SetAlpha (int alpha)
     {

     }

    public override int Opacity {
         get {
             return (int)Format.Opaque;
         }
     }

    public override void SetColorFilter (ColorFilter cf)
    {

    }
 }

And here is an example of how to use it:

var bitmap = new Bitmap(); //do something else here to create your bitmap
var circleImage = new CircleDrawable(bitmap);

Organized Architecture for a Cross-Platform SignalR Application

SignalR is a great tool for keeping not only your web applications synced in real-time, but with it’s easy to use APIs for clients, it is perfect for use in your mobile applications.

I have some previous posts that are going to help in designing the of an architecture for a cross-platform implementation with SignalR. Take a look at these:

In this scenario, we are going to focus on two major layers of separation within our applications, although you can always add more layers of abstraction if that is your style or preference. Our two layers are the Portable Class Library and Native Client Libraries. This example is going to be using one PCL with all of our shared code, and then individual projects for Windows Phone 8.1, Windows 8.1, Xamarin.iOS, and Xamarin.Android.

The Portable Class Library

In this architecture, we want to focus on sharing as much code as possible. This implies that the only code that should not be in our PCL is code that includes the UI (Note we are not using Xamarin.Forms), updates the UI, or accesses the device’s native features (cameras, location, etc). This would include things such as ViewModels if you’re using the MVVM pattern (this example is using MVVM Light), Models, Web Request Logic, and even our SignalR Managers.
With that in mind, here are some nuget packages to consider for your PCL:

So let’s get started with a simple BaseHubManager to manage our connections. I’m going to follow a basic Inheritance pattern for these managers so that we can share as much of our SignalR code in our Base Manager as possible.

BaseHubManager:

  public class BaseHubManager
    {
        public HubConnection Connection{ get; set; }
        public IHubProxy Proxy { get; set; }

        // The empty constructor should only be used for a basic connection with no specific Hub
        public BaseHubManager()
        {
            Connection= new HubConnection(Constants.BaseUrl);
        }

        // Connect to specific Hub
        public BaseHubManager(string hubProxy)
        {
            Connection= new HubConnection(Constants.BaseUrl);
            Connection.Headers.Add(&quot;Authorization&quot;, string.Format(&quot;Bearer {0}&quot;, App.CurrentUser.TokenInfo.AccessToken)); //add access token to authorize
            Proxy = Connection.CreateHubProxy(hubProxy);
        }

        public async Task Start()
        {
            await _connection.Start(new LongPollingTransport());
            //Add additional shared Start logic
        }

        public void Stop()
        {
             _connection.Stop();
             //Add additional shared Stop logic
        }

        public virtual async void Connect()
        {
            await this.Start();
            //Add additional shared Connect logic
        }
    }

Now that we have a solid base, we can easily spin up individual Hub managers to connect to specific Hubs. Below is an example of a HubManager that would connect to the “ChatHub” on your server.

ChatHubManager:

 public class ChatHubManager : BaseHubManager
    {
        public ObservableCollection&lt;string&gt; Messages{ get; set; }

        public ChatHubManager ()
            : base(&quot;ChatHub&quot;)
        {
            this.Connect();
        }
        // Send new message to ChatHub
        public async Task&lt;string&gt; Create(string newMessage)
        {
            //establish connection
            await this.Start();

            var message= await Proxy.Invoke&lt;string&gt;(&quot;Create&quot;, newMessage);

            return message;
        }

        // Get all messages from ChatHub
        public async Task&lt;IEnumerable&lt;string&gt;&gt; Get()
        {
            //establish connection
            await this.Start();

            var messages = await Proxy.Invoke&lt;IEnumerable&lt;string&gt;&gt;(&quot;Get&quot;));

            Messages = new ObservableCollection&lt;string&gt;(messages);
            return messages;

        }

    }

Expanding new HubManagers like this one make it very easy to call server-side methods from our client by simply creating an instance of our Manager and calling our Invoking methods:

var manager = new ChatManager();
var messages = await manager.Get();

Now what about the other side of SignalR – Client methods? There are some things to consider. Most importantly, will your client end points update anything in the UI? This also includes updating ViewModel properties that will cause updates in the UI.
The problem is that the client end point listeners don’t stem from any sort of UI action the way that calling a server method might. Thus, it can’t run on the UI thread by itself and you would likely run into some sort of Threading Exception.

If you don’t need to update the UI at any point from your client listener, consider adding your listeners in your manager with something like this:

public ChatHubManager ()
    : base(&quot;ChatHub&quot;)
{
        this.Connect();
        Proxy.On&lt;string&gt;(&quot;newMessage&quot;, async data =&gt;
        {
            //Do something that is NOT on the UI thread
        }
}

One thing that SignalR does wonderfully is give you the ability to add these listeners from anywhere. That includes from your individual client projects that reference your PCL. So, let’s look at how to add these kind of requests to our client projects so we can update our UIs.

The Individual Client Projects

Let’s use a Windows Phone 8.1 project as our example, although the same logic can be applied to any type of project. So we need to add our client listener like we did above, but we also need it to make changes to our UI, which will require tapping into our UI thread. For this case, let’s add a ChatSignalingManager to our Windows Phone project that contains a reference to our ChatHubManager in our PCL above:

 public class ChatSignalingManager
    {
        private ChatHubManager _hubManager;
        private CoreDispatcher _dispatcher;
        public ChatSignalingManager (CoreDispatcher dispatcher)
        {
            _hubManager= new ChatHubManager ();
            _dispatcher = dispatcher;
            InitializeChatEndpoints();
        }

       //Add client end points for the ChatHubManager
        private void InitializeChatEndpoints()
        {
            var newMessage = _hubManager.Proxy.On&lt;string&gt;(&quot;newMessage&quot;, async data =&gt;
            {
                await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =&gt;
                    {
                        // process your UI changes here
                    });
            });

           // Add additional end points for the ChatHub here
        }

    }

Notice the biggest difference in how we handle our end point in our client project versus our PCL. The Dispatcher. In this case, we can pass Windows CoreDispatcher to our constructor, and by calling _dispatcher.RunAsync we are able to execute our process on our UI thread to successfully run code against our UI.

Here is an example of constructing the ChatSignalingManager from the MainPage of a Windows Phone app:

public sealed partial class MainPage : Page
{

    private ChatSignalingManager _signalingManager;
    public MainPage()
    {
        this.InitializeComponent();

        this.NavigationCacheMode = NavigationCacheMode.Required;
        _signalingManager = new ChatSignalingManager (Dispatcher);

    }

}

Hopefully that is enough code to get you started, but feel free to ask more questions in the comments. Just remember to share as much code as possible in your PCL and use your Client Projects to handle updates to your UI and also to utilize SignalR’s flexibility and versatility.

Connecting to an Authorized SignalR Hub from a .NET Client

In a previous post, I talked about adding Access and Refresh tokens to your Web Application using OAuth Bearer Tokens. In this post, we are going to be using this same logic to authorize external clients from an external .NET client application such as Windows Store apps, Xamarin.iOS, Xamarin.Android, etc.

Assuming we have our access token (and refresh token) stored locally on our client, we can use it to authorize our requests to our SignalR Hub. Let’s put together a basic Hub:

[Authorize]
public class SimpleHub : Hub
{
    public string AuthorizedString()
    {
        return "You are successfully Authorized";
    }

}

This is obviously and extremely simple example, and we aren’t going to get into calling client methods from the server with our authorized user as I will be covering that in a later post.
Now that we have our server-side Hub, let’s put together a client-side manager to connect to this Hub and make our request to AuthorizedString()

public class SimpleHubManager
{
    private HubConnection _connection;
    private IHubProxy _proxy;
    public SimpleHubManager()
    {
        _connection = new HubConnection("http://YOUR_DOMAIN/"); //connect to SignalR on your server
        _connection.Headers.Add("Authorization", string.format("Bearer {0}", YOUR_ACCESS_TOKEN)); //THIS IS WHERE YOU ADD YOUR ACCESS TOKEN MENTIONED ABOVE
        _proxy = _connection.CreateHubProxy("SimpleHub"); //connect to Hub from above
    }

    public async Task<string> GetAuthorizedString()
    {
        await _connection.Start(); //start connection
        var authorizedString = await _proxy.Invoke<string>("AuthorizedString"); //Invoke server side method and return value
        return authorizedString;
    }
}

As long as the Access Token being used by the client has not expired and is added to the Authorization Http Header, then we will be able to bypass the [Authorization] on the server.
So now, from our client, if we call:

var manager = new SimpleHubManager();
var authString = await manager.GetAuthorizedString(); //"You are successfully Authorized"

We see our string is exactly what we expect.

Stay tuned for some more advanced SignalR work in the future!