Google login in Ionic Capacitor app with Angular
Tags: ionic, angular, sociallogin, capacitor
Published: 2021-08-22 16:32:19

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full is-withAccentColors" lang="en"><div class="postArticle-content js-postField js-notesSource editable" id="editor_7" g_editable="true" role="textbox" contenteditable="false" data-default-value="Title
Tell your story…"><section name="0543" class="section section--body section--first"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="9ba7" class="graf graf--p graf-after--figure">In this post, you’ll learn how to implement <strong class="markup--strong markup--p-strong">Google login</strong> in your Ionic Angular Capacitor apps. We will also retrieve user name and profile photo to show after login. <strong class="markup--strong markup--p-strong">We will test the authentication on Web, Android and iOS.</strong></p><p name="0704" class="graf graf--p graf-after--p">Since Google login is applicable in a lot of app frameworks, it is possible you landed here by (SEO) mistake. If you are looking for Google login in</p><ul class="postList"><li name="c030" class="graf graf--li graf-after--p">Ionic Angular (Cordova) apps —&hairsp;Please check <a href="https://enappd.com/blog/google-login-in-ionic-4-apps-using-firebase/39"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener"    target="_blank">this post</a></li><li name="6065" class="graf graf--li graf-after--li">React Native&hairsp;—&hairsp;Please check this for <a href="https://enappd.com/blog/google-login-in-react-native-android-apps-with-firebase/90"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener"    target="_blank">Android</a> and <a href="https://enappd.com/blog/google-login-in-react-native-apps-with-firebase/88"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener"    target="_blank">iOS</a></li><li name="0b2b" class="graf graf--li graf-after--li">Ionic React Capacitor Apps —Check <a href="https://enappd.com/blog/google-login-in-ionic-react-capacitor-apps/122"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">this post</a></li><li name="f183" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Ionic Angular Capacitor Apps&hairsp;—&hairsp;Continue reading 🙂</strong></li></ul><p name="6fd4" class="graf graf--p graf-after--li">As you can see from above, there are several options available for Hybrid app development these days, and it is easy to get confused between them. This post is focussed on <strong class="markup--strong markup--p-strong">Ionic framework</strong> with <strong class="markup--strong markup--p-strong">Angular</strong> as the front-end framework, and <a href="https://capacitor.ionicframework.com/docs/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener"    target="_blank"><strong class="markup--strong markup--p-strong">Capacitor</strong></a> as runtime and build environment.</p><p name="8e99" class="graf graf--p graf-after--p">Let’s see a brief intro to each of the included frameworks:</p><ol class="postList"><li name="4e6f" class="graf graf--li graf-after--p">Ionic</li><li name="5d7b" class="graf graf--li graf-after--li">Capacitor</li></ol><h3 name="f662" class="graf graf--h3 graf-after--li">What is Ionic&nbsp;?</h3><p name="9946" class="graf graf--p graf-after--h3">In short&hairsp;—&hairsp;If you create Native apps in Android, you code in Java/Kotlin. If you create Native apps in iOS, you code in Obj-C or Swift. Both of these are powerful but complex languages. <strong class="markup--strong markup--p-strong">With Ionic and Capacitor you can write a single piece of code for your app that can run on both iOS and Android </strong>(and web!), that too with the simplicity of HTML, CSS, and JS.</p><p name="0ffe" class="graf graf--p graf-after--p">It is important to note the contribution of Capacitor in this. Ionic is a UI + functionality wrapper made up of HTML, CSS and JS. So, by default, Ionic cannot run as an app in an iOS or Android device. Capacitor is the build environment that containerizes (sort of) this Ionic web app and converts it into a device installable app, along with providing this app access to native APIs like Camera etc.</p><h3 name="bf63" class="graf graf--h3 graf-after--p">Capacitor&hairsp;—&hairsp;How is it different from Cordova&nbsp;?</h3><blockquote name="3e4b" class="graf graf--blockquote graf-after--h3"><strong class="markup--strong markup--blockquote-strong"><em class="markup--em markup--blockquote-em">Capacitor is very similar to Cordova, but with some key differences in the app workflow</em></strong></blockquote><p name="d0bf" class="graf graf--p graf-after--blockquote">You might be familiar with the popular hybrid technology Cordova. So why are we using Capacitor? Cordova helps build Ionic web app into a device installable app. But there are some limitations of Cordova, which Capacitor tries to overcome with a new App workflow.</p><p name="2f1f" class="graf graf--p graf-after--p">Capacitor is a cross-platform app runtime that makes it easy to build web apps that run natively on iOS, Android, Electron, <em class="markup--em markup--p-em">and</em> the web. Ionic people call these apps “Native Progressive Web Apps” and they represent the next evolution beyond Hybrid apps.</p><p name="8326" class="graf graf--p graf-after--p">Here are few differences between Cordova and Capacitor</p><ol class="postList"><li name="2554" class="graf graf--li graf-after--p">Capacitor considers each platform project a <em class="markup--em markup--li-em">source asset</em> instead of a <em class="markup--em markup--li-em">build time asset</em>. That means, Capacitor wants you to keep the platform source code in the repository, unlike Cordova which always assumes that you will generate the platform code on build time</li><li name="573f" class="graf graf--li graf-after--li">Since platform code is a <em class="markup--em markup--li-em">source asset, </em>you can directly change the native code using Xcode or Android Studio. This give more flexibility to developers. We will do some similar changes for Google login as well.</li><li name="1503" class="graf graf--li graf-after--li">Capacitor has great PWA support in-built</li><li name="ad37" class="graf graf--li graf-after--li">Capacitor CLI is locally installed, so different apps can have different Capacitor versions in your system</li></ol><p name="ba3a" class="graf graf--p graf-after--li">You can read more about Capacitor vs Cordova in <a href="https://ionic.io/resources/articles/capacitor-vs-cordova-modern-hybrid-app-development"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">this article by Ionic</a>.</p><h3 name="9ad4" class="graf graf--h3 graf-after--p">Plugins</h3><p name="c062" class="graf graf--p graf-after--h3">Capacitor has its own set of plugins available in the core itself, or with @capacitor-community, but it can also support Cordova plugins. For Google login functionality, we’ll use the <a href="https://github.com/CodetrixStudio/CapacitorGoogleAuth"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">CapacitorGoogleAuth</a> plugin by <a href="https://github.com/CodetrixStudio"  class="markup--anchor markup--p-anchor" rel="author noopener noopener"    target="_blank">CodetrixStudio</a>.</p><p name="cd38" class="graf graf--p graf-after--p">Capacitor plugins require a bit of configuration editing in Android and iOS files, but you don’t need any Android and iOS native expertise for that. Just follow along with the tutorial and you’ll find it very easy to implement Google login in Capacitor.</p><h3 name="ae4d" class="graf graf--h3 graf-after--p">A word on Google authentication</h3><p name="136c" class="graf graf--p graf-after--h3">We will use the <a href="https://github.com/CodetrixStudio/CapacitorGoogleAuth"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">CapacitorGoogleAuth</a> plugin by <a href="https://github.com/CodetrixStudio"  class="markup--anchor markup--p-anchor" rel="author noopener noopener noopener"    target="_blank">CodetrixStudio</a> to authenticate the user. Once the login is done, we receive user profile information in auth response itself. Hence, there is no need to fetch user’s profile information separately.</p><p name="642f" class="graf graf--p graf-after--p">This Google Auth plugin supports 2 functions, across web, Android and iOS</p><ul class="postList"><li name="bae5" class="graf graf--li graf-after--p">Login</li><li name="0dd9" class="graf graf--li graf-after--li">Logout</li></ul><p name="7422" class="graf graf--p graf-after--li">Also note that this plugin only helps you to login and logout using Google Auth. As you’ll see, the process of Google login involves creating a Firebase project etc. but this plugin does not connect your authenticated user directly to Firebase project.</p><p name="6d48" class="graf graf--p graf-after--p">In other words, there are two ways you can use Google login</p><ul class="postList"><li name="1257" class="graf graf--li graf-after--p">Confirm user’s authenticity from Google login, and then save the user info in your own Database. This is true if you already have a server and DB defined for your project</li><li name="66b4" class="graf graf--li graf-after--li">Confirm user’s authenticity from Google login, and then save user info in the same Firebase project itself. It is a convenient and faster way. More about this in <strong class="markup--strong markup--li-strong">Step 2 and further</strong></li></ul><h3 name="4668" class="graf graf--h3 graf-after--li">Structure of&nbsp;post</h3><p name="f65f" class="graf graf--p graf-after--h3">I always go step-by-step for readers of all experience level. If you know certain steps, feel free to skip them</p><p name="4f21" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 1:</strong> Create a basic Ionic Angular Capacitor app</p><p name="754b" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 2</strong>: Create a Google project for authentication</p><p name="94aa" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 3: </strong>Setup Google Login Plugin and functions</p><p name="9d98" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 4</strong>: Prepare and Test on Web</p><p name="997b" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 5: </strong>Build and Test your app on Android</p><p name="73cf" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">Step 6: </strong>Build and Test your app on iOS</p><p name="0bee" class="graf graf--p graf-after--p">Let’s get started with Ionic Angular Capacitor Google login&nbsp;!</p><h3 name="2ee4" class="graf graf--h3 graf-after--p">Step 1&hairsp;—&hairsp;Create a basic Ionic Angular Capacitor app</h3><p name="28fe" class="graf graf--p graf-after--h3">Here’s my environment</p><ul class="postList"><li name="58e4" class="graf graf--li graf-after--p">Node 14.x+</li><li name="f159" class="graf graf--li graf-after--li">Capacitor 3.0+</li><li name="3912" class="graf graf--li graf-after--li">Angular 12+</li><li name="d1cc" class="graf graf--li graf-after--li">NPM 7+</li></ul><p name="34a7" class="graf graf--p graf-after--li">First you need to make sure you have the latest Ionic CLI. This will ensure you are using everything latest. Ensure latest Ionic CLI installation using</p><pre name="2f4c" class="graf graf--pre graf-after--p">$ npm install -g ionic@latest</pre><p name="2020" class="graf graf--p graf-after--pre">Creating a basic Ionic-React app is not much different or difficult from creating a basic Ionic-Angular app. Start a basic <code class="markup--code markup--p-code">blank</code> starter using</p><pre name="e49e" class="graf graf--pre graf-after--p">$ ionic start IonNgCapGoogleLogin blank --type=angular --capacitor</pre><p name="6308" class="graf graf--p graf-after--pre">The CLI options are pretty self-explanatory.</p><p name="a3cb" class="graf graf--p graf-after--p">Run the app in browser using</p><pre name="706d" class="graf graf--pre graf-after--p">$ ionic serve</pre><p name="8a9b" class="graf graf--p graf-after--pre">You won’t see much in the homepage created in the blank starter. Let’s modify this page to include a button, icon and a title for login. Also, I have created a LandingPage, where the user is redirected after successful login. The user profile information in this page comes after login and single API call.</p><figure tabindex="0" contenteditable="false" name="cb2c" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 606px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 86.6%;"></div><img class="graf-image" data-image-id="1*PYiW0eD5KiRZQoCeXwRUoA.png" data-width="850" data-height="736" alt="Login and Home page for Ionic Angular Capacitor Google Login demo app" src="https://cdn-images-1.medium.com/max/800/1*PYiW0eD5KiRZQoCeXwRUoA.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Login and Home page for Ionic Angular Capacitor Google Login demo&nbsp;app</figcaption><br></figure><h4 name="4392" class="graf graf--h4 graf-after--figure">Attach Capacitor to existing&nbsp;app</h4><blockquote name="0a11" class="graf graf--blockquote graf-after--h4"><strong class="markup--strong markup--blockquote-strong">Note</strong>: Unlike earlier, now you don’t have to attach Capacitor separately to your Ionic apps. When you run the <code class="markup--code markup--blockquote-code"><em class="markup--em markup--blockquote-em">ionic start</em></code> command with <code class="markup--code markup--blockquote-code"><em class="markup--em markup--blockquote-em">--Capacitor</em></code> option, it attaches Capacitor to the app automatically.</blockquote><p name="8a95" class="graf graf--p graf-after--blockquote">If by change you forgot to attach Capacitor which creating the app, it can be attached to an existing Ionic app as well. To attach Capacitor to your existing Ionic app, run</p><pre name="8f7b" class="graf graf--pre graf-after--p">$ ionic integrations enable capacitor</pre><p name="9edc" class="graf graf--p graf-after--pre">This will attach Capacitor to your Ionic app. After this, you have to <code class="markup--code markup--p-code">init</code> the Capacitor app with</p><pre name="9893" class="graf graf--pre graf-after--p">$ npx cap init</pre><p name="4e5f" class="graf graf--p graf-after--pre">It will ask you the app name and ID. Give app name whatever you want. App ID is the domain identifier of your app (ex: <code class="markup--code markup--p-code">com.example.app</code>). Note this ID as this will be required later when you create app in Google developer console. In my case, the ID is <code class="markup--code markup--p-code">com.enappd.IonNgCapGoogleLogin</code> ( too long, I know)</p><h3 name="84df" class="graf graf--h3 graf-after--p">Step 2&hairsp;—&hairsp;Create a Google&nbsp;project</h3><p name="88f2" class="graf graf--p graf-after--h3">To implement a Google login, you will need a Google app/project. A Google project can serve as a single point of control for your Google login, analytics, AdMob, push notifications, API keys for Map and several other services etc.</p><h4 name="631c" class="graf graf--h4 graf-after--p">2.1 Create new&nbsp;project</h4><p name="322a" class="graf graf--p graf-after--h4">Create a project in <a href="https://console.cloud.google.com/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener"    target="_blank">Google Developer console</a> or create it in <a href="https://console.firebase.google.com/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener"    target="_blank">Firebase Console</a> (recommended). Both consoles are essentially integrated with each other.<br><strong class="markup--strong markup--p-strong">More details about creating a Firebase project can be found </strong><a href="https://enappd.com/blog/how-to-integrate-firebase-in-ionic-4-apps/23"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener"    target="_blank"><strong class="markup--strong markup--p-strong">here</strong></a><strong class="markup--strong markup--p-strong">.</strong></p><figure tabindex="0" contenteditable="false" name="e0d3" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 657px; max-height: 450px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 68.5%;"></div><img class="graf-image" data-image-id="0*YQGvGRldPI-aamrK.png" data-width="657" data-height="450" src="https://cdn-images-1.medium.com/max/800/0*YQGvGRldPI-aamrK.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Create a project in <a href="https://console.cloud.google.com/"  class="markup--anchor markup--figure-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Google Developer console</a></figcaption><br></figure><h4 name="6923" class="graf graf--h4 graf-after--figure">2.2 Requirements for different project&nbsp;types</h4><h4 name="d106" class="graf graf--h4 graf-after--h4">Web</h4><p name="e504" class="graf graf--p graf-after--h4">As soon as you make a Google project in either Google Developer console or Firebase console, a <code class="markup--code markup--p-code">web-client-ID</code> is automatically generated. For web-login, you only need this <code class="markup--code markup--p-code">web-client-ID</code></p><p name="cc14" class="graf graf--p graf-after--p">More in Step 2.4 and Step 4.</p><h4 name="180f" class="graf graf--h4 graf-after--p">Android</h4><p name="c1fa" class="graf graf--p graf-after--h4">To implement Google Login in Android, we will have to create an Android app inside our Google project. In this Android app’s settings, we’ll get <code class="markup--code markup--p-code"><em class="markup--em markup--p-em">google-services.json</em></code> file. This files essentially contains the API keys and IDs for the project.</p><p name="107c" class="graf graf--p graf-after--p">We’ll also have to attach SHA-1 key from our build system in our Google project’s Android app.</p><p name="5dc9" class="graf graf--p graf-after--p">More in Step 5.</p><p name="de47" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">iOS</strong></p><p name="2385" class="graf graf--p graf-after--p">To implement Google Login in iOS, we will have to create an iOS app inside our Google project. In this iOS app’s settings, we’ll get a<code class="markup--code markup--p-code">google-services.plist</code> file&nbsp;. This file essentially contains the API keys and IDs for the project.</p><p name="6556" class="graf graf--p graf-after--p">For iOS we’ll also have to generate a URL scheme. More in Step 6.</p><h4 name="0870" class="graf graf--h4 graf-after--p">2.3 Google-services.<code class="markup--code markup--h4-code">plist</code></h4><p name="ed1a" class="graf graf--p graf-after--h4">In your Firebase console (of the same project), create a new iOS app. During creation process it will ask you the app bundle ID. Use the bundle ID you used to initialize Capacitor in section 2 (<code class="markup--code markup--p-code">com.enappd.IonNgCapGoogleLogin</code>). In next step, download the <code class="markup--code markup--p-code">google-services.plist</code> file.</p><p name="ff2f" class="graf graf--p graf-after--p">If you already have an existing project, download the <code class="markup--code markup--p-code">google-services.plist</code> from the Project Settings page.</p><figure tabindex="0" contenteditable="false" name="a0cf" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 326px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 46.6%;"></div><img class="graf-image" data-image-id="0*lZ7fseWFMvnzLt-g.png" data-width="700" data-height="326" alt="Download google-services.plist from your Firebase iOS project" src="https://cdn-images-1.medium.com/max/800/0*lZ7fseWFMvnzLt-g.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Download <code class="markup--code markup--figure-code">google-services.plist from your Firebase iOS&nbsp;project</code></figcaption><br></figure><h4 name="c022" class="graf graf--h4 graf-after--figure">2.4 Web-client ID</h4><p name="74eb" class="graf graf--p graf-after--h4">When you create a Google project, a <code class="markup--code markup--p-code">web client ID</code> is automatically created. You can find this web-client ID in Google Developer console. Note that the web client ID says (Auto created by Google Service). You DO NOT need to create an Android or iOS app in the Google Project to create this web client ID.</p><figure tabindex="0" contenteditable="false" name="9894" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 261px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 37.3%;"></div><img class="graf-image" data-image-id="0*YcVI_o1pQjG7fJWT.png" data-width="700" data-height="261" alt="Client IDs in Google Developer Console." src="https://cdn-images-1.medium.com/max/800/0*YcVI_o1pQjG7fJWT.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Client IDs in Google Developer Console.</figcaption><br></figure><blockquote name="b2c7" class="graf graf--blockquote graf-after--figure"><em class="markup--em markup--blockquote-em">If you create Android/iOS app in Firebase, you can get web-client ID from the downloaded </em><code class="markup--code markup--blockquote-code"><em class="markup--em markup--blockquote-em">google-services.json</em></code><em class="markup--em markup--blockquote-em"> or </em><code class="markup--code markup--blockquote-code">google-services.plist</code><em class="markup--em markup--blockquote-em">file.</em></blockquote><p name="830d" class="graf graf--p graf-after--blockquote">To use web-client ID on <code class="markup--code markup--p-code">ionic serve</code> or on your website for web login, you need to make sure you include the origin URL in the Web Client ID’s settings</p><figure tabindex="0" contenteditable="false" name="9943" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 662px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 94.6%;"></div><img class="graf-image" data-image-id="1*66SENLYhB5TVugyJ_c_ffg.png" data-width="902" data-height="853" alt="Add Javascript origins to this list to enable login on web platforms" src="https://cdn-images-1.medium.com/max/800/1*66SENLYhB5TVugyJ_c_ffg.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Add Javascript origins to this list to enable login on web platforms</figcaption><br></figure><h4 name="4482" class="graf graf--h4 graf-after--figure">2.5 Web API&nbsp;Key</h4><p name="ba9e" class="graf graf--p graf-after--h4">Required only for making a REST API call to get user profile info. Web API Key can be obtained from the Firebase console. It appears after you have at least once entered the Authentication module of Firebase console.</p><figure tabindex="0" contenteditable="false" name="6e3c" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 464px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 66.3%;"></div><img class="graf-image" data-image-id="1*VKMG9xnfzsWoWfgCOehnEw.png" data-width="1043" data-height="692" src="https://cdn-images-1.medium.com/max/800/1*VKMG9xnfzsWoWfgCOehnEw.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Obtain Web API key from Firebase&nbsp;console</figcaption><br></figure><h4 name="fa6d" class="graf graf--h4 graf-after--figure">2.6 SHA-1&nbsp;key</h4><p name="6d21" class="graf graf--p graf-after--h4">For web implementation of Google login, nothing is required in our Google project. But for Android implementation, we need to add Android app in the project. Also, make sure the app ID (com.something.something) you provide when making the Android app in Google project, is the same as your app ID. (Double check in <code class="markup--code markup--p-code">capacitor.config.json</code> and <code class="markup--code markup--p-code">capacitor.config.ts</code> )</p><figure tabindex="0" contenteditable="false" name="823f" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 301px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 43%;"></div><img class="graf-image" data-image-id="1*Un2kJmK2J2K9eZef057BMQ.png" data-width="1494" data-height="643" alt="Add an Android app in Google Project (Firebase Console)" src="https://cdn-images-1.medium.com/max/800/1*Un2kJmK2J2K9eZef057BMQ.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Add an Android app in Google Project (Firebase Console)</figcaption><br></figure><p name="a156" class="graf graf--p graf-after--figure">Now create a SHA-1 key of your system. This key is specific to</p><ul class="postList"><li name="436a" class="graf graf--li graf-after--p">Your system (laptop/PC)</li><li name="fe18" class="graf graf--li graf-after--li">Your app’s&nbsp;<code class="markup--code markup--li-code">.keystore</code> file</li></ul><p name="bdf8" class="graf graf--p graf-after--li">Use following commands to generate SHA-1 key</p><pre name="7710" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">$ keytool -list -v -keystore &lt;&lt;YOUR_APP_KEYSTORE_PATH&gt;&gt; -alias &lt;&lt;KEYSTORE_ALIAS&gt;&gt; -storepass &lt;&lt;PASSWORD&gt;&gt; -keypass &lt;&lt;KEY_PASSWORD&gt;&gt;</code></pre><p name="8161" class="graf graf--p graf-after--pre">All the above info (alias, keystore, passwords) should be same as the one you used when creating the Keystore file.</p><p name="ad1d" class="graf graf--p graf-after--p">Add this SHA-1 key in Android App setting of your Google project</p><figure tabindex="0" contenteditable="false" name="8567" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 442px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63.2%;"></div><img class="graf-image" data-image-id="1*PgR3knzGSAOp-0WROxVf4Q.png" data-width="1022" data-height="646" alt="Add SHA-1 key in your Google Project’s Android App" src="https://cdn-images-1.medium.com/max/800/1*PgR3knzGSAOp-0WROxVf4Q.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Add SHA-1 key in your Google Project’s Android&nbsp;App</figcaption><br></figure><h3 name="21d1" class="graf graf--h3 graf-after--figure">Step 3&hairsp;—&hairsp;Setup Google Login Plugin and functions</h3><p name="41fe" class="graf graf--p graf-after--h3">To setup Google login in the app, we’ll do following things</p><p name="097d" class="graf graf--p graf-after--p">4.1 Install <a href="https://github.com/CodetrixStudio/CapacitorGoogleAuth"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">CapacitorGoogleAuth</a> plugin by <a href="https://github.com/CodetrixStudio"  class="markup--anchor markup--p-anchor" rel="author noopener noopener noopener"    target="_blank">CodetrixStudio</a>.</p><p name="55fd" class="graf graf--p graf-after--p">4.2 Setup plugin functions for login</p><p name="ae08" class="graf graf--p graf-after--p">4.3 Navigate and Send data between two pages of the app</p><p name="418f" class="graf graf--p graf-after--p">4.4 Sign Out</p><p name="731c" class="graf graf--p graf-after--p">4.5 Detect already logged in users</p><h4 name="0b3b" class="graf graf--h4 graf-after--p">4.1 Install Capacitor Google Auth&nbsp;plugin</h4><p name="1294" class="graf graf--p graf-after--h4">Install the plugin using</p><pre name="e91d" class="graf graf--pre graf-after--p">$ npm i --save @codetrix-studio/capacitor-google-auth</pre><p name="5d96" class="graf graf--p graf-after--pre">Add the following info in your <code class="markup--code markup--p-code">capacitor.config.json</code></p><blockquote name="badd" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Note</strong>: Capacitor 3.0+ uses <code class="markup--code markup--blockquote-code">capacitor.config.ts</code> by default. You’ll have to create the <code class="markup--code markup--blockquote-code">capacitor.config.json</code> in root folder, and copy the content from the&nbsp;<code class="markup--code markup--blockquote-code">.ts</code> filem and add the following info. This is plugin specific</blockquote><pre name="9838" class="graf graf--pre graf-after--blockquote">...<br>"plugins": {<br> "GoogleAuth": {<br>  "scopes": ["profile","email"],<br>  "serverClientId": "160012889513-qkxxxxxxxxxxxxxxxxxxxxxxxxkgubrp5ve.apps.googleusercontent.com"<br>}<br>}<br>...</pre><p name="1271" class="graf graf--p graf-after--pre"><code class="markup--code markup--p-code">serverClientId</code> is basically the web-client ID itself. Import the plugin in app’s pages using</p><pre name="8350" class="graf graf--pre graf-after--p">import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth';</pre><h4 name="c780" class="graf graf--h4 graf-after--pre">4.2 Setup plugin functions for&nbsp;login</h4><p name="9480" class="graf graf--p graf-after--h4">We have to setup few functions for Google Auth functionality</p><ol class="postList"><li name="bc2c" class="graf graf--li graf-after--p"><strong class="markup--strong markup--li-strong">init</strong>&hairsp;—&hairsp;GoogleAuth.init()&hairsp;—&hairsp;Initializes the plugin, required only in Web. This can be called at the page load. Avoid on device, or it will throw error.</li><li name="775c" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">signIn</strong>—GoogleAuth.signIn()&hairsp;—&hairsp;Signs you in with a popup on web, and native functionality in device. This should be called after init().&nbsp;<br>The success of this function will given user profile data as response. Based on this response you can navigate user in your app.</li><li name="ab88" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">signOut</strong>&hairsp;—&hairsp;GoogleAuth.signOut()&hairsp;—&hairsp;Signs you out from Google.&nbsp;<br>Based on success of this method, you can navigate user out of your app.</li><li name="3447" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">refresh</strong>&hairsp;—&hairsp;GoogleAuth.refresh()&hairsp;—&hairsp;At app start (or at any point), it can check if you are already logged in. This can be helpful if you want to auto-login users who have logged in once.</li></ol><p name="875e" class="graf graf--p graf-after--li">I believe you can handle the HTML and CSS part of the pages yourself. The login code for <code class="markup--code markup--p-code">Home.page.ts</code> looks like this</p><figure tabindex="0" contenteditable="false" name="ea18" class="graf graf--figure graf--iframe graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 60.429%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/7231aed9f42b609ca6a76a666fdbf2ff.js %}</div></div></figure><h4 name="01d3" class="graf graf--h4 graf-after--figure">4.3 Enable routing between two pages of the&nbsp;app</h4><p name="bcc7" class="graf graf--p graf-after--h4">The user data from Auth response can be sent to Landing Page using <code class="markup--code markup--p-code">NavigationExtras</code>&nbsp;. Here’s what you need to add to <code class="markup--code markup--p-code">home.page.ts</code> for navigating with data (where <code class="markup--code markup--p-code">user</code> is the response object from <code class="markup--code markup--p-code">GoogleAuth.singIn</code>)</p><pre name="d0a8" class="graf graf--pre graf-after--p">import { Router, NavigationExtras } from '@angular/router';<br>.... </pre><pre name="28d6" class="graf graf--pre graf-after--pre">export class HomePage {<br>  constructor(private router: Router) { }<br>  ...</pre><pre name="1e0a" class="graf graf--pre graf-after--pre">goToHome(user) {<br> let navigationExtras: NavigationExtras = { state: { user: user } };<br> this.router.navigate(['landing'], navigationExtras);<br>}</pre><p name="9ae8" class="graf graf--p graf-after--pre">In <code class="markup--code markup--p-code">landing.page.ts</code>, you can receive the data as follows</p><figure tabindex="0" contenteditable="false" name="1487" class="graf graf--figure graf--iframe graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 69.857%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/4c01430a22b6e6736448c66545535fee.js %}</div></div></figure><p name="4750" class="graf graf--p graf-after--figure">This way, you have logged in, and received the profile info of the user 🎉</p><h4 name="a7a5" class="graf graf--h4 graf-after--p">4.4 Sign&nbsp;out</h4><p name="6ab6" class="graf graf--p graf-after--h4">Once user is successfully logged in, we redirect user to <code class="markup--code markup--p-code">Landing</code> page. And when user logs out, we want to come back to <code class="markup--code markup--p-code">Home</code> page.</p><p name="52e3" class="graf graf--p graf-after--p">Sign out can be implemented with the following code on button click</p><pre name="585b" class="graf graf--pre graf-after--p">signOut() {<br> GoogleAuth.signOut().then(() =&gt; {<br>  this.router.navigate(['home']);<br> });<br>}</pre><h4 name="c0fe" class="graf graf--h4 graf-after--pre">4.5 Detect already logged in user / Auto-login</h4><p name="1215" class="graf graf--p graf-after--h4">In most of the apps, if you have logged in once, next time you open the app, you don’t have to login again. This can be done with our plugin as well.</p><p name="0c48" class="graf graf--p graf-after--p">We can detect already logged in user with <code class="markup--code markup--p-code">GoogleAuth.refresh()</code> method, Here’s the implementation and the resulting full code for <code class="markup--code markup--p-code">home.page.ts</code></p><figure tabindex="0" contenteditable="false" name="299c" class="graf graf--figure graf--iframe graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 134.857%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/642667ad906330c2a599effcc4359a74.js %}</div></div></figure><p name="e311" class="graf graf--p graf-after--figure">So, on button click we check if user is already logged in using <code class="markup--code markup--p-code">checkLoggedIn()</code>&nbsp;. If user is logged in, we send the user to Landing page with corresponding data. If not logged in, we go through the normal sign in route.</p><p name="14d6" class="graf graf--p graf-after--p">Once the user is detected as already logged in, we send the app user to Landing page with <code class="markup--code markup--p-code">accessToken</code>&nbsp;. This <code class="markup--code markup--p-code">accessToken</code> can then be used in a REST API call to get user’s profile info. Here’s the full code for <code class="markup--code markup--p-code">landing.page.ts</code> including getting the user’s profile info with REST API Call.</p><figure tabindex="0" contenteditable="false" name="5102" class="graf graf--figure graf--iframe graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 141.143%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/6e2e7cf0332933a155a2f77d2a68d0d8.js %}</div></div></figure><p name="7e9d" class="graf graf--p graf-after--figure">Here, <code class="markup--code markup--p-code">YOUR_WEB_API_KEY</code> is your web API key of Google project, which you obtained in Step 2.5</p><p name="486e" class="graf graf--p graf-after--p">The <code class="markup--code markup--p-code">https://www.googleapis.com/oauth2/v2/userinfo</code> end-point gives us the user’s profile info.</p><blockquote name="f600" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Note</strong>&nbsp;: I have used Capacitor Http plugin to make the API call. This is because this plugin can make API calls from all platforms while avoiding CORS and other issues. You can learn more on<a href="https://github.com/capacitor-community/http"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"> the plugin page</a></blockquote><h3 name="7aee" class="graf graf--h3 graf-after--blockquote">Step 4: Prepare and Test on&nbsp;Web</h3><p name="fefd" class="graf graf--p graf-after--h3">To implement Google Auth in web app with Capacitor, add this meta tag to head in <code class="markup--code markup--p-code">index.html</code> file.</p><pre name="d833" class="graf graf--pre graf-after--p">&lt;meta name="google-signin-client_id" content="{your client id here}"&gt;</pre><p name="48bf" class="graf graf--p graf-after--pre">With all the above code in place, web Google login can be tested in <code class="markup--code markup--p-code">ionic serve</code> itself. Here’s how it will work on browser</p><ol class="postList"><li name="5a58" class="graf graf--li graf-after--p">Normal login -&gt; Navigates to Landing page -&gt; Signout -&gt; Back to home page</li><li name="52b5" class="graf graf--li graf-after--li">Normal login -&gt;Navigates to Landing page | Refresh app on home page to simulate existing login on app start -&gt; Takes you directly to Landing page</li></ol><figure tabindex="0" contenteditable="false" name="a17b" class="graf graf--figure graf-after--li"><div class="aspectRatioPlaceholder is-locked" style="max-width: 350px; max-height: 650px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 185.7%;"></div><img class="graf-image" data-image-id="1*w4fwpWdypeEAxNDQp5Cfcw.gif" data-width="350" data-height="650" alt="Google login on Web&hairsp;—&hairsp;Ionic Capacitor Angular app" src="https://cdn-images-1.medium.com/max/800/1*w4fwpWdypeEAxNDQp5Cfcw.gif"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Google login on Web&hairsp;—&hairsp;Ionic Capacitor Angular&nbsp;app</figcaption><br></figure><p name="ff1e" class="graf graf--p graf-after--figure">The response object user will output all auth info of the user as shown in following image</p><figure tabindex="0" contenteditable="false" name="fa0b" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 167px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 23.9%;"></div><img class="graf-image" data-image-id="1*g8RdOSjVTRbJbJlmOm1nXA.png" data-width="1004" data-height="240" src="https://cdn-images-1.medium.com/max/800/1*g8RdOSjVTRbJbJlmOm1nXA.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Auth response object on Google&nbsp;Login</figcaption><br></figure><p name="acec" class="graf graf--p graf-after--figure">As you can see, you get all the required info in this response object. The response object obtained on the REST API call (as explained in Step 4.5) looks a little different. The profile photo comes under the property <code class="markup--code markup--p-code">picture</code> instead of <code class="markup--code markup--p-code">imageUrl</code></p><h3 name="1e9d" class="graf graf--h3 graf-after--p">Step 5&hairsp;—&hairsp;Build and Test your app on&nbsp;Android</h3><h4 name="99be" class="graf graf--h4 graf-after--h3">Create and configure platform</h4><p name="bf53" class="graf graf--p graf-after--h4">To build the app on Android, run these commands</p><pre name="7aae" class="graf graf--pre graf-after--p">// Add android platform<br>$ <strong class="markup--strong markup--pre-strong">npx cap add android<br></strong>// Copy all changes to Android platform<br>$ <strong class="markup--strong markup--pre-strong">npx cap sync<br></strong>// Open the project in Android studio<br>$ <strong class="markup--strong markup--pre-strong">npx cap open android</strong></pre><p name="296a" class="graf graf--p graf-after--pre">Also, add the following in your <code class="markup--code markup--p-code">strings.xml</code> file in Android Project</p><pre name="9442" class="graf graf--pre graf-after--p">&lt;resources&gt;<br>  &lt;string name="server_client_id"&gt;Your Web Client ID&lt;/string&gt;<br>&lt;/resources&gt;</pre><blockquote name="9067" class="graf graf--blockquote graf-after--pre"><strong class="markup--strong markup--blockquote-strong">Note</strong>: As of Capacitor 3.0, you do not need to add the plugin in the <code class="markup--code markup--blockquote-code">MainActivity.java</code> file</blockquote><h4 name="38c5" class="graf graf--h4 graf-after--blockquote">Avoid unimplemented methods</h4><p name="f19a" class="graf graf--p graf-after--h4">Build the app on Android device using Android studio. Make sure you detect the platform of device and NOT run <code class="markup--code markup--p-code">GoogleAuth.init()</code> and <code class="markup--code markup--p-code">GoogleAuth.refresh()</code> methods. These are currently not implemented in the plugin. Directly use <code class="markup--code markup--p-code">GoogleAuth.singIn()</code>&nbsp;. Something like this needs to be added</p><pre name="bdbb" class="graf graf--pre graf-after--p">import { Platform } from '@ionic/angular';<br>....<br>export class HomePage {<br> constructor(private platform: Platform, private router: Router) {<br>  this.isWeb = !this.platform.is('android') &amp;&amp;    !this.platform.is('ios');<br> }<br> checkLoggedIn() {<br>  if(this.isWeb){<br>   //run web implementation with init() and refresh()<br>  }<br>  else{<br>  // direct GoogleAuth.signIn()}<br>  }<br> }<br>}</pre><h4 name="cdbd" class="graf graf--h4 graf-after--pre">Make sure</h4><ul class="postList"><li name="6a29" class="graf graf--li graf-after--h4">You have added SHA-1 key to your Google project’s Android app settings <strong class="markup--strong markup--li-strong">as per Step 2.6</strong></li><li name="96a6" class="graf graf--li graf-after--li">Your app ID is same as the one you added in Google project’s Android app (and in <code class="markup--code markup--li-code">capacitor.config.json</code>)</li></ul><p name="4b65" class="graf graf--p graf-after--li">With these settings, your Google login should work fine in Android. Following GIF shows the login flow in my Android device.</p><figure tabindex="0" contenteditable="false" name="c191" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 337px; max-height: 600px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 178%;"></div><img class="graf-image" data-image-id="1*z-tXqAXUngzPJvCwp47mbg.gif" data-width="337" data-height="600" alt="Google login in Ionic Angular Capacitor App&hairsp;—&hairsp;Android" src="https://cdn-images-1.medium.com/max/800/1*z-tXqAXUngzPJvCwp47mbg.gif"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Google login in Ionic Angular Capacitor App&hairsp;—&hairsp;Android</figcaption><br></figure><h3 name="de04" class="graf graf--h3 graf-after--figure">Step 6&hairsp;—&hairsp;Build and Test your app on&nbsp;iOS</h3><h4 name="9c91" class="graf graf--h4 graf-after--h3">Create and configure platform</h4><p name="5caf" class="graf graf--p graf-after--h4">To build the app on iOS, run these commands</p><pre name="e2f6" class="graf graf--pre graf-after--p">// Add android platform<br>$ <strong class="markup--strong markup--pre-strong">npx cap add ios<br></strong>// Copy all changes to iOS platform<br>$ <strong class="markup--strong markup--pre-strong">npx cap sync<br></strong>// Open the project in XCode<br>$ <strong class="markup--strong markup--pre-strong">npx cap open ios</strong></pre><ul class="postList"><li name="3323" class="graf graf--li graf-after--pre">Place your downloaded<code class="markup--code markup--li-code">GoogleService.plist</code> in <code class="markup--code markup--li-code">ios/App/App</code> folder</li><li name="db56" class="graf graf--li graf-after--li">Find <code class="markup--code markup--li-code">REVERSED_CLIENT_ID</code> from the <code class="markup--code markup--li-code">GoogleService.plist</code> and add it as a URL scheme in <code class="markup--code markup--li-code">info.plist</code> of Xcode</li></ul><figure tabindex="0" contenteditable="false" name="4786" class="graf graf--figure graf-after--li"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 351px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 50.1%;"></div><img class="graf-image" data-image-id="0*ONMatwaQVGDmJu0c.png" data-width="700" data-height="351" alt="Add REVERSE_CLIENT_ID as URL scheme" src="https://cdn-images-1.medium.com/max/800/0*ONMatwaQVGDmJu0c.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Add <code class="markup--code markup--figure-code">REVERSE_CLIENT_ID</code> as URL&nbsp;scheme</figcaption><br></figure><h4 name="a813" class="graf graf--h4 graf-after--figure">Make sure</h4><ul class="postList"><li name="1539" class="graf graf--li graf-after--h4">You have created iOS app in Google Project as per Step 2.3</li><li name="a4cc" class="graf graf--li graf-after--li">You have added <code class="markup--code markup--li-code">GoogleServices-Info.plist</code> in <code class="markup--code markup--li-code">ios/App/App</code> folder. Cross-check by checking in XCode</li><li name="8f81" class="graf graf--li graf-after--li">You have added required URL scheme as mentioned is last paragraph</li></ul><figure tabindex="0" contenteditable="false" name="febf" class="graf graf--figure graf-after--li"><div class="aspectRatioPlaceholder is-locked" style="max-width: 531px; max-height: 301px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 56.699999999999996%;"></div><img class="graf-image" data-image-id="1*CdWOkdjUjZmrAiL8nGXpSQ.png" data-width="531" data-height="301" alt="Make sure XCode shows the GoogleServices-Info.plist added" src="https://cdn-images-1.medium.com/max/800/1*CdWOkdjUjZmrAiL8nGXpSQ.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Make sure XCode shows the <code class="markup--code markup--figure-code">GoogleServices-Info.plist added</code></figcaption><br></figure><p name="bd06" class="graf graf--p graf-after--figure">Build the app on iOS device or Simulator using Xcode. You should be able to login via Google, and reach the inner page where you see the user information. Following GIF shows the login flow in my iPhone simulator</p><figure tabindex="0" contenteditable="false" name="7836" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 277px; max-height: 600px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.6%;"></div><img class="graf-image" data-image-id="1*bG_skxM2kYF71mHEseE46g.gif" data-width="277" data-height="600" alt="Google login in Ionic React Capacitor App&hairsp;—&hairsp;iOS" src="https://cdn-images-1.medium.com/max/800/1*bG_skxM2kYF71mHEseE46g.gif"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Google login in Ionic React Capacitor App&hairsp;—&hairsp;iOS</figcaption><br></figure><h3 name="dfaa" class="graf graf--h3 graf-after--figure">Conclusion</h3><p name="b02e" class="graf graf--p graf-after--h3">In this post you learnt how to implement Google login in your Ionic Angular Capacitor app. Social logins are very important part of your apps, as they make users trust your apps more. It is also easy to use, and users don’t have to remember any passwords. You can always link the Social logins with your server as well.</p><p name="c704" class="graf graf--p graf-after--p">We also tested the Authentication on all three devices&hairsp;—&hairsp;Android, iOS and Web. This creates a complete set of devices a user can use with your app.</p><p name="3430" class="graf graf--p graf-after--p graf--trailing">Google Login is a complex one among social logins. Make sure you follow all the steps very carefully.</p></div></div></section><section name="bb2c" class="section section--body"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h3 name="a4bd" class="graf graf--h3 graf--leading">Next Steps</h3><p name="ee74" class="graf graf--p graf-after--h3 graf--trailing">If you liked this blog, you will also find the following blogs interesting and helpful. Feel free to ask any questions in the comment section</p></div></div></section><section name="06ac" class="section section--body"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h3 name="bdf7" class="graf graf--h3 graf--leading">Ionic Capacitor</h3><ul class="postList"><li name="5f8e" class="graf graf--li graf-after--h3"><strong class="markup--strong markup--li-strong">Basic</strong>&hairsp;—&hairsp;<a href="https://enappd.com/blog/use-geolocation-geocoding-and-reverse-geocoding-in-ionic-capacitor/131"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Geolocation</a> | <a href="https://enappd.com/blog/qr-code-and-barcode-scanning-with-ionic-capacitor/127"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Barcode &amp; QR code</a> | <a href="https://enappd.com/blog/facebook-login-in-capacitor-apps-with-ionic-angular/128"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Facebook Login</a> (Angular) | <a href="https://enappd.com/blog/facebook-login-in-ionic-react-capacitor-apps/118"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Facebook Login (React)</a> | <a href="https://enappd.com/blog/icon-splash-in-ionic-react-capacitor-apps/114"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Icon and Splash</a> | <a href="https://enappd.com/blog/camera-and-gallery-in-ionic-react-app-using-capacitor/110"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Camera &amp; Photo Gallery</a> | <a href="https://enappd.com/blog/debugging-ionic-apps-using-chrome-and-safari-developers-tools/167"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Debugging with browser</a>|<a href="https://enappd.com/blog/make-awesome-theme-switcher-in-ionic-5/170"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Theming in Ionic apps</a> | <a href="https://enappd.com/blog/google-login-in-ionic-capacitor-app-with-angular/178/"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Google Login (Angular)</a></li><li name="0f51" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Advanced</strong>&hairsp;—&hairsp;<a href="https://enappd.com/blog/implement-admob-in-ionic-react-capacitor-apps/135"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">AdMob</a> | <a href="https://enappd.com/blog/local-notifications-in-ionic-5-capacitor/132"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Local Notifications</a> | <a href="https://enappd.com/blog/google-login-in-ionic-react-capacitor-apps/122"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Google Login</a> | <a href="https://enappd.com/blog/twitter-login-in-ionic-react-capacitor-app/121"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Twitter Login</a> | <a href="https://enappd.com/blog/html5-games-in-ionic-capacitor-using-phaser/115"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Games using Phaser</a> | <a href="https://enappd.com/blog/play-music-in-ionic-capacitor-apps/112"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Play music</a> | <a href="https://enappd.com/blog/firebase-push-notification-in-ionic-react-capacitor/111"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Push Notifications</a></li></ul><h3 name="da78" class="graf graf--h3 graf-after--li">Ionic Cordova</h3><ul class="postList"><li name="23b7" class="graf graf--li graf-after--h3"><a href="https://enappd.com/blog/ionic-app-with-nodejs-express-mysql-sequelize-taxi-app/160"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Taxi Booking App example with Ionic, Node, Express and MySQL</a></li><li name="e3ed" class="graf graf--li graf-after--li">Ionic Payment Gateways&hairsp;—&hairsp;<a href="https://enappd.com/blog/integrate-stripe-payment-gateway-in-ionic-5-apps-and-pwa-using-firebase/158"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Stripe with Firebase</a> | <a href="https://enappd.com/blog/ionic-5-stripe-payment-integration-firebase-cloud-functions-vs-node-express-based-server/159"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Stripe with NodeJS</a> | <a href="https://enappd.com/blog/paypal-integration-in-ionic-apps-and-pwa/142"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">PayPal</a> |<a href="https://enappd.com/blog/paypal-payment-integration-using-braintree-in-ionic-5-apps/177/"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">PayPal with Braintree</a>| <a href="https://enappd.com/blog/how-to-integrate-apple-pay-in-ionic-4-apps/21"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Apple Pay</a> | <a href="https://enappd.com/blog/how-to-integrate-razorpay-in-ionic-4-apps-and-pwa/20"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">RazorPay</a></li><li name="4ecb" class="graf graf--li graf-after--li">Ionic Charts with&hairsp;—&hairsp;<a href="https://enappd.com/blog/ionic-4-charts-using-google-charts/66"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Google Charts </a>| <a href="https://enappd.com/blog/adding-charts-in-ionic-4-apps-and-pwa-part-3/60"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">HighCharts</a> | <a href="https://enappd.com/blog/adding-charts-in-ionic-4-apps-and-pwa-part-2/54"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">d3.js</a> | <a href="https://enappd.com/blog/charts-in-ionic-4-apps-and-pwa-part-1/52"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Chart.js</a></li><li name="7dc9" class="graf graf--li graf-after--li">Ionic Authentications&hairsp;—&hairsp;<a href="https://enappd.com/blog/firebase-email-authentication-in-ionic-apps/153"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Via Email</a> | <a href="https://enappd.com/blog/implement-anonymous-login-in-ionic-apps-with-firebase/154"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Anonymous</a> | <a href="https://enappd.com/blog/facebook-login-in-ionic-apps-using-firebase/150"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Facebook</a> | <a href="https://enappd.com/blog/implement-google-login-in-ionic-apps-using-firebase/147"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Google</a> | <a href="https://enappd.com/blog/twitter-login-in-ionic-4-apps-using-firebase/24"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Twitter</a> | <a href="https://enappd.com/blog/firebase-phone-authentication-in-ionic-5-apps/169"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Via Phone</a></li><li name="1310" class="graf graf--li graf-after--li">Ionic Features&hairsp;—&hairsp;<a href="https://enappd.com/blog/ionic-5-complete-guide-on-geolocation/141"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Geolocation</a>| <a href="https://enappd.com/blog/ionic-complete-guide-barcode-qrcode-scan/140"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">QR Code reader</a> | <a href="https://enappd.com/blog/best-fitness-plugins-for-ionic-4-how-to-use-pedometer/15"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Pedometer</a>| <a href="https://enappd.com/blog/implement-signature-pad-in-ionic-apps/145"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Signature</a> <a href="https://enappd.com/blog/implement-signature-pad-in-ionic-apps/145"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Pad</a> | <a href="https://enappd.com/blog/using-background-geolocation-in-ionic-angular-apps/165"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Background Geolocation</a> | <a href="https://enappd.com/blog/detect-wifi-and-data-network-in-ionic-5-apps/173"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Network Detection</a></li><li name="5a5f" class="graf graf--li graf-after--li">Media in Ionic&hairsp;—&hairsp;<a href="https://enappd.com/blog/spotify-like-music-in-ionic-4-apps/48"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Audio</a> | <a href="https://enappd.com/blog/adding-video-player-in-ionic-4-app/64"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Video</a> | <a href="https://enappd.com/blog/camera-and-image-picker-in-ionic-apps/148"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Image Picker</a> | <a href="https://enappd.com/blog/how-to-add-image-cropper-in-ionic-apps/149"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Image Cropper</a> | <a href="https://enappd.com/blog/implement-sounds-and-vibration-in-ionic-apps/172"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Sounds and Vibrations</a></li><li name="71f9" class="graf graf--li graf-after--li">Ionic Essentials&hairsp;—&hairsp;<a href="https://enappd.com/blog/debugging-ionic-apps-using-chrome-and-safari-developers-tools/167"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Debugging with browser</a>| <a href="https://enappd.com/blog/ionic-4-save-and-retrieve-data-locally-on-device/59"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Native Storage</a> | <a href="https://enappd.com/blog/how-to-translate-in-ionic-internationalization-and-localization/143"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Translations</a> | <a href="https://enappd.com/blog/how-to-use-rtl-right-to-left-in-ionic-apps-pwa/152"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">RTL</a> | <a href="https://enappd.com/blog/using-sentry-error-monitoring-with-ionic-angular-applications/164"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Sentry Error Monitoring</a> | <a href="https://enappd.com/blog/social-sharing-component-in-ionic-5-mobile-web-apps/168"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Social sharing</a> | <a href="https://enappd.com/blog/how-to-generate-and-download-pdf-in-ionic-apps/174"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">PDF generation</a></li><li name="58ce" class="graf graf--li graf-after--li">Ionic messaging&hairsp;—&hairsp;<a href="https://enappd.com/blog/how-to-implement-firebase-push-notifications-in-ionic-apps/157"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Firebase Push</a> | <a href="https://enappd.com/blog/how-to-automatically-read-sms-in-ionic-5-apps/175"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Reading SMS</a> | <a href="https://enappd.com/blog/local-notifications-in-ionic-5-capacitor/132"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Local Notifications</a></li><li name="0b6b" class="graf graf--li graf-after--li">Ionic with Firebase&hairsp;—&hairsp;<a href="https://enappd.com/blog/how-to-integrate-firebase-in-ionic-4-apps/23"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Basics</a> | <a href="https://enappd.com/blog/firebase-with-ionic-4-hosting-auth-and-db-connection/58"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Hosting and DB</a> | <a href="https://enappd.com/blog/firebase-cloud-functions-in-ionic-5-complete-guide/166"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Cloud functions</a> | <a href="https://enappd.com/blog/github-actions-deploying-ionic-angular-app-to-firebase-hosting/146"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Deploy App to Firebase</a> | <a href="https://enappd.com/blog/how-to-use-firebase-emulators-with-ionic-angular-applications/163"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Firebase simulator</a></li><li name="eaef" class="graf graf--li graf-after--li graf--trailing">Unit Testing in Ionic&hairsp;—&hairsp;<a href="https://enappd.com/blog/beginners-guide-to-ionic-angular-unit-testing-part-1/151"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Part 1</a> | <a href="https://enappd.com/blog/beginners-guide-to-ionic-angular-unit-testing-part-2-mocks-and-spies/155"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Mocks &amp; Spies</a>| <a href="https://enappd.com/blog/beginners-guide-to-ionic-angular-unit-testing-async-testing/156"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Async Testing</a></li></ul></div></div></section><section name="5071" class="section section--body section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h3 name="4c3b" class="graf graf--h3 graf--leading">Ionic Capacitor Full App (Angular)</h3><p name="9a60" class="graf graf--p graf-after--h3">If you need a base to start your next Angular <strong class="markup--strong markup--p-strong">Capacitor app</strong>, you can make your next awesome app using <a href="https://store.enappd.com/product/capacitor-full-app-with-ionic-angular/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Capacitor Full App</a></p><figure tabindex="0" contenteditable="false" name="c219" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 761px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 108.7%;"></div><img class="graf-image" data-image-id="0*UwSHcofTMStMnzAX.png" data-width="736" data-height="800" alt="Capacitor Full App with huge number of layouts and features" src="https://cdn-images-1.medium.com/max/800/0*UwSHcofTMStMnzAX.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Capacitor Full App with huge number of layouts and&nbsp;features</figcaption><br></figure><h3 name="ad14" class="graf graf--h3 graf-after--figure">Ionic React Full App with Capacitor</h3><p name="4fa5" class="graf graf--p graf-after--h3">If you need a base to start your next Ionic 5 React Capacitor app, you can make your next awesome app using <a href="https://store.enappd.com/product/ionic-react-full-app-capacitor/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic 5 React Full App in Capacitor</a></p><figure tabindex="0" contenteditable="false" name="0d2d" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 441px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63%;"></div><img class="graf-image" data-image-id="1*G3yOFVX4oABx9MhUy-3kng.png" data-width="760" data-height="479" alt="Ionic 5 React Full App in Capacitor from Enappd" src="https://cdn-images-1.medium.com/max/800/1*G3yOFVX4oABx9MhUy-3kng.png"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Ionic 5 React Full App in Capacitor from&nbsp;Enappd</figcaption><br></figure><h3 name="30ba" class="graf graf--h3 graf-after--figure">Ionic Full App (Angular and&nbsp;Cordova)</h3><p name="1008" class="graf graf--p graf-after--h3">If you need a base to start your next Ionic 5 app, you can make your next awesome app using <a href="https://store.enappd.com/product/ionic-full-app"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Ionic 5 Full App</a></p><figure tabindex="0" contenteditable="false" name="16d6" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 442px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63.1%;"></div><img class="graf-image" data-image-id="0*1ArpKyhiDHZnevwB.jpeg" data-width="700" data-height="442" alt="Ionic Full App with huge number of layouts and features" src="https://cdn-images-1.medium.com/max/800/0*1ArpKyhiDHZnevwB.jpeg"><div class="crosshair u-ignoreBlock"></div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Ionic Full App in Cordova, with huge number of layouts and&nbsp;features</figcaption><br></figure><p name="eff1" class="graf graf--p graf--empty graf-after--figure graf--trailing"><br></p></div></div></section></div></article></main>