Register Ionic 7 Push Notifications Android

146 views Asked by At

I'm trying to get configured Push Notifications for Android devices on a brand new Ionic app (v7). As I read in different docs and articles I did the following steps:

1.- Created my Firebase project and I added a new Android APP. The "package name" property matches the actual appId in the Android configuration.

2.- I downloaded the google-services.json file and placed it under Android > app folder.

3.- On the Android folder, my build.gradle looks like this:

buildscript {

    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:8.0.0'
        classpath 'com.google.gms:google-services:4.4.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

apply from: "variables.gradle"

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
} 

4.- My Android > app > build.gradle file looks like this:

plugins {
  id 'com.android.application'
  // Add the Google services Gradle plugin
  id 'com.google.gms.google-services'
}

apply plugin: 'com.android.application'

android {
    namespace "com.myapp.name"
    compileSdkVersion rootProject.ext.compileSdkVersion
    defaultConfig {
        applicationId "com.myapp.name"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        aaptOptions {
             // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
             // Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
            ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

repositories {
    flatDir{
        dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
    }
    maven {
        url "https://dl.bintray.com/microsoftazuremobile/SDK"
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
    implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
    implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
    implementation project(':capacitor-android')
    testImplementation "junit:junit:$junitVersion"
    androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
    androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
    implementation project(':capacitor-cordova-android-plugins')
    implementation 'com.microsoft.azure:notification-hubs-android-sdk:0.6@aar'
    implementation platform('com.google.firebase:firebase-bom:32.5.0')
    implementation 'com.google.firebase:firebase-analytics'
}

apply from: 'capacitor.build.gradle'

try {
    def servicesJSON = file('google-services.json')
    if (servicesJSON.text) {
        apply plugin: 'com.google.gms.google-services'
    }
} catch(Exception e) {
    logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
}

Note that I added the top "plugins" section as well as the azure notification hub implementation and the firebase BoM implementations too.

5.- I added firebaseMessagingVersion = '23.1.2' to the variables.gradle file in the root (Android) folder - as shown here https://ionicframework.com/docs/native/push-notifications#variables, resulting like this:

ext {
    minSdkVersion = 22
    compileSdkVersion = 33
    targetSdkVersion = 33
    androidxActivityVersion = '1.7.0'
    androidxAppCompatVersion = '1.6.1'
    androidxCoordinatorLayoutVersion = '1.2.0'
    androidxCoreVersion = '1.10.0'
    androidxFragmentVersion = '1.5.6'
    coreSplashScreenVersion = '1.0.0'
    androidxWebkitVersion = '1.6.1'
    junitVersion = '4.13.2'
    androidxJunitVersion = '1.1.5'
    androidxEspressoCoreVersion = '3.5.1'
    cordovaAndroidVersion = '10.1.1',
    firebaseMessagingVersion = '23.1.2'
}

6.- I updated the ApplicationManifest.xml file with the following data:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
            android:name=".MainActivity"
            android:label="@string/title_activity_main"
            android:theme="@style/AppTheme.NoActionBarLaunch"
            android:launchMode="singleTask"
            android:exported="true">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>

        <meta-data android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <service
            android:name=".RegistrationIntentService"
            android:exported="false">
        </service>
        <service
            android:name=".FirebaseService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    </application>

    <!-- Permissions -->

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
</manifest>

7.- my capacitor.config.ts looks like this:

/// <reference types="@capacitor/push-notifications" />

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.myapp.name',
  appName: 'my-app-name',
  webDir: 'www',
  server: {
    androidScheme: 'https'
  },
  plugins: {
    PushNotifications: {
      presentationOptions: ["badge", "sound", "alert"]
    }
  }
};

export default config;

8.- My packages.json is pretty standard and contains the following package versions:

"dependencies": {
    "@angular/animations": "^16.2.12",
    "@angular/common": "^16.2.12",
    "@angular/compiler": "^16.2.12",
    "@angular/core": "^16.2.12",
    "@angular/forms": "^16.2.12",
    "@angular/platform-browser": "^16.2.12",
    "@angular/platform-browser-dynamic": "^16.2.12",
    "@angular/router": "^16.2.12",
    "@capacitor/android": "^5.0.0",
    "@capacitor/app": "^5.0.0",
    "@capacitor/core": "^5.0.0",
    "@capacitor/haptics": "^5.0.0",
    "@capacitor/ios": "^5.0.0",
    "@capacitor/keyboard": "^5.0.0",
    "@capacitor/push-notifications": "^5.0.0",
    "@capacitor/splash-screen": "^5.0.0",
    "@capacitor/status-bar": "^5.0.0",
    "@fortawesome/angular-fontawesome": "^0.13.0",
    "@fortawesome/fontawesome-svg-core": "^6.4.2",
    "@fortawesome/free-solid-svg-icons": "^6.4.2",
    "@ionic/angular": "^7.0.0",
    "ionicons": "^7.0.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.13.0"
  },

In order to play with the registration process I put testing code on the app.component like so:

import { Component } from '@angular/core';
import { AlertController, IonicModule, Platform } from '@ionic/angular';
import { SplashScreen } from '@capacitor/splash-screen';
import {
    ActionPerformed,
    PushNotificationSchema,
    PushNotifications,
    Token,
  } from '@capacitor/push-notifications';
@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    standalone: true,
    imports: [
        IonicModule,
    ]
})
export class AppComponent {
    constructor(private platform: Platform,
                private alertController: AlertController) {
        this.initializeApp();
    }
  
    initializeApp() {
        this.platform.ready().then(async () => {

              // Request permission to use push notifications
              // iOS will prompt user and return if they granted permission or not
              // Android will just grant without prompting
              PushNotifications.requestPermissions().then(result => {
                if (result.receive === 'granted') {
                  // Register with Apple / Google to receive push via APNS/FCM
                  PushNotifications.register();
                } else {
                  // Show some error
                }
              });
          
              // On success, we should be able to receive notifications
              PushNotifications.addListener('registration',
                async (token: Token) => {
                    const alert = await this.alertController.create({
                        header: 'Registration OK!',
                        subHeader: 'Registration OK!',
                        message: token.value,
                        buttons: ['OK'],
                      });
                      await alert.present();
                }
              );
          
              // Some issue with our setup and push will not work
              PushNotifications.addListener('registrationError',
                async (error: any) => {
                    const alert = await this.alertController.create({
                        header: 'Registration ERROR',
                        subHeader: 'Registration ERROR',
                        message: JSON.stringify(error),
                        buttons: ['OK'],
                      });
                      await alert.present();
                }
              );
          
              // Show us the notification payload if the app is open on our device
              PushNotifications.addListener('pushNotificationReceived',
                (notification: PushNotificationSchema) => {
                    console.log('Push received: ' + JSON.stringify(notification));
                }
              );
          
              // Method called when tapping on a notification
              PushNotifications.addListener('pushNotificationActionPerformed',
                (notification: ActionPerformed) => {
                    console.log('Push action performed: ' + JSON.stringify(notification));
                }
              );
        });
    }
}

When I run the app the first time I get the following message which seems to be a good sign:

enter image description here

But then I got a FIS_AUTH_ERROR:

enter image description here

And I am sort of stuck because I don't know how to get more information about this error and how to address it. I am running Android SDK 33. Any ideas what am I missing?

UPDATE

I when to Google Cloud Console and removed all API credentials and service accounts created for that application. Removed the APP. Recreated the APP and copied the newly generated google-services.json and worked like a charm. Therefore you can use the above steps to configure your push notifications on a ionic 7 app using capacitor 5 and firebase

0

There are 0 answers