{"id":432,"date":"2016-06-08T18:21:29","date_gmt":"2016-06-08T17:21:29","guid":{"rendered":"http:\/\/jonika.nu\/JonasBlogg\/?p=432"},"modified":"2016-10-04T20:39:50","modified_gmt":"2016-10-04T19:39:50","slug":"xamarin-droid-putting-locationmanager-in-a-separate-class","status":"publish","type":"post","link":"https:\/\/jonika.nu\/JonasBlogg\/archives\/432","title":{"rendered":"Xamarin Droid: Putting LocationManager in a separate class"},"content":{"rendered":"<p>I almost always put all logic in som sort of separate classes in my projects. I simply think it looks better, is way more easy to understand and the better way.<\/p>\n<p>When using Xamarin to create cross-plattform apps, you probably use dependency injection to minimize ugly code blocks like this.<\/p>\n<pre class=\"lang:c# decode:true\">if (Device.OS == TargetPlatform.iOS) {\r\n}else{\r\n}<\/pre>\n<p>That also means you pretty much need to create interfaces that you can use for all plattforms, which leads to this topic: You need to put logic in classes.<\/p>\n<p>I had a bit of a struggle to implement location services on Android this way, hence this post. Most bloggs and articles i found used the main activity. For iOS it was very straight forward, so I&#8217;m leaving that part out.<\/p>\n<p>And to be clear: This is my POC-code, not intended to copy and paste into production!<\/p>\n<p>First of all, i had to create an interface i could use for iOS and Droid. I kept\u00a0it simple, and only included stuff i needed: The current location, a method to initialize everything and a event to trigger when position changes.<\/p>\n<pre class=\"lang:c# decode:true \">public interface ILocationManager\r\n{\r\n\tTuple&lt;double, double&gt; GetCurrentLocation();\r\n\tvoid StartLocationUpdates();\r\n\tevent EventHandler LocationUpdated;\r\n}<\/pre>\n<p>I also created i class holding the main activity context. I needed this to be able to use the context from my class.<\/p>\n<pre class=\"lang:c# decode:true \">public class Config {\r\n\tpublic static MainActivity context = null;\r\n}<\/pre>\n<p>In my MainActivity i set the context of the class above:<\/p>\n<pre class=\"lang:c# decode:true \">Config.context = this;<\/pre>\n<p>From my cross-plattform code i need to get a instance of ILocationManager for the current plattform. For this, i use the DependencyService. I Also call my StartLocationUpdates method to start getting location updates:<\/p>\n<pre class=\"lang:c# decode:true\">private ILocationManager LocManager = DependencyService.Get&lt;ILocationManager&gt; ();\r\nLocManager.StartLocationUpdates ();<\/pre>\n<p>So far, all code except the config class is the same for both iOS and Android. But this is where i hit the wall on Android. I spent days trying to figure out how to create a class using my interface that would work in the same way my iOS code did. This is my solution<\/p>\n<p>First, make sure to put this line above the namespace in your class to get dependency injection to work:<\/p>\n<pre class=\"lang:c# decode:true \">[assembly: Xamarin.Forms.Dependency (typeof(NautiCalc.Droid.LocationManager))]<\/pre>\n<p>The second thing i found important was to decorate your class with the Activity attribute. This makes sure your activity is inserted into the Manifest, which is important. You also need to inherit Activity class, and implement your interface.<\/p>\n<pre class=\"lang:c# decode:true \">[Activity]\r\npublic class LocationManager : Activity, NautiCalc.ILocationManager, ILocationListener\r\n<\/pre>\n<p>The rest is kind of straight forward. You need to implement a few methods because of the inheritance of Activity, and of course your own interface.<\/p>\n<p>Here is my complete code:<\/p>\n<pre class=\"lang:c# decode:true \">using System;\r\nusing Android.Content;\r\nusing Android.App;\r\nusing Android.Locations;\r\nusing Android.OS;\r\nusing Android.Widget;\r\n\r\n[assembly: Xamarin.Forms.Dependency (typeof(NautiCalc.Droid.LocationManager))]\r\nnamespace NautiCalc.Droid\r\n{\r\n\t[Activity]\r\n\tpublic class LocationManager : Activity, NautiCalc.ILocationManager, ILocationListener\r\n\t{\r\n\t\t\/\/ event for the location changing\r\n\t\tpublic event EventHandler LocationUpdated = delegate {};\r\n\r\n\t\tprotected Android.Locations.LocationManager locMgr;\r\n\r\n\t\tpublic Android.Locations.LocationManager LocMgr {\r\n\t\t\tget { return this.locMgr; }\r\n\t\t}\r\n\r\n\t\tpublic Tuple&lt;double, double&gt; GetCurrentLocation ()\r\n\t\t{\r\n\t\t\tLocation lastKnown = locMgr.GetLastKnownLocation (Android.Locations.LocationManager.NetworkProvider);\r\n\t\t\tif (lastKnown != null) {\r\n\t\t\t\treturn Tuple.Create (lastKnown.Latitude, lastKnown.Longitude);\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tpublic void StartLocationUpdates ()\r\n\t\t{\r\n\t\t\tlocMgr = (Android.Locations.LocationManager)Config.context.GetSystemService (Context.LocationService);\r\n\r\n\t\t\tif (locMgr.AllProviders.Contains (Android.Locations.LocationManager.GpsProvider) &amp;&amp; locMgr.IsProviderEnabled (Android.Locations.LocationManager.GpsProvider)) {\r\n\t\t\t\tlocMgr.RequestLocationUpdates (Android.Locations.LocationManager.GpsProvider, 2000, 1, this);\r\n\t\t\t} \r\n\t\t}\r\n\r\n\t\tprotected override void OnPause ()\r\n\t\t{\r\n\t\t\tbase.OnPause ();\r\n\t\t\tlocMgr.RemoveUpdates (this);\r\n\t\t}\r\n\r\n\t\tpublic void OnProviderEnabled (string provider)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\tpublic void OnProviderDisabled (string provider)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\tpublic void OnStatusChanged (string provider, Availability status, Bundle extras)\r\n\t\t{\r\n\t\t}\r\n\r\n\t\tpublic void OnLocationChanged (Location location)\r\n\t\t{\r\n\t\t\tLocationData CurrentLocation = new LocationData ();\r\n\t\t\tCurrentLocation.Altitude = location.Altitude;\r\n\t\t\tCurrentLocation.Course = (double)location.Bearing;\r\n\t\t\tCurrentLocation.Latitude = location.Latitude;\r\n\t\t\tCurrentLocation.Longitude = location.Longitude;\r\n\t\t\tCurrentLocation.Speed = (double)location.Speed;\r\n\t\t\tLocationUpdated (this, new LocationUpdatedEventArgs (CurrentLocation));\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>Not that hard, once you figured it out. Happy coding!<\/p>\n<a href=\"https:\/\/twitter.com\/jonlin76\" class=\"twitter-follow-button\" data-show-count=\"false\" data-size=\"small\">Follow jonlin76<\/a>\n<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=\/^http:\/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+':\/\/platform.twitter.com\/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');<\/script>","protected":false},"excerpt":{"rendered":"<p>I almost always put all logic in som sort of separate classes in my projects. I simply think it looks better, is way more easy to understand and the better way. When using Xamarin to create cross-plattform apps, you probably use dependency injection to minimize ugly code blocks like this. if (Device.OS == TargetPlatform.iOS) { &hellip; <a href=\"https:\/\/jonika.nu\/JonasBlogg\/archives\/432\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Xamarin Droid: Putting LocationManager in a separate class<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[59,38,1],"tags":[99,100,42,101,102],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/posts\/432"}],"collection":[{"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/comments?post=432"}],"version-history":[{"count":2,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/posts\/432\/revisions"}],"predecessor-version":[{"id":434,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/posts\/432\/revisions\/434"}],"wp:attachment":[{"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/media?parent=432"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/categories?post=432"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jonika.nu\/JonasBlogg\/wp-json\/wp\/v2\/tags?post=432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}