9
votes

I have a problem with Cordova's android application based on Angular 5+. I've found that window.history.back() and similar native JS back functions make two problems:

  • when going back, a page is flashing. It seems like first, all HTML content loaded and after it CSS
  • In one page on a back action, my layout is broken (screens below)

Orginal view: Original view

After back button: After back button

What's curious - after changing phone orientation all backs to normal.

I've found a solution - instead of using vanilla JS back functions I've created mine using Angular Router:

I've subscribe on router's events and save all routes:

this._subs.push(this._router.events.subscribe((e) => {
      if (e instanceof NavigationEnd) {
        this._cordovaService.saveRoute(e.url);
      }
    }));

And if I want back, I use navigateByUrl function:

back(): void {
    const lastRoute = this._routingHistory[this._routingHistory.length - 2];
    if (lastRoute) {
      this._router.navigateByUrl(lastRoute);
      this._routingHistory.pop();
    }
  }

After implementing this functionality for my inApp back buttons all work fine - there is no flashing or breaking layout.

Although, after implemented this function for my physical back button, the error is the same - layout breaking or flashing. Below my implementation:

Service:

this.deviceReady = Observable.fromEvent(document, 'deviceready').publishReplay(1);
    (this.deviceReady as ConnectableObservable<Event>).connect();
    this.restore = Observable.fromEvent(document, 'resume').publishReplay();
    (this.restore as ConnectableObservable<Event>).connect();
    this.backbutton = Observable.fromEvent(document, 'backbutton').publishReplay();
    (this.backbutton as ConnectableObservable<Event>).connect();

Using it:

this._subs.push(this._cordovaService.deviceReady.subscribe(
      () => {
        document.addEventListener('backbutton', function (e) {
          e.preventDefault();
          e.stopPropagation();
          this._cordovaService.back();
        }.bind(this), false);
      }
      )
    );

I'm sure that function in backbutton is executed (I've logged some information) but the problem still occurs.

More information:

  • I'm using cordova version 8.0.0
  • I'm using the following plugins:

    https://github.com/TheMattRay/cordova-plugin-wkwebviewxhrfix.git" />

Some hints:

Once, I've built Cordova's android applications which work great (with native JS back function) but after next build, all come back. In hockeyapp I see that in good working version lowest available Android version was 4.1. In new apps, it is 4.4.

I've tried to downgrade Cordova/android engine version but without any positive results.

Additionally, I want to work with the newest libraries available.

Thanks for any help in that case.

1

1 Answers

12
votes

I've finally found the solution, based on the following blog's post: http://weblogs.thinktecture.com/thomas/2017/02/cordova-vs-zonejs-or-why-is-angulars-document-event-listener-not-in-a-zone.html, I've added below script just before cordova.js import:

   <script>
    (function () {
      'use strict';

      window.addEventListener = function () {
        EventTarget.prototype.addEventListener.apply(this, arguments);
      };

      window.removeEventListener = function () {
        EventTarget.prototype.removeEventListener.apply(this, arguments);
      };

      document.addEventListener = function () {
        EventTarget.prototype.addEventListener.apply(this, arguments);
      };

      document.removeEventListener = function () {
        EventTarget.prototype.removeEventListener.apply(this, arguments);
      };
    })();
  </script>
  <script type="text/javascript" src="cordova.js"></script>

More about why this error occurring you can read in this GitHub issue: https://github.com/angular/angular/issues/22509