Skip to content

Instantly share code, notes, and snippets.

@nilsmehlhorn
Last active November 16, 2019 13:46
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save nilsmehlhorn/1a3ee7447d0c7b60104288bc16c80c13 to your computer and use it in GitHub Desktop.
Save nilsmehlhorn/1a3ee7447d0c7b60104288bc16c80c13 to your computer and use it in GitHub Desktop.
Android push notifications with EddyVerbruggen/nativescript-plugin-firebase
import { ReplaySubject } from "rxjs/ReplaySubject";
import { Observable } from "rxjs/Observable";
const _intentSubject = new ReplaySubject<android.content.Intent>();
export const OnIntent: Observable<any> = _intentSubject.asObservable(); // apply transformation as needed to abstract from platform
@JavaProxy("org.example.App.MainActivity")
export class Activity extends android.app.Activity {
private _callbacks: AndroidActivityCallbacks;
protected onCreate(savedInstanceState: android.os.Bundle): void {
if (!this._callbacks) {
setActivityCallbacks(this);
}
this._callbacks.onCreate(this, savedInstanceState, super.onCreate);
const creationIntent = this.getIntent();
_intentSubject.next(creationIntent);
}
protected onNewIntent(intent: android.content.Intent): void {
super.onNewIntent(intent);
_intentSubject.next(intent);
}
protected onSaveInstanceState(outState: android.os.Bundle): void {
this._callbacks.onSaveInstanceState(this, outState, super.onSaveInstanceState);
}
protected onStart(): void {
this._callbacks.onStart(this, super.onStart);
}
protected onStop(): void {
this._callbacks.onStop(this, super.onStop);
}
protected onDestroy(): void {
this._callbacks.onDestroy(this, super.onDestroy);
}
public onBackPressed(): void {
this._callbacks.onBackPressed(this, super.onBackPressed);
}
public onRequestPermissionsResult(requestCode: number, permissions: Array<String>, grantResults: Array<number>): void {
this._callbacks.onRequestPermissionsResult(this, requestCode, permissions, grantResults, undefined /*TODO: Enable if needed*/);
}
protected onActivityResult(requestCode: number, resultCode: number, data: android.content.Intent): void {
this._callbacks.onActivityResult(this, requestCode, resultCode, data, super.onActivityResult);
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="__PACKAGE__"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="__APILEVEL__"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<meta-data android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_content_notification" />
<activity
android:name="org.example.App.MainActivity"
android:launchMode="singleTask"
android:label="@string/title_activity_kimera"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/LaunchScreenTheme">
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="app.org" />
</intent-filter>
</activity>
<activity android:name="com.tns.ErrorReportActivity"/>
<service android:name="org.nativescript.plugins.firebase.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name="org.nativescript.plugins.firebase.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
import { Component, OnInit, NgZone } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { RouterExtensions } from "nativescript-angular";
import { isAndroid, isIOS } from "platform";
// setup notifcation source for both platforms
let OnNotification: Observable<string>;
if (isAndroid) {
OnNotification = require("./activity").OnIntent;
} else if (isIOS) {...}
@Component({selector: "app", templateUrl: "app.component.html"})
export class AppComponent implements OnInit {
constructor(private _zone: NgZone) {...}
ngOnInit() {
// subscribe to notification events from both platforms
OnNotification.subscribe((notification) => this._doSomething());
// if you are doing something with Angular based on the notifications, you should probably run it in NgZone
}
}
@Aks659
Copy link

Aks659 commented Sep 26, 2017

Again, thanks for this mightily helpful gist 👍

Few minor issues I faced :

  1. [ts] Cannot find name 'android' :
    Added npm i tns-platform-declarations --save-dev
    Added /// <reference path="../node_modules/tns-platform-declarations/android/android17.d.ts" /> to the top of activity.android.ts

  2. Getting the extras as intent.getExtras().get('param1')

  3. Also, I changed the name of activity from android.activity.ts to activity.android.ts as mentioned in official doc

@Sharique-Hasan
Copy link

I am seeing this error:

An uncaught Exception occurred on "main" thread.
java.lang.RuntimeException: Unable to resume activity {com.bol.bolgameshow/org.nativescript.sdkAngular.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Handler android.support.v4.app.FragmentHostCallback.getHandler()' on a null object reference
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3103)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Handler android.support.v4.app.FragmentHostCallback.getHandler()' on a null object reference
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2170)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2223)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:379)
at android.support.v4.app.FragmentActivity.onResume(FragmentActivity.java:449)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
at android.app.Activity.performResume(Activity.java:6312)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
... 10 more

@Aks659
Copy link

Aks659 commented Oct 21, 2017

I got some errors too, don't remember exactly what. I just made a clean build and it worked!

@mrtouya
Copy link

mrtouya commented Nov 14, 2019

Hey Guys,
How did you parse the data that was returned to get the information returned from the dynamic link?

--> OnNotification.subscribe((notification) => this._doSomething());

Thanks!

@nilsmehlhorn
Copy link
Author

@mrtouya It should already be an object containing the data fields of your push message - at least it was when I look back into the app where I used this gist back in 2017. There I just used the data keys to route the app to a specific view.

If I recall correctly, this code is only for notifications displayed to the user while the app is not opened. In that case, the system will display the title and message of your notification and forward only the notification data to your app once the user clicks on it from system tray. When the app is running, you could get the notification (title, message & data) through the plugin and open up a dialog by yourself. Any of this might have changed though since then.

I don't understand what you mean by "dynamic link". This gist only refers to push notifications. The plugin also supports Firebase Dynamic Links though, here are the docs: https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/master/docs/DYNAMIC_LINKS.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment