{"id":5653,"date":"2023-10-04T15:53:49","date_gmt":"2023-10-04T19:53:49","guid":{"rendered":"https:\/\/ionic.io\/blog\/?p=5653"},"modified":"2023-10-05T12:50:05","modified_gmt":"2023-10-05T16:50:05","slug":"create-background-tasks-in-ionic-with-capacitor","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor","title":{"rendered":"How to Create Background Tasks in Ionic with Capacitor"},"content":{"rendered":"\n<p><em>This is a guest post from Simon Grimm, Ionic Developer Expert and educator at <\/em><a href=\"https:\/\/ionicacademy.com\/\"><em>the Ionic Academy<\/em><\/a><em>, an online school with 70+ video courses focused entirely on building awesome mobile apps with Ionic and Capacitor!<\/em><\/p>\n\n\n\n<p>What happens when users put your mobile app in the background? Can you still occasionally tap into the device\u2019s resources to perform tasks? The answer is yes, and Capacitor makes it easy to do so now with the new <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/background-runner\">Capacitor Background Runner<\/a>.<\/p>\n\n\n\n<p>In this tutorial, we will learn how to use the new Background Runner plugin to perform tasks such as fetching data, sending notifications, or even getting the user&#8217;s geolocation. We will also learn how to debug and trigger background tasks directly from Xcode.<\/p>\n\n\n\n<p>You can also <a href=\"https:\/\/github.com\/saimon24\/capacitor-background-tasks\">find the full source code on GitHub<\/a>. But before we get into the plugin, let\u2019s first take a look at what background tasks are and why we need them.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Background Tasks in Mobile Apps<\/strong><\/h2>\n\n\n\n<p>When building mobile apps, we often have to deal with tasks that should run in the background, like checking for new emails, updating chat messages, or syncing data. In the past, this was only possible with native code, but now we can do it with Capacitor as well.<\/p>\n\n\n\n<p>The idea is to define a task that you will run in the background and either dispatch it manually from your code or let the OS trigger it automatically on a given interval.<\/p>\n\n\n\n<p>However, the second option proves very challenging in reality. Because even if you tell iOS to perform your background task every 5 minutes, your code will most likely get executed every 2 hours.<\/p>\n\n\n\n<p>This is because iOS will try to optimize the battery life of the device and only run background tasks when it thinks it&#8217;s a good time to do so. This is why you should never rely on background tasks to run at a specific time.<\/p>\n\n\n\n<p>However, you can still use this to update your app&#8217;s data before a user opens it again or to send a local notification to the user.<\/p>\n\n\n\n<p>It can also offload some work from the main thread to the background thread &#8211; and we will see all of that in action.<\/p>\n\n\n\n<p>If you want to learn more about this, check out the <a href=\"https:\/\/www.youtube.com\/watch?v=xjaPK0xuYgg&amp;ab_channel=Ionic\">Capacitor Livestream about Background Tasks<\/a>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Setting up the Project with Background Runner<\/strong><\/h2>\n\n\n\n<p>To get started, bring up a terminal, create a new Ionic app, and install the <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/background-runner\">Capacitor Background Runner<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-shell\">ionic start backgroundApp blank --type angular\ncd .\/backgroundApp\nnpm install @capacitor\/background-runner\nionic cap add ios\nionic cap add android<\/code><\/pre>\n\n\n\n<p>Next, we need to add a file that holds our background tasks, so simply create one at <code>src\/app\/runners\/runner.js<\/code> and leave it empty for the moment. To make sure this file is copied when building the app, we need to bring up the angular.json and include it in the assets array like this:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">{\n  &quot;projects&quot;: {\n    &quot;app&quot;: {\n      &quot;architect&quot;: {\n        &quot;build&quot;: {\n          &quot;options&quot;: {\n            &quot;assets&quot;: [\n              {\n                &quot;glob&quot;: &quot;**\/*&quot;,\n                &quot;input&quot;: &quot;src\/assets&quot;,\n                &quot;output&quot;: &quot;assets&quot;\n              },\n              {\n                &quot;glob&quot;: &quot;**\/*.svg&quot;,\n                &quot;input&quot;: &quot;node_modules\/ionicons\/dist\/ionicons\/svg&quot;,\n                &quot;output&quot;: &quot;.\/svg&quot;\n              },\n              {\n                &quot;glob&quot;: &quot;runner.js&quot;,\n                &quot;input&quot;: &quot;src\/app\/runners&quot;,\n                &quot;output&quot;: &quot;.\/runners&quot;\n              }\n            ]\n          }\n        }\n      }\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Now we also need to specify some information for Capacitor so the plugin can pick up the file and eventually an event that we can trigger from our code. To do so, open the <code>capacitor.config.ts<\/code> and change it like this:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { CapacitorConfig } from &#039;@capacitor\/cli&#039;;\n\nconst config: CapacitorConfig = {\n  appId: &#039;com.capacitor.background&#039;,\n  appName: &#039;backgroundApp&#039;,\n  webDir: &#039;www&#039;,\n  server: {\n    androidScheme: &#039;https&#039;,\n  },\n  plugins: {\n    BackgroundRunner: {\n      label: &#039;com.capacitor.background.check&#039;,\n      src: &#039;runners\/runner.js&#039;,\n      event: &#039;checkIn&#039;,\n      repeat: true,\n      interval: 30,\n      autoStart: true,\n    },\n  },\n};\n\nexport default config;<\/code><\/pre>\n\n\n\n<p>The most important part is that the plugin has a similar label to your appId! This is important because otherwise, the plugin won&#8217;t be able to find your file or execute the task. The time we specify here is more a friendly request to the OS as mentioned before, we are not guaranteed to get executed at this time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Native App Configuration<\/strong><\/h2>\n\n\n\n<p>To make sure our app can run in the background, we need to add some configuration to our native apps as well.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>iOS<\/strong><\/h3>\n\n\n\n<p>For iOS we first need to update the <code>ios\/App\/App\/AppDelegate.swift<\/code> file and change one function and add another:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-swift\">import UIKit\nimport BackgroundTasks\nimport Capacitor\nimport CapacitorBackgroundRunner\n\n@UIApplicationMain\n\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n\u00a0\u00a0\u00a0\u00a0var window: UIWindow?\n\n\u00a0\u00a0\u00a0\u00a0func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0BackgroundRunnerPlugin.registerBackgroundTask()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0BackgroundRunnerPlugin.handleApplicationDidFinishLaunching(launchOptions: launchOptions)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return true\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -&gt; Void) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0print(&quot;Received remote notification&quot;)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0BackgroundRunnerPlugin.dispatchEvent(event: &quot;remoteNotification&quot;, eventArgs: userInfo) { result in\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0switch result {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case .success:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0completionHandler(.newData)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case .failure:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0completionHandler(.failed)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}<\/code><\/pre>\n\n\n\n<p>Additionally, we need to enable the background capability and different modes that our app will use from the background:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh6.googleusercontent.com\/mYb59tPdWHYQ4LcRFZcd9XTJ4hQ2Z9GAzM85kzO2MaNY7wbdV-72UsVfEBqA0dTcTSXMazMH6_GJvFtu3Y9k9il94CCrzup_hxAhg8NYv05Xij5Kh9KL5735GN9cgpBkPw5CZmbxIbgbJr9BkSWvf9Q\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/mYb59tPdWHYQ4LcRFZcd9XTJ4hQ2Z9GAzM85kzO2MaNY7wbdV-72UsVfEBqA0dTcTSXMazMH6_GJvFtu3Y9k9il94CCrzup_hxAhg8NYv05Xij5Kh9KL5735GN9cgpBkPw5CZmbxIbgbJr9BkSWvf9Q\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>Select the modes as you see fit, but for our example, these are the ones we need:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh4.googleusercontent.com\/G0yvDS6UKgmlBmn5vGkJSn1jjLEiWR7i1o-l4Q08M6TdukoK5mODXroIRkRuYDz7cftLWuD-Yzm4f8Tv-JZmKZxW975mS4dbSygKzVOGIagGVoV6HGkx6eUyn5oQ456UROwtGlw1C9GWPID1oHHDFAo\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/G0yvDS6UKgmlBmn5vGkJSn1jjLEiWR7i1o-l4Q08M6TdukoK5mODXroIRkRuYDz7cftLWuD-Yzm4f8Tv-JZmKZxW975mS4dbSygKzVOGIagGVoV6HGkx6eUyn5oQ456UROwtGlw1C9GWPID1oHHDFAo\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>Now we also need to include some permissions in the <code>ios\/App\/App\/Info.plist<\/code> for geolocation and also add the <code>BGTaskSchedulerPermittedIdentifiers<\/code> if it wasn&#8217;t added before and use the key of your background task:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-xml\">&lt;key&gt;BGTaskSchedulerPermittedIdentifiers&lt;\/key&gt;\n&lt;array&gt;\n  &lt;string&gt;com.capacitor.background.check&lt;\/string&gt;\n&lt;\/array&gt;\n&lt;key&gt;NSLocationAlwaysAndWhenInUseUsageDescription&lt;\/key&gt;\n&lt;string&gt;$(PRODUCT_NAME) uses location services to track your location.&lt;\/string&gt;\n&lt;key&gt;NSLocationAlwaysUsageDescription&lt;\/key&gt;\n&lt;string&gt;$(PRODUCT_NAME) uses location services to track your location.&lt;\/string&gt;\n&lt;key&gt;NSLocationWhenInUseUsageDescription&lt;\/key&gt;\n&lt;string&gt;$(PRODUCT_NAME) uses location services to track your location.&lt;\/string&gt;<\/code><\/pre>\n\n\n\n<p>This did not happen automatically for me, so check your file for that entry.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Android<\/strong><\/h3>\n\n\n\n<p>For Android we first need to add some permissions as well, so open up the <code>android\/app\/src\/main\/AndroidManifest.xml<\/code> and add the following:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">&lt;uses-permission android:name=&quot;android.permission.ACCESS_COARSE_LOCATION&quot; \/&gt;\n&lt;uses-permission android:name=&quot;android.permission.ACCESS_FINE_LOCATION&quot; \/&gt;\n&lt;uses-permission android:name=&quot;android.permission.SCHEDULE_EXACT_ALARM&quot; \/&gt;\n&lt;uses-feature android:name=&quot;android.hardware.location.gps&quot; \/&gt;<\/code><\/pre>\n\n\n\n<p>There are no other changes needed for Android, so we are good to go!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Implementing the Background Task<\/strong><\/h2>\n\n\n\n<p>Let&#8217;s start with an easy example and simply save a value to the CapacitorKV store. This is like the <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/preferences\">Capacitor Preferences<\/a> plugin and is directly available to our Background Runner. To do so, open up the src\/app\/runners\/runner.js and add the following code:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">\/\/ Save a value to the Capacitor KV store\naddEventListener(&#039;testSave&#039;, async (resolve, reject, args) =&gt; {\n  try {\n    CapacitorKV.set(&#039;foo&#039;, &#039;my bar 42&#039;);\n    resolve();\n  } catch (err) {\n    console.error(err);\n    reject(err);\n  }\n});\n\n\/\/ Get a value from the Capacitor KV store\naddEventListener(&#039;testLoad&#039;, async (resolve, reject, args) =&gt; {\n  try {\n    const value = CapacitorKV.get(&#039;foo&#039;);\n    resolve(value);\n  } catch (err) {\n    console.error(err);\n    reject(err);\n  }\n});<\/code><\/pre>\n\n\n\n<p>This is a very simple example, but it shows how we can use the Capacitor API directly from our background task. Now that we have two events defined, we can call them directly from our app! For this, bring up the <code>src\/app\/home\/home.page.ts<\/code> and first request permissions for our background runner and then call the <code>dispatchEvent()<\/code> method to trigger the event:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { Component } from &#039;@angular\/core&#039;;\nimport { BackgroundRunner } from &#039;@capacitor\/background-runner&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n  user: any = null;\n\n  constructor() {\n    this.init();\n  } \/\/ Request permissions for background tasks\n\n  async init() {\n    try {\n      const permissions = await BackgroundRunner.requestPermissions({\n        apis: [&#039;notifications&#039;, &#039;geolocation&#039;],\n      });\n      console.log(&#039;permissions&#039;, permissions);\n    } catch (err) {\n      console.log(`ERROR: ${err}`);\n    }\n  } \/\/ Test the KV Store\n\n  async testSave() {\n    const result = await BackgroundRunner.dispatchEvent({\n      label: &#039;com.capacitor.background.check&#039;,\n      event: &#039;testSave&#039;,\n      details: {},\n    });\n    console.log(&#039;save result&#039;, result);\n  }\n\n  async testLoad() {\n    const result = await BackgroundRunner.dispatchEvent({\n      label: &#039;com.capacitor.background.check&#039;,\n      event: &#039;testLoad&#039;,\n      details: {},\n    });\n    console.log(&#039;load result&#039;, result);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Now simply call those functions with some buttons and check your logs when you run the app on a real device &#8211; you should see the values being saved and loaded!&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Using Background Notifications and Data Fetching<\/strong><\/h2>\n\n\n\n<p>The real power of background tasks comes from the fact that we can offload some work from our app, or periodically update some data. Let&#8217;s now add a fetch call that returns data, and another call to the <code>CapacitorNotifications<\/code> plugin to schedule a local notification.<\/p>\n\n\n\n<p>Bring up the <code>src\/app\/runners\/runner.js<\/code> again and add:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">\/\/ Make a fetch request to the randomuser API and return first user\n\naddEventListener(&#039;fetchTest&#039;, async (resolve, reject, args) =&gt; {\n\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0const res = await fetch(&#039;https:\/\/randomuser.me\/api\/&#039;);\n\u00a0\u00a0\u00a0\u00a0if (!res.ok) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error(&#039;Could not fetch user&#039;);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0const result = await res.json();\n\u00a0\u00a0\u00a0\u00a0resolve(result[&#039;results&#039;][0]);\n\u00a0\u00a0} catch (err) {\n\u00a0\u00a0\u00a0\u00a0console.error(err);\n\u00a0\u00a0\u00a0\u00a0reject(err);\n\u00a0\u00a0}\n});\n\n\/\/ Trigger a local notification\n\naddEventListener(&#039;notificationTest&#039;, async (resolve, reject, args) =&gt; {\n\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0let scheduleDate = new Date();\n\u00a0\u00a0\u00a0\u00a0scheduleDate.setSeconds(scheduleDate.getSeconds() + 5);\n\u00a0\u00a0\u00a0\u00a0CapacitorNotifications.schedule([\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0id: 42,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0title: &#039;Background Magic \ud83e\uddd9\u200d\u2642\ufe0f&#039;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0body: &#039;This comes from the background runner&#039;,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scheduleAt: scheduleDate,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0},\n\u00a0\u00a0\u00a0\u00a0]);\n\u00a0\u00a0\u00a0\u00a0resolve();\n\u00a0\u00a0} catch (err) {\n\u00a0\u00a0\u00a0\u00a0console.error(err);\n\u00a0\u00a0\u00a0\u00a0reject(err);\n\u00a0\u00a0}\n});<\/code><\/pre>\n\n\n\n<p>Again we can simply include those events in our <code>src\/app\/home\/home.page.ts<\/code> like this:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">\/\/ Test the background fetch\nasync performBackgroundFetch() {\n\u00a0\u00a0const result = await BackgroundRunner.dispatchEvent({\n\u00a0\u00a0\u00a0\u00a0label: &#039;com.capacitor.background.check&#039;,\n\u00a0\u00a0\u00a0\u00a0event: &#039;fetchTest&#039;,\n\u00a0\u00a0\u00a0\u00a0details: {},\n\u00a0\u00a0});\n\u00a0\u00a0this.user = result;\n};\n\n\/\/ Schedule a notification from background\nasync scheduleNotification() {\n\u00a0\u00a0await BackgroundRunner.dispatchEvent({\n\u00a0\u00a0\u00a0\u00a0label: &#039;com.capacitor.background.check&#039;,\n\u00a0\u00a0\u00a0\u00a0event: &#039;notificationTest&#039;,\n\u00a0\u00a0\u00a0\u00a0details: {},\n\u00a0\u00a0});\n};<\/code><\/pre>\n\n\n\n<p>And finally, update your UI inside the <code>src\/app\/home\/home.page.html<\/code> to show the buttons and an item that we try to load from the background:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-xml\">&lt;ion-header&gt;\n\u00a0\u00a0&lt;ion-toolbar&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-title&gt; Capacitor Background &lt;\/ion-title&gt;\n\u00a0\u00a0&lt;\/ion-toolbar&gt;\n&lt;\/ion-header&gt;\n\n&lt;ion-content&gt;\n\u00a0\u00a0&lt;ion-button (click)=&quot;performBackgroundFetch()&quot; expand=&quot;full&quot; &gt;Perform Background Call&lt;\/ion-button&gt;\n\u00a0\u00a0&lt;ion-button (click)=&quot;scheduleNotification()&quot; expand=&quot;full&quot; &gt;Schedule Local Notification&lt;\/ion-button&gt;\n\u00a0\u00a0&lt;ion-button (click)=&quot;testSave()&quot; expand=&quot;full&quot;&gt;Save values&lt;\/ion-button&gt;\n\u00a0\u00a0&lt;ion-button (click)=&quot;testLoad()&quot; expand=&quot;full&quot;&gt;Load values&lt;\/ion-button&gt;\n\u00a0\u00a0&lt;ion-button routerLink=&quot;\/map&quot; expand=&quot;full&quot;&gt;Map&lt;\/ion-button&gt;\n\n\u00a0\u00a0&lt;ion-item *ngIf=&quot;user&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-avatar slot=&quot;start&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;img [src]=&quot;user.picture.thumbnail&quot; \/&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/ion-avatar&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-label&gt;\n      &lt;h2&gt;{{ user.name.first }} {{user.name.last}}&lt;\/h2&gt;\n      &lt;p&gt;{{ user.email }}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/ion-label&gt;\n\u00a0\u00a0&lt;\/ion-item&gt;\n&lt;\/ion-content&gt;<\/code><\/pre>\n\n\n\n<p>Try and trigger the background fetch!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh5.googleusercontent.com\/rZLl4MMss33szrj-vLcuXIWU0sfLnB4U_7N0unzZnsMcTifvD3v2SlFz4TJjexHH1DGDpjy4Hi4hR6T0Aj2ZnSknGVDsJE1mI6I4oiF9h2OvDjHcPBjEk6xPT-wLjWzkNgm8nr8ISWP8fxk8Q_i3So8\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/rZLl4MMss33szrj-vLcuXIWU0sfLnB4U_7N0unzZnsMcTifvD3v2SlFz4TJjexHH1DGDpjy4Hi4hR6T0Aj2ZnSknGVDsJE1mI6I4oiF9h2OvDjHcPBjEk6xPT-wLjWzkNgm8nr8ISWP8fxk8Q_i3So8\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>We have now successfully triggered a background task that fetches data and returns it to our app &#8211; a huge milestone! You can now also try to schedule a notification and see it appear on your device.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh3.googleusercontent.com\/AWYugLDjHis9f-0VvAspTmckihsJUcSPKJia4SZaIOIW5LglwEy4vhhCQgkMqLqIL8RkTkh0AvJXLrqGh7YNPdQTzvwFsYXBFVshI8rnPaLHdiCASN0yItx1v24R_iQqrSOmeOobMMwebXi3TQUEPa4\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/AWYugLDjHis9f-0VvAspTmckihsJUcSPKJia4SZaIOIW5LglwEy4vhhCQgkMqLqIL8RkTkh0AvJXLrqGh7YNPdQTzvwFsYXBFVshI8rnPaLHdiCASN0yItx1v24R_iQqrSOmeOobMMwebXi3TQUEPa4\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>All of this works flawlessly if you have configured everything correctly in the first step. But let&#8217;s take this another step further.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Adding Capacitor Google Maps<\/strong><\/h2>\n\n\n\n<p>We could now combine our background check-in with the <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/google-maps\">Capacitor Google Maps Plugin<\/a> to capture the geolocation, store it and later show it on a map!<\/p>\n\n\n\n<p>To do so, first install the plugin and create a new page:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">ionic g page map\nnpm install @capacitor\/google-maps<\/code><\/pre>\n\n\n\n<p>To configure the plugin you need to supply your Google Maps API key inside the <code>android\/app\/src\/main\/AndroidManifest.xml<\/code> like this:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-xml\">&lt;application ...&gt;\n  &lt;meta-data\n    android:name=&quot;com.google.android.geo.API_KEY&quot;\n    android:value=&quot;YOURAPIKEY&quot;\/&gt;\n&lt;\/application&gt;<\/code><\/pre>\n\n\n\n<p>For more information about the integration also <a href=\"https:\/\/ionicacademy.com\/capacitor-google-maps-plugin\/\">check out my Capacitor Maps tutorial on the Ionic Academy<\/a>! Now we can add two new functions to our runner file to save and load the check-ins:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">\/\/ Save a time and location object in the Capacitor KV store\naddEventListener(&#039;checkIn&#039;, async (resolve, reject, args) =&gt; {\n  try {\n    console.log(&#039;checkIn event fired&#039;);\n    const { value } = CapacitorKV.get(&#039;CHECKINS&#039;); \/\/ Gather some data\n    const time = new Date().getTime();\n    const location = await CapacitorGeolocation.getCurrentPosition(); \/\/ Create an array of checkins\n    let checkinArr = [{ location, time }]; \/\/ Try to append our data to the existing array\n    try {\n      const parsedArr = JSON.parse(value);\n      checkinArr = [...parsedArr, { location, time }];\n    } catch (e) {\n      console.log(&#039;no checkins&#039;);\n    }\n\n    console.log(checkinArr); \/\/ Save the array\n    CapacitorKV.set(&#039;CHECKINS&#039;, JSON.stringify(checkinArr));\n    console.log(&#039;checkin saved&#039;); \/\/ Resolve the event call\n    resolve();\n  } catch (err) {\n    console.error(err);\n    reject(err);\n  }\n});\n\n\/\/ Get all checkins from the Capacitor KV store\naddEventListener(&#039;loadCheckins&#039;, (resolve, reject, args) =&gt; {\n  try {\n    const { value } = CapacitorKV.get(&#039;CHECKINS&#039;);\n    try {\n      const arr = JSON.parse(value);\n      resolve(arr);\n    } catch (e) {\n      resolve([]);\n    }\n  } catch (err) {\n    console.error(err);\n    reject([]);\n  }\n});<\/code><\/pre>\n\n\n\n<p>We have previously defined in our Capacitor configuration that the checkIn event will be automatically scheduled when our app goes to the background &#8211; if you use different event names, make sure you update your config. To finish the maps implementation, bring up the <code>src\/app\/map\/map.module.ts<\/code> and&nbsp;include the <code>CUSTOM_ELEMENTS_SCHEMA<\/code><\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { NgModule } from &#039;@angular\/core&#039;;\nimport { CommonModule } from &#039;@angular\/common&#039;;\nimport { FormsModule } from &#039;@angular\/forms&#039;;\nimport { IonicModule } from &#039;@ionic\/angular&#039;;\nimport { MapPageRoutingModule } from &#039;.\/map-routing.module&#039;;\nimport { MapPage } from &#039;.\/map.page&#039;;\nimport { CUSTOM_ELEMENTS_SCHEMA } from &#039;@angular\/core&#039;;\n\n@NgModule({\n\u00a0\u00a0imports: [CommonModule, FormsModule, IonicModule, MapPageRoutingModule],\n\u00a0\u00a0declarations: [MapPage],\n\u00a0\u00a0schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class MapPageModule {}<\/code><\/pre>\n\n\n\n<p>Finally, sprinkle in some CSS inside the <code>src\/app\/map\/map.page.scss<\/code> to make the map view visible on native devices:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">capacitor-google-map {\n  \u00a0\u00a0display: inline-block;\n  \u00a0\u00a0width: 100%;\n  \u00a0\u00a0height: 400px;\n}\n\nion-content {\n  \u00a0\u00a0--background: none;\n}<\/code><\/pre>\n\n\n\n<p>Now we can use the map in our page and also display a list with the check-ins below it, so change your <code>src\/app\/map\/map.page.html<\/code> to:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-xml\">&lt;ion-header&gt;\n\u00a0\u00a0&lt;ion-toolbar&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-buttons slot=&quot;start&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;ion-back-button defaultHref=&quot;home&quot;&gt;&lt;\/ion-back-button&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/ion-buttons&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-title&gt;Map&lt;\/ion-title&gt;\n\u00a0\u00a0&lt;\/ion-toolbar&gt;\n&lt;\/ion-header&gt;\n\n&lt;ion-content&gt;\n\u00a0\u00a0&lt;ion-button (click)=&quot;loadCheckins()&quot; expand=&quot;full&quot;&gt;Load Checkins&lt;\/ion-button&gt;\n\u00a0\u00a0&lt;capacitor-google-map #map&gt;&lt;\/capacitor-google-map&gt;\n\u00a0\u00a0&lt;ion-list&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;ion-item *ngFor=&quot;let checkin of checkins&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;ion-label&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h2&gt;{{ checkin.location?.longitude }} - {{ checkin.location?.latitude }}&lt;\/h2&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;p&gt;{{ checkin.time | date:&#039;medium&#039; }}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/ion-label&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/ion-item&gt;\n\u00a0\u00a0&lt;\/ion-list&gt;\n&lt;\/ion-content&gt;<\/code><\/pre>\n\n\n\n<p>Finally in the <code>src\/app\/map\/map.page.ts<\/code> we need to initialize the map and then load the check-ins from the background runner using <code>dispatchEvent()<\/code> again.<\/p>\n\n\n\n<p>When we have the data, we can add markers to the map and display them:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-typescript\">import { AfterViewInit, Component, ElementRef, ViewChild } from &#039;@angular\/core&#039;;\nimport { BackgroundRunner } from &#039;@capacitor\/background-runner&#039;;\nimport { GoogleMap, Marker } from &#039;@capacitor\/google-maps&#039;;\n\n@Component({\n  selector: &#039;app-map&#039;,\n  templateUrl: &#039;.\/map.page.html&#039;,\n  styleUrls: [&#039;.\/map.page.scss&#039;],\n})\nexport class MapPage implements AfterViewInit {\n  @ViewChild(&#039;map&#039;) mapRef!: ElementRef&lt;HTMLElement&gt;;\n  map!: GoogleMap;\n  checkins: any[] = [];\n\n  constructor() {}\n  ngAfterViewInit() {\n    this.createMap();\n  }\n\n  async createMap() {\n    this.map = await GoogleMap.create({\n      id: &#039;my-cool-map&#039;,\n      element: this.mapRef.nativeElement,\n      apiKey: &#039;YOURAPIKEY&#039;,\n      config: {\n        center: {\n          lat: 51.88,\n          lng: 7.6,\n        },\n        zoom: 8,\n      },\n    });\n  }\n\n  loadCheckins = async () =&gt; {\n    const result = (await BackgroundRunner.dispatchEvent({\n      label: &#039;com.capacitor.background.check&#039;,\n      event: &#039;loadCheckins&#039;,\n      details: {},\n    })) as any;\n\n    if (result) {\n      this.checkins = [];\n      Object.keys(result).forEach((key) =&gt; {\n        this.checkins.push(result[key]);\n      });\n      this.addMarkers();\n    }\n  };\n\n  async addMarkers() {\n    if (this.checkins.length === 0) {\n      return;\n    }\n\n    const markers: Marker[] = this.checkins.map((item) =&gt; {\n      return {\n        coordinate: {\n          lat: item.location.latitude,\n          lng: item.location.longitude,\n        },\n        title: item.time,\n      };\n    });\n    await this.map.addMarkers(markers);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Once your background task has run, you should see the markers on the map!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh4.googleusercontent.com\/HMQqtrEcpdjPUwIqOdUQUvsLo-njzEauGe6VEVPHNDvQIcEjdh6c_Xx7q1P6vdmoIw3pF0yWyT2HYjumShC4epzFIndoCVVTCuRpH4qsPmVyBkXeVTQ3ZAtS0c4QcNA7aby-SOhoG7Cvj1KflWdrrnw\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/HMQqtrEcpdjPUwIqOdUQUvsLo-njzEauGe6VEVPHNDvQIcEjdh6c_Xx7q1P6vdmoIw3pF0yWyT2HYjumShC4epzFIndoCVVTCuRpH4qsPmVyBkXeVTQ3ZAtS0c4QcNA7aby-SOhoG7Cvj1KflWdrrnw\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>But what if it&#8217;s not running and you don&#8217;t want to wait until it&#8217;s executed?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Debug and Trigger Background Tasks<\/strong><\/h2>\n\n\n\n<p>For iOS, there is a handy trick to manually trigger your background tasks.<\/p>\n\n\n\n<p>First, we will add a random print statement to the <code>BackgroundRunner<\/code> file in our pods target after the <code>BGTaskScheduler.shared.submit()<\/code> call.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh4.googleusercontent.com\/wlg9r3RKUOzq66thobq5zNfqKtqhWmFlxp_5ZnVWXq8LMu47aVqbX9PmFh1zwoS3SZ34z7DGr7qNAtcYr9IebCHL7guuWKkl8g_fRjNOrTF2nPx29TU938EKXHHVJsaClF4mbNC-Q0cCUaH_dLft_Vk\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/wlg9r3RKUOzq66thobq5zNfqKtqhWmFlxp_5ZnVWXq8LMu47aVqbX9PmFh1zwoS3SZ34z7DGr7qNAtcYr9IebCHL7guuWKkl8g_fRjNOrTF2nPx29TU938EKXHHVJsaClF4mbNC-Q0cCUaH_dLft_Vk\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>Set a breakpoint to the left of that line of code, run your app, and slide it to the background &#8211; your breakpoint will be triggered.<\/p>\n\n\n\n<p>Now you can run the following command in the log window where you see (lldb):<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-shell\">e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@&quot;com.academy.runner.check&quot;]<\/code><\/pre>\n\n\n\n<p>Replace the identifier with your own and hit enter.<\/p>\n\n\n\n<p>This causes iOS to schedule and run your background task when the app continues, so let the app continue and you should see a log from your runner.<\/p>\n\n\n\n<p>If you bring up the app again, you should also see the check-ins on the map!<\/p>\n\n\n\n<p>Apparently, the only debugging option for Android I found was to use the App Inspector view in Android Studio, from which you can at least get a glimpse of your background job:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" data-src=\"https:\/\/lh3.googleusercontent.com\/kUrx_74EzJabJpFxGW1dIeY0JgGgxt7P71h9jAJYgdnxMpGdm5hhQPjWP-T0KJq-hqNqfkrfNWRCj3nBdtQ0p2vgdgoyDOzR455352Y9kH3i370B3o4Ag7MU6oMTUZeuMmvVU519FdYFEZV0oQspbBc\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/kUrx_74EzJabJpFxGW1dIeY0JgGgxt7P71h9jAJYgdnxMpGdm5hhQPjWP-T0KJq-hqNqfkrfNWRCj3nBdtQ0p2vgdgoyDOzR455352Y9kH3i370B3o4Ag7MU6oMTUZeuMmvVU519FdYFEZV0oQspbBc\" alt=\"\"\/><\/noscript><\/figure>\n\n\n\n<p>If you find a way to directly trigger the Android background task, let me know!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Recap<\/strong><\/h2>\n\n\n\n<p>In this tutorial we have learned how to use the new <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/background-runner\">Capacitor Background Runner<\/a> plugin to perform tasks in the background, like fetching data, sending notifications, or even getting the user&#8217;s geolocation.<\/p>\n\n\n\n<p>We have access to a limited set of APIs already, but we need to make sure we request the permissions upfront and configure our native apps correctly. To see all of them in action, also check out the official <a href=\"https:\/\/github.com\/ionic-team\/capacitor-background-runner\/tree\/main\">Capacitor Background Runner demo app<\/a>!<\/p>\n\n\n\n<p>Keep in mind the <a href=\"https:\/\/capacitorjs.com\/docs\/apis\/background-runner#limitations-of-background-tasks\">limitations of background tasks<\/a> which are quite heavily restricted on both iOS and Android. But if you act within the boundaries of the operating systems, adding background tasks to your Ionic app with Capacitor is now possible and right at your fingertips!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What happens when users put your mobile app in the background? Can you still occasionally tap into the device\u2019s resources to perform tasks? The answer is yes, and Capacitor makes it easy to do so now with the new Capacitor Background Runner.<\/p>\n","protected":false},"author":11,"featured_media":5655,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"","publish_post_category":"","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"","discourse_permalink":"","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,124],"tags":[275,151,179],"class_list":["post-5653","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all","category-tutorials","tag-background-tasks","tag-capacitor","tag-native"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Create Background Tasks in Ionic with Capacitor - Ionic Blog<\/title>\n<meta name=\"description\" content=\"When users put your app in the background, they can tap into the device\u2019s resources &amp; perform tasks with the new Capacitor Background Runner.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Create Background Tasks in Ionic with Capacitor\" \/>\n<meta property=\"og:description\" content=\"When users put your app in the background, they can tap into the device\u2019s resources &amp; perform tasks with the new Capacitor Background Runner.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-04T19:53:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-10-05T16:50:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2240\" \/>\n\t<meta property=\"og:image:height\" content=\"1120\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Simon Grimm\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@schlimmson\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Simon Grimm\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\"},\"author\":{\"name\":\"Simon Grimm\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\"},\"headline\":\"How to Create Background Tasks in Ionic with Capacitor\",\"datePublished\":\"2023-10-04T19:53:49+00:00\",\"dateModified\":\"2023-10-05T16:50:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\"},\"wordCount\":1570,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png\",\"keywords\":[\"Background Tasks\",\"Capacitor\",\"native\"],\"articleSection\":[\"All\",\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\",\"url\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\",\"name\":\"How to Create Background Tasks in Ionic with Capacitor - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png\",\"datePublished\":\"2023-10-04T19:53:49+00:00\",\"dateModified\":\"2023-10-05T16:50:05+00:00\",\"description\":\"When users put your app in the background, they can tap into the device\u2019s resources & perform tasks with the new Capacitor Background Runner.\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png\",\"width\":2240,\"height\":1120},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Create Background Tasks in Ionic with Capacitor\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\",\"name\":\"Simon Grimm\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"caption\":\"Simon Grimm\"},\"sameAs\":[\"https:\/\/x.com\/schlimmson\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/schlimmson\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Create Background Tasks in Ionic with Capacitor - Ionic Blog","description":"When users put your app in the background, they can tap into the device\u2019s resources & perform tasks with the new Capacitor Background Runner.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor","og_locale":"en_US","og_type":"article","og_title":"How to Create Background Tasks in Ionic with Capacitor","og_description":"When users put your app in the background, they can tap into the device\u2019s resources & perform tasks with the new Capacitor Background Runner.","og_url":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor","og_site_name":"Ionic Blog","article_published_time":"2023-10-04T19:53:49+00:00","article_modified_time":"2023-10-05T16:50:05+00:00","og_image":[{"width":2240,"height":1120,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","type":"image\/png"}],"author":"Simon Grimm","twitter_card":"summary_large_image","twitter_creator":"@schlimmson","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Simon Grimm","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor"},"author":{"name":"Simon Grimm","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6"},"headline":"How to Create Background Tasks in Ionic with Capacitor","datePublished":"2023-10-04T19:53:49+00:00","dateModified":"2023-10-05T16:50:05+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor"},"wordCount":1570,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","keywords":["Background Tasks","Capacitor","native"],"articleSection":["All","Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor","url":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor","name":"How to Create Background Tasks in Ionic with Capacitor - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","datePublished":"2023-10-04T19:53:49+00:00","dateModified":"2023-10-05T16:50:05+00:00","description":"When users put your app in the background, they can tap into the device\u2019s resources & perform tasks with the new Capacitor Background Runner.","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","width":2240,"height":1120},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/create-background-tasks-in-ionic-with-capacitor#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"How to Create Background Tasks in Ionic with Capacitor"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6","name":"Simon Grimm","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","caption":"Simon Grimm"},"sameAs":["https:\/\/x.com\/schlimmson"],"url":"https:\/\/ionic.io\/blog\/author\/schlimmson"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2023\/10\/cap-bg-tasks-feature-image.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5653","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=5653"}],"version-history":[{"count":4,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5653\/revisions"}],"predecessor-version":[{"id":5659,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/5653\/revisions\/5659"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/5655"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=5653"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=5653"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=5653"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}