question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cordova Android reloads causing white screen on some app pages when navigating

See original GitHub issue

Bug Report

Problem

When navigating between some pages within my app, on Cordova Android the page seems to reload causing a white screen.

What is expected to happen?

Cordova Android shouldn’t reload an existing page and cause a white screen to appear.

What does actually happen?

When navigating between some pages in my app, the screen goes white for several seconds before appearing to reload on whatever page I was trying to navigate away from.

Information

Using the latest version of Nuxt JS along with Vuetify JS

Command or Code

Plugins

cordova-plugin-actionsheet 2.3.3 "ActionSheet"
cordova-plugin-app-event 1.2.2 "Application Events"
cordova-plugin-background-mode 0.7.3 "BackgroundMode"
cordova-plugin-badge 0.8.8 "Badge"
cordova-plugin-console 1.1.0 "Console"
cordova-plugin-device 2.0.3 "Device"
cordova-plugin-file 6.0.2 "File"
cordova-plugin-local-notification 0.9.0-beta.3 "LocalNotification"
cordova-plugin-native-keyboard 2.0.6 "Native Keyboard"
cordova-plugin-whitelist 1.3.4 "Whitelist"

Main package.json in project root

"dependencies": {
  "@nuxtjs/axios": "5.12.1",
  "@nuxtjs/firebase": "6.1.1",
  "@nuxtjs/pwa": "3.0.1",
  "axios": "0.20.0",
  "cross-env": "7.0.2",
  "crypto-js": "4.0.0",
  "firebase": "7.19.0",
  "lz-string": "1.4.4",
  "nuxt": "2.14.3",
  "nuxt-vuex-localstorage": "1.2.7",
  "pulljs": "0.1.2",
  "vee-validate": "2.2.15",
  "vue-axios": "2.1.5",
  "vue-moment": "^4.1.0",
  "vue-swatches": "2.1.0",
  "vue-tour": "1.5.0",
  "vue2-touch-events": "^2.3.1",
  "vuedraggable": "2.24.1",
  "vuetify": "1.5.24",
  "vuetify-loader": "1.6.0",
  "vuexfire": "3.2.4",
  "xml-to-json-stream": "1.1.0",
  "xml2js": "0.4.23"
}

config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget android-versionCode="101050" id="com.COMPANY.APPNAME" ios-CFBundleVersion="1.1.5" version="1.1.5" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>APPNAME</name>
    <description>
        DESC
    </description>
    <author email="contact@EMAIL" href="SITE">
        AUTHOR
    </author>
    <content src="index.html" />
    <access origin="*" />
    <allow-navigation href="*" />
    <allow-intent href="*" />
    <preference name="DisallowOverscroll" value="true" />
    <platform name="android">
        <icon density="xxxhdpi" src="res/icon/android/icon-192-xxxhdpi.png" />
        <icon density="xxhdpi" src="res/icon/android/icon-144-xxhdpi.png" />
        <icon density="xhdpi" src="res/icon/android/icon-96-xhdpi.png" />
        <icon density="hdpi" src="res/icon/android/icon-72-hdpi.png" />
        <icon density="mdpi" src="res/icon/android/icon-48-mdpi.png" />
        <icon density="ldpi" src="res/icon/android/icon-36-ldpi.png" />
        <splash src="res/splash/android/Default@2x~universal~anyany.png" />
        <allow-intent href="market:*" />
        <custom-config-file parent="/*" target="AndroidManifest.xml">
            <uses-permission android:name="android.permission.INTERNET" />
            <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
            <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
            <uses-permission android:name="android.permission.WAKE_LOCK" />
        </custom-config-file>
        <preference name="android-windowSoftInputMode" value="adjustPan" />
        <preference name="android-minSdkVersion" value="28" />
        <preference name="android-targetSdkVersion" value="29" />
    </platform>
    <platform name="ios">
        <icon height="1024" src="res/icon/ios/icon-1024.png" width="1024" />
        <icon height="180" src="res/icon/ios/icon-180.png" width="180" />
        <icon height="167" src="res/icon/ios/icon-167.png" width="167" />
        <icon height="152" src="res/icon/ios/icon-152.png" width="152" />
        <icon height="120" src="res/icon/ios/icon-120.png" width="120" />
        <icon height="87" src="res/icon/ios/icon-87.png" width="87" />
        <icon height="76" src="res/icon/ios/icon-76.png" width="76" />
        <icon height="60" src="res/icon/ios/icon-60.png" width="60" />
        <icon height="40" src="res/icon/ios/icon-40.png" width="40" />
        <splash src="res/splash/ios/Default@2x~universal~anyany.png" />
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
        <preference name="scheme" value="app" />
        <preference name="hostname" value="localhost" />
        <preference name="deployment-target" value="13.0" />
    </platform>
    <plugin name="cordova-plugin-console" spec="1.1.0" />
    <plugin name="cordova-plugin-actionsheet" spec="2.3.3" />
    <plugin name="cordova-plugin-local-notification" spec="https://github.com/katzer/cordova-plugin-local-notifications.git">
        <variable name="ANDROID_SUPPORT_V4_VERSION" value="26.+" />
    </plugin>
    <plugin name="cordova-plugin-file" spec="6.0.2" />
    <plugin name="cordova-plugin-device" spec="2.0.3" />
    <plugin name="cordova-plugin-app-event" spec="^1.2.2" />
    <plugin name="cordova-plugin-native-keyboard" spec="2.0.5">
        <variable name="LICENSE" value="TRIAL" />
        <variable name="LIC_ANDROID" value="TRIAL" />
        <variable name="LIC_IOS" value="TRIAL" />
    </plugin>
    <plugin name="cordova-plugin-whitelist" spec="1.3.3" />
</widget>

My JS file responsible for initialising Cordova in my project is…

export default (ctx, inject) => {
  const { app } = ctx

  const cordovaApp = {
    // Application Constructor
    initialize () {
      alert('app init')
      document.addEventListener(
        'deviceready',
        this.onDeviceReady.bind(this),
        false
      )
      document.addEventListener(
        'pause',
        this.onPause.bind(this),
        false
      )
    },

    // Android back button
    androidBackButton () {
      alert('back button')
      app.router.push(`/`)
    },

    // pause Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onPause () {
      alert('paused app')
      if (!app.store.state.localStorage.authSettings[0].remainLoggedIn) {
        app.store.state.localStorage.account = null
        app.store.state.localStorage.user = null
      }
    },

    // deviceready Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onDeviceReady () {
      alert('device is ready')
      if (device.platform) {
        app.store.state.device.platform = device.platform
      }

      if (device.platform == 'Android' || device.platform == 'android') {

        // TODO: 07/01/20: crashes Android, requires fix.
        cordova.plugins.backgroundMode.enable()
        cordova.plugins.backgroundMode.overrideBackButton()
        cordova.plugins.backgroundMode.setDefaults({
          silent: true
        })
        cordova.plugins.backgroundMode.on('activate', function () {
          cordova.plugins.backgroundMode.disableWebViewOptimizations()
        })

        document.addEventListener(
          'backbutton',
          this.androidBackButton.bind(this),
          false
        )
      }
      cordova.plugins.notification.local.on("click", function(notification) {
        var notificationRaw = JSON.stringify(notification, null, 4);
        var notificationBeautify = JSON.parse(notificationRaw);
        if (notificationBeautify.data.redirectTo) {
          app.router.push(`/url/${notificationBeautify.data.redirectTo}`)
        } else {
          app.router.push(`/`)
        }
      });

      /**
       * initialize all different stuff here:
       * e.g.
       *  - sentry
       *  - firebase
       *  - adjust
       *  - push notifications
       *  - fabric
       *  - custom url schema
       *  - facebook
       *  - universal links
       *  - google analytics
       *  - ...
       *
       *  context to "app" is avaialble, but beware only the app scope of a plugin (which means if any other plugin
       *  extends the app scope, it could be that it is not available yet)
       */

      try {
        this.initStatusBar()
      } catch (err) {
        alert('status bar error')
        alert(err)
        // console.error('status bar failed', err)
      }

      try {
        this.initWKWebView()
      } catch (err) {
        alert('webkit view error')
        alert(err)
        // console.error('init WKWebView failed', err)
      }

      try {
        this.initCustomUrlScheme()
      } catch (err) {
        alert('custom url scheme error')
        alert(err)
      }
    },

    initCustomUrlScheme () {
      window.handleOpenURL = url => {
        alert('DeepLink: ' + url)
      }
    },

    initStatusBar () {
      console.log()
      window.StatusBar.overlaysWebView(false)
      window.StatusBar.backgroundColorByHexString('#009896')
    },

    initWKWebView () {
      /* window.WkWebView.allowsBackForwardNavigationGestures(false)
      EventBus.$on('OpenInsidePages', count => {
        if (count > 0) {
          window.WkWebView.allowsBackForwardNavigationGestures(true)
        } else {
          window.WkWebView.allowsBackForwardNavigationGestures(false)
        }
      }) */
    }
  }

  cordovaApp.initialize()

  // patch redirect url for cordova - removes "formatUrl" call because it add "//" to the path
  app.context.redirect = (status, path, query) => {
    if (!status) {
      return
    }

    app.context._redirected = true
    // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' })
    let pathType = typeof path
    if (
      typeof status !== 'number' &&
      (pathType === 'undefined' || pathType === 'object')
    ) {
      query = path || {}
      path = status
      pathType = typeof path
      status = 302
    }
    if (pathType === 'object') {
      path = app.router.resolve(path).href
    }
    // "/absolute/route", "./relative/route" or "../relative/route"
    if (/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path)) {
      app.context.next({
        path: path,
        query: query,
        status: status
      })
    } else {
      // https://developer.mozilla.org/en-US/docs/Web/API/Location/replace

      // path = formatUrl(path, query) removed

      window.location.replace(path)
    }
  }
}

Environment, Platform, Device

  • Android device

Version information

Cordova 10 Cordova Android 9.0.0

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
breautekcommented, Aug 26, 2020

Cordova Android shouldn’t reload an existing page

Cordova Android webview wouldn’t ever reload an existing page. It would load an HTML document, and run it’s javascript.

What you’re describing sounds like you’re encountering a javascript exception within your app. Have you tried connecting the chrome web inspector and looking for javascript errors in the console?

0reactions
breautekcommented, Jan 5, 2021

@srikarnagzz this issue turned out to not be related to Cordova Android in the end, but rather a change in the framework’s code that I’m using

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cordova - white screen after splash, no exceptions in console
1) First you need to declare Splash screen preference along with splash screen plugin location in your config.xml. · 2) Declare your splash ......
Read more >
Android white screen on startup, Cordova-android white screen ...
Cordova -android white screen. Problem When navigating between some pages within my app, on Cordova Android the page seems to reload causing a...
Read more >
WebView - Android Developers
WebView objects allow you to display web content as part of your activity layout, but lack some of the features of fully-developed browsers....
Read more >
Debugging the Ionic White Screen of Death - YouTube
In this video, we walk through 4 different steps you can take to help track down errors that are occurring in your Ionic...
Read more >
WkWebView always comes up with white background?
This will prevent the web view from clearing the display. 2) Set webView.backgroundColor to the eventual colour of your HTML, or something halfway...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found