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:
But then I got a FIS_AUTH_ERROR
:
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