Android push notification and ViewChild Element null when onMessageReceivedCallback call


#1

Hi !

I have implemented push notification on android with nativescript-firebase-plugin.

I have a webview that I want to reload with a new url param on push notification, but when onMessageReceivedCallback is emitted, my webview Viewchild element is not loaded yet, but still I can saw the webview loaded correctly, I made this

this.web1.nativeElement.android.loadUrl(new_url);

And I get TypeError: Cannot read property ‘loadUrl’ of null

I made this on NgOninit, and if I do the action manually it has no problem, the problem is when te action comes from the firebase event.

Does anyone have any idea?

Thanks !


#2

What you mean by manually?

Besides ngOnInit doesn’t gaurentee that your view / native elements are rendered.


#3

If I make the action inside NgOnInit is not a problem, the problem is when te action comes on the firebase event.

No problem:

ngOnInit() {
   this.web1.nativeElement.android.loadUrl('url');
}

Problem

ngOnInit() {
firebase.init({
            onPushTokenReceivedCallback: (token) => {
                console.log("Firebase push token: " + token);
            },
            onMessageReceivedCallback: (message) => {
                console.log(JSON.stringify(message));
                if (message.foreground) {
                    //App abierta
                } else {
                    if (message.data.noticia) {
                        var not = message.data.noticia;
                        this.web1.nativeElement.android.loadUrl(not);
                    }
                }
            },
            persist: false,
        });
}

Thanks !


#4

Looks like the native android element was not yet created when notification callback was triggered. Try adding a timeout of one or two sec, let me know the outcome.


#5

I tried with 5 seconds and I get the same error

ngOnInit() {
firebase.init({
            onPushTokenReceivedCallback: (token) => {
                console.log("Firebase push token: " + token);
            },
            onMessageReceivedCallback: (message) => {
                console.log(JSON.stringify(message));
                if (message.foreground) {
                    //App abierta
                } else {
                    if (message.data.noticia) {
                        var not = message.data.noticia;
                        setTimeout(()=>{
            this.web1.nativeElement.android.loadUrl(not);
        }, 5000)
                    }
                }
            },
            persist: false,
        });
}

I tried to put the firebase subscription in the webViewModule.WebView.loadFinishedEvent but the error still happening

Would you have any idea?

Thanks!


#6

Would you mind sharing what you have in your html template? Also try to log and see what is the value of .nativeElement and .android in the message received callback.


#7

Of course !

HTML

<StackLayout>
  <Webview #web src="{{webViewSrc}}"></Webview>
</StackLayout>

TS

import {Component,ElementRef,ViewChild,OnInit,NgZone} from "@angular/core";
import {Page} from "ui/page";
import webViewModule = require("ui/web-view");
var utilityModule = require("utils/utils");
import * as app from "application";
import {WebView,LoadEventData} from "ui/web-view"
import {PropertyChangeData,View} from "tns-core-modules/ui/frame/frame";

@Component({
    selector: "ns-app",
    templateUrl: "app.component.html",
})

export class AppComponent implements OnInit {
    @ViewChild("web") web1: ElementRef;
    public webViewSrc;
    constructor(private page: Page, private zone: NgZone) {
        page.actionBarHidden = true;
    }

    ngOnInit() {
        this.webViewSrc = "**********";
        this.web1.nativeElement.on(webViewModule.WebView.loadStartedEvent, (args: LoadEventData) => {
            if (args.url.search("****") <= 0 || args.url.search("*******") > 15) {
                this.web1.nativeElement.stopLoading()
                utilityModule.openUrl(args.url)
            }
        });
        this.web1.nativeElement.on(webViewModule.WebView.loadFinishedEvent, (args: LoadEventData) => {
            this.web1.nativeElement.android.getSettings().setJavaScriptEnabled(true);
            this.web1.nativeElement.android.getSettings().setDomStorageEnabled(true);
            let firebase = require("nativescript-plugin-firebase");
        firebase.init({
            onPushTokenReceivedCallback: (token) => {
                console.log("Firebase push token: " + token);
            },
            onMessageReceivedCallback: (message) => {
                console.log(JSON.stringify(message));
                if (message.foreground) {
                    //App abierta
                } else {
                    if (message.data.noticia) {
                        var not = message.data.noticia;
                        this.load(not);
                    }
                }
            },
            persist: false,
        }).then(
            function (instance) {
                console.log("firebase.init done");
            },
            function (error) {
                console.log("firebase.init error: " + error);
            }
        );
        })
    }
    load(not) {
        setTimeout(()=>{
            console.log('*** Web nativeElement');
            console.log(this.web1.nativeElement);
            console.log('*** Android element')
            console.log(this.web1.nativeElement.android);
            this.web1.nativeElement.android.loadUrl(not);
        }, 5000) 
    }
}

Logs when setTimeout()

JS: *** Web nativeElement
JS: WebView(6)
JS: *** Android element
JS: null
System.err: com.tns.NativeScriptException:
System.err: Calling js method run failed
System.err: TypeError: Cannot read property 'loadUrl' of null
System.err: File: "file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js, line: 142, column: 24
System.err: StackTrace:
System.err:     Frame: function:'', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/app.component.js', line: 57, column: 45
System.err:     Frame: function:'ZoneDelegate.invokeTask', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 398, column: 31
System.err:     Frame: function:'Zone.runTask', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 165, column: 47
System.err:     Frame: function:'ZoneTask.invoke', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 460, column: 38
System.err:     Frame: function:'timer', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 1634, column: 29
System.err:     Frame: function:'invoke', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/tns-core-modules/timer/timer.js', line: 19, column: 48
System.err:     Frame: function:'ZoneDelegate.invoke', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 365, column: 26
System.err:     Frame: function:'Zone.runGuarded', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 138, column: 47
System.err:     Frame: function:'', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js', line: 116, column: 29
System.err:     Frame: function:'run', file:'file:///data/data/org.nativescript.pruebaAndroid/files/app/tns_modules/tns-core-modules/timer/timer.js', line: 23, column: 13
System.err:     at com.tns.Runtime.callJSMethodNative(Native Method)
System.err:     at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1043)
System.err:     at com.tns.Runtime.callJSMethodImpl(Runtime.java:925)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:912)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:896)
System.err:     at com.tns.Runtime.callJSMethod(Runtime.java:888)
System.err:     at com.tns.gen.java.lang.Runnable.run(Runnable.java:10)
System.err:     at android.os.Handler.handleCallback(Handler.java:739)
System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
System.err:     at android.os.Looper.loop(Looper.java:135)
System.err:     at android.app.ActivityThread.main(ActivityThread.java:5254)
System.err:     at java.lang.reflect.Method.invoke(Native Method)
System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
ActivityManager: Process org.nativescript.pruebaAndroid (pid 5599) has died

Thanks a lot !!!


#8

Can you try to simply your code to understand where exactly the issue occurs? Try moving all WebView events. Just keep the firebase init code piece inside ngOnInit.

Also this doesn’t seem like a valid code / regular expression args.url.search("****") <= 0 || args.url.search("*******") > 15), You must consider escaping asterisk (*) in a regular expression.