{"id":24940,"date":"2016-03-15T13:15:55","date_gmt":"2016-03-15T20:15:55","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=24940"},"modified":"2019-04-04T09:05:48","modified_gmt":"2019-04-04T16:05:48","slug":"performing-background-data-refresh-for-android","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/performing-background-data-refresh-for-android\/","title":{"rendered":"Performing Background Data Refresh for Android"},"content":{"rendered":"<p>\t\t\t\tData is a crucial component of any app, which is why perfecting how your application interacts with data is so important. There are many techniques for improving interactions with remote data, such as request prioritization, speculative requests, and caching. These are certainly techniques to be explored and used, but what if your data was there before users even opened your app?<\/p>\n<p>Both iOS and Android expose mechanisms for refreshing data when your app is in the background (i.e. when a user is using a different app on their mobile device). Previously, we covered <a href=\"https:\/\/blog.xamarin.com\/add-background-data-refresh-to-ios-apps\/\">how to perform background data refresh on iOS<\/a>. In this blog post, we&#8217;re going to walk through the process of adding background data refresh to Android apps with the Google Cloud Messaging service in just a few easy steps.<\/p>\n<h2>Introduction to Android Background Data Refresh<\/h2>\n<p>Google Cloud Messaging (GCM) provides a way to send data between a client and server. However, it also exposes some additional functionality that we can take advantage of (even if you aren&#8217;t using GCM as a data service for your apps), such as the ability to schedule recurring background data refreshes at a regular interval. To get started, add the <a href=\"https:\/\/www.nuget.org\/packages\/Xamarin.GooglePlayServices.Gcm\/\">Xamarin Google Play Services &#8211; GCM<\/a> NuGet to your project.<\/p>\n<p>Android provides a mechanism for performing operations in the background called a service. Google Cloud Messaging exposes a special type of service named <code>GcmTaskService<\/code> which we can use to configure how exactly the background refresh will take place. We can then use the <code>GcmNetworkManager<\/code> to schedule a task on a regular interval.<\/p>\n<h2>Creating a Background Service<\/h2>\n<p>Create a new subclass of <code>GcmTaskService<\/code>\u00a0named BackgroundService. All services must be marked with the [Service] attribute so that they can properly be bundled into the\u00a0AndroidManifest.xml file. You can also specify additional members, such as required permissions for the service to operate. <code>IntentFilter<\/code> can also be applied as an attribute to filter what types of messages the service responds to. Apply the following attributes to the BackgroundService class:<\/p>\n<pre class=\"lang:csharp decode:true\">\n[Service (Exported = true, Permission = \"com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE\")]\n[IntentFilter (new [] {\"com.google.android.gms.gcm.ACTION_TASK_READY\"})]\n<\/pre>\n<p>Next, override the <code>OnRunTask<\/code> method, where we&#8217;ll define the logic to refresh the app data in the background automatically. You should return either <code>GcmNetworkManager.ResultSuccess<\/code> <code>GcmNetworkManager.ResultReschedule<\/code> or <code>GcmNetworkManager.ResultFailed<\/code>, depending on the <a href=\"https:\/\/developers.google.com\/android\/reference\/com\/google\/android\/gms\/gcm\/GcmNetworkManager#constant-summary\">result of the background operation<\/a>:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic override int OnRunTask (TaskParams @params)\n{\n    System.Threading.Tasks.Task.Run (async () =&gt; {\n        \/\/ TODO: Perform background refresh logic here.\n        Log.Debug (\"Background Service\", \"Background Task Succeeded\");\n    });\n\n    return GcmNetworkManager.ResultSuccess;\n}\n<\/pre>\n<p>GcmTaskService is a type of <a href=\"https:\/\/docs.microsoft.com\/xamarin\/android\/app-fundamentals\/services\/creating-a-service\/bound-services\">bound service<\/a>, so we must create a class that subclasses the <code>Binder<\/code> class, as seen below:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class BackgroundServiceBinder : Binder\n{\n    BackgroundService service;\n\n    public BackgroundServiceBinder (BackgroundService service)\n    {\n        this.service = service;\n    }\n\n    public BackgroundService GetBackgroundService ()\n    {\n        return service;\n    }\n}\n<\/pre>\n<p>The <code>Binder<\/code> class is responsible for maintaining a reference to our service so clients can make method calls against it. This is only created one time, in <code>GcmTaskService<\/code>&#8216;s <code>OnBind<\/code> method and remains until it&#8217;s unbound. Override the <code>OnBind<\/code> method and initialize and return the binder:<\/p>\n<pre class=\"lang:csharp decode:true\">\nIBinder binder;\npublic override IBinder OnBind (Intent intent)\n{\n    binder = new BackgroundServiceBinder (this);\n\n    return binder;\n}\n<\/pre>\n<h2>Schedule the Background Data Refresh<\/h2>\n<p>Now that the <code>GcmTaskService<\/code> is properly configured, it&#8217;s time to schedule our task using the <code>GcmNetworkManager<\/code>. We can use the <code>PeriodicTask&lt;\/code builder to build a task around a set of options, including execution interval, the service to run, requiring a network connection, and more. Add a new method named <code>StartBackgroundDataRefreshService<\/code> to your <code>MainActivity<\/code> and call it from the <code>OnCreate<\/code> lifecycle method:<\/p>\n<pre class=\"lang:csharp decode:true\">\nprivate void StartBackgroundDataRefreshService ()\n{\n    var pt = new PeriodicTask.Builder ()\n        .SetPeriod (1800) \/\/ in seconds; minimum is 30 seconds\n        .SetService (Java.Lang.Class.FromType (typeof(BackgroundService)))\n        .SetRequiredNetwork (0)\n        .SetTag (\"com.pierceboggan.backgrounddatarefresh\") \/\/ package name\n        .Build ();\n\n        GcmNetworkManager.GetInstance (this).Schedule (pt);\n}\n<\/pre>\n<h2>Configuration &amp; Testing<\/h2>\n<p>Finally, <code>GcmNetworkManager<\/code> requires a Google App Id to function properly, even if your app is not using Google Cloud Messaging services. To do this, create a <a href=\"https:\/\/console.developers.google.com\/\">new app in the Google Developers Console<\/a>. Copy the application identifier and create a new string entry in the <code>Strings.xml<\/code> file in the Resources\/values directory:<\/p>\n<pre class=\"lang:csharp decode:true\">\nAPPLICATION_ID_HERE\n<\/pre>\n<p>Run the app, and you'll see it updates in the background every 30 seconds! For testing, ensure that the device (<a href=\"https:\/\/university.xamarin.com\/resources\/how-to-install-google-play-on-android-emulator\">or emulator<\/a>) in test has Google Play Services correctly installed, or <code>GcmNetworkManager<\/code> will not be able to properly operate.<\/p>\n<h2>Wrapping Up<\/h2>\n<p>In this blog post, we created a background data refresh service using the Google Cloud Messaging NuGet with <code>GcmTaskService<\/code> and scheduled our background service to run periodically using <code>GcmNetworkManager<\/code>. Adding background data refresh is super easy, and only requires a few lines of code to get up and running. For more information on background services, <a href=\"https:\/\/docs.microsoft.com\/xamarin\/android\/app-fundamentals\/services\/\">check out our documentation on Android services<\/a> or our blog post on <a href=\"https:\/\/blog.xamarin.com\/add-background-data-refresh-to-ios-apps\/\">how to perform background refresh in iOS apps<\/a>.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Data is a crucial component of any app, which is why perfecting how your application interacts with data is so important. There are many techniques for improving interactions with remote data, such as request prioritization, speculative requests, and caching. These are certainly techniques to be explored and used, but what if your data was there [&hellip;]<\/p>\n","protected":false},"author":546,"featured_media":24947,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5,4],"class_list":["post-24940","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-android","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>Data is a crucial component of any app, which is why perfecting how your application interacts with data is so important. There are many techniques for improving interactions with remote data, such as request prioritization, speculative requests, and caching. These are certainly techniques to be explored and used, but what if your data was there [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/24940","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/546"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=24940"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/24940\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=24940"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=24940"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=24940"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}