Corrado's Blog 2.0

Online thoughts of a technology funatic

Fixing SDWebImage issue on Xamarin.iOS

Loading an image into an ImageView control using Xamarin.iOS is a straightforward process:

  • Add a ImageView to a ViewController and give it a name (e.g: MyImage)
  • Add an image to Resources folder (e.g Users.png) and be sure that related Build Action is set to BundleResource.
  • And add this code:
        public override async void ViewDidLoad() { base.ViewDidLoad(); MyImage.Image=UIImage.FromBundle("Users.png"); }

      And you’re done, as alternative you can also use UIImage.FromFile, in this case the call is asynchronous and doesn’t use caching, while former is synchronous and does caching.

      Ok, but what if I want to show an image from a web url? things gets more complicated since you have to do the entire downloading process manually, something like:

      public async Task<UIImage> FromUrl(string imageUrl) { var httpClient = new HttpClient(); var contents = await httpClient.GetByteArrayAsync(imageUrl); return UIImage.LoadFromData(NSData.FromArray(contents)); }

      And use it this way:

      MyImage.Image = await this.FromUrl("http://thechromenews.com/wp-content/uploads/2015/11/Apple-Logo-4.png");

      Cool, but what if I want to use caching, show a placeholder or fire some code when downloading completes? well, that’s more code to write and since this is a quite common task you’ll be happy to know that there’s a component that does that for you.

      Look for SDWebImage on Xamarin Component Store and add it to your project:

      image

      Doing that adds to ImageView control a SetImage extension method that accepts a Uri and does all the work for you, usage is very easy, just write something like:

      NSUrl url=new NSUrl("http://thechromenews.com/wp-content/uploads/2015/11/Apple-Logo-4.png"); MyImage.SetImage(url,null,null);

      If you try this code you’ll discover that it doesn’t work, why? is the component buggy? well no, if you try it on older iOS versions it works fine.

      Also this quite common alternative raises an exception on iOS 9.x

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

      Ok, so what is the problem? well Apple decided that starting from iOS 9.0 all communications must use ATS (app transport security) and if you want to change this behavior you have to add an entry into info.plist file.

      This blog post describes ATS in detail and I encourage you to read it: http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

      To cut a long story short: Add this entry to your info.plist

      <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

      And everything will work as expected. Smile

      HTH

      Change ListView RowHeight programmatically in Xamarin Android

      Here’s a quick code snippet that allows you to change the row height of an Android ListView in Xamarin

      public override View GetView(int position, View convertView, ViewGroup parent) { View view = convertView ?? this.context.LayoutInflater.Inflate(Android.Resource.Layout.ActivityListItem, null); if (view.LayoutParameters == null) { view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, 300); } else { view.LayoutParameters.Height = 300; } ...other code here... return view; }

      Code resides inside ListView adapter, as you see, the magic is acting on view LayoutParameters property.

      Hope it helps.

      Genymotion issue with Windows 10 10586

      I use Genymotion for my Xamarin Android development, I know that both Xamarin and Microsoft provide their own emulator but, for my machine configuration Genymotion is the one I like most at the moment.

      This post is to help you find a solution in case the virtual device doesn’t boot on a machine after the upgrade to TH2 aka build 10586, with this message:

      image

      obviously the message is meaningless, digging into device log file located at %LocalAppData%\Genymobile\Genymotion\deployed\  I’ve discovered that error depends on a network issue:

      0:00:01.362237 VMSetError: Failed to open/create the internal network ‘HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #4′

      After doing several test and internet search I finally found the reason of the problem: no idea why but an option in the adapter settings was not selected:

      image

      The option is: VirtualBox NDIS6 Bridged Networking adapter, if not selected, select it and try again, your emulator should now work (or at least, it worked for me)

      works-on-my-machine-starburst

       

      Hope it works for you too, otherwise good luck finding the solution, if you find it please share, Genymotion support for free licenses is far than optimal.