Wikitude / wikitude-cordova-plugin

Wikitude's Augmented Reality Plugin for Cordova - working together with the Wikitude SDK library for Android and iOS. Provides image recognition and tracking, geo-based augmente reality and 3D rendering and animations in an augmented reality scene
https://www.wikitude.com
Other
199 stars 181 forks source link

onWikitude error – "The URL can’t be shown" #123

Open pauwlsky opened 7 years ago

pauwlsky commented 7 years ago

Hi,

I've recently taken over the work on a react cordova application that uses your plugin. Thanks for all your hard work.

I am getting this error very commonly when calling loadARchitectWorld pretty consistently though. This issue resolves when routing to a different view and then rerouting back to the component which mounts the AR World.

Haven't been able to find the root of the problem, previously we had conflicts in our project between the cordova file plugin and the wikitude plugin. Could be how our application is structured though.

I've read your docs and am not seeing any major flags in how our application was setup. Any recommendations about how to troubleshoot this would be much appreciated.

Thanks much

pauwlsky commented 7 years ago

Hi again,

was wondering if one of the plugin wikitude maintainers had time to assist with this issue, it is currently a large blocker.

Thanks for the help

danielguttenberg commented 7 years ago

Hi,

so far, this doesn't ring a bell yet.

Do you maybe have something for me to build, run and look at? Preferably a small project that demonstrates the issue.

Ideally, I'd like you to reproduce the issue in our Cordova sample app or provide the steps required for me to do so.

Daniel

pauwlsky commented 7 years ago

Thanks for the response @danielguttenberg,

I would like to send you the project so you could take a look but unfortunately cannot. I can try to explain how the application is structured and how we are loading the wikitude plugin though.

Here is the project structure that concerns how wikitude is being loaded.

react.js cordova application www dir

-www
    -ar
        -scripts
            -ar.js
    -src
        -components
            -arView
                -indexArView.js
                -wikitudeLaucher.js
        -...other dirs
        -bundle.js
        -bundleAr.js
        -index.js
        -inexAr.js
    -index.html
    -indexAr.html

cordova is loading the wikitude plugin in index.js, which mount a react router. The react components that are mounting the AR world are indexArView.js and wikitudeLauncher.js. All of this is bundled into bundle.js and loaded in the loaded index.html webview.

Here is the code for those files: index.html

<!DOCTYPE html>
<html>
  <head>
    <script>
(function(n,t){"use strict";function r(n){a[a.length]=n}function k(n){var t=new RegExp(" ?\\b"+n+"\\b");c.className=c.className.replace(t,"")}function p(n,t){for(var i=0,r=n.length;i<r;i++)t.call(n,n[i],i)}function tt(){var t,e,f,o;c.className=c.className.replace(/ (w-|eq-|gt-|gte-|lt-|lte-|portrait|no-portrait|landscape|no-landscape)\d+/g,""),t=n.innerWidth||c.clientWidth,e=n.outerWidth||n.screen.width,u.screen.innerWidth=t,u.screen.outerWidth=e,r("w-"+t),p(i.screens,function(n){t>n?(i.screensCss.gt&&r("gt-"+n),i.screensCss.gte&&r("gte-"+n)):t<n?(i.screensCss.lt&&r("lt-"+n),i.screensCss.lte&&r("lte-"+n)):t===n&&(i.screensCss.lte&&r("lte-"+n),i.screensCss.eq&&r("e-q"+n),i.screensCss.gte&&r("gte-"+n))}),f=n.innerHeight||c.clientHeight,o=n.outerHeight||n.screen.height,u.screen.innerHeight=f,u.screen.outerHeight=o,u.feature("portrait",f>t),u.feature("landscape",f<t)}function it(){n.clearTimeout(b),b=n.setTimeout(tt,50)}var y=n.document,rt=n.navigator,ut=n.location,c=y.documentElement,a=[],i={screens:[240,320,480,640,768,800,1024,1280,1440,1680,1920],screensCss:{gt:!0,gte:!1,lt:!0,lte:!1,eq:!1},browsers:[{ie:{min:6,max:11}}],browserCss:{gt:!0,gte:!1,lt:!0,lte:!1,eq:!0},html5:!0,page:"-page",section:"-section",head:"head"},v,u,s,w,o,h,l,d,f,g,nt,e,b;if(n.head_conf)for(v in n.head_conf)n.head_conf[v]!==t&&(i[v]=n.head_conf[v]);u=n[i.head]=function(){u.ready.apply(null,arguments)},u.feature=function(n,t,i){return n?(Object.prototype.toString.call(t)==="[object Function]"&&(t=t.call()),r((t?"":"no-")+n),u[n]=!!t,i||(k("no-"+n),k(n),u.feature()),u):(c.className+=" "+a.join(" "),a=[],u)},u.feature("js",!0),s=rt.userAgent.toLowerCase(),w=/mobile|android|kindle|silk|midp|phone|(windows .+arm|touch)/.test(s),u.feature("mobile",w,!0),u.feature("desktop",!w,!0),s=/(chrome|firefox)[ \/]([\w.]+)/.exec(s)||/(iphone|ipad|ipod)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(android)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(webkit|opera)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(msie) ([\w.]+)/.exec(s)||/(trident).+rv:(\w.)+/.exec(s)||[],o=s[1],h=parseFloat(s[2]);switch(o){case"msie":case"trident":o="ie",h=y.documentMode||h;break;case"firefox":o="ff";break;case"ipod":case"ipad":case"iphone":o="ios";break;case"webkit":o="safari"}for(u.browser={name:o,version:h},u.browser[o]=!0,l=0,d=i.browsers.length;l<d;l++)for(f in i.browsers[l])if(o===f)for(r(f),g=i.browsers[l][f].min,nt=i.browsers[l][f].max,e=g;e<=nt;e++)h>e?(i.browserCss.gt&&r("gt-"+f+e),i.browserCss.gte&&r("gte-"+f+e)):h<e?(i.browserCss.lt&&r("lt-"+f+e),i.browserCss.lte&&r("lte-"+f+e)):h===e&&(i.browserCss.lte&&r("lte-"+f+e),i.browserCss.eq&&r("eq-"+f+e),i.browserCss.gte&&r("gte-"+f+e));else r("no-"+f);r(o),r(o+parseInt(h,10)),i.html5&&o==="ie"&&h<9&&p("abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|progress|section|summary|time|video".split("|"),function(n){y.createElement(n)}),p(ut.pathname.split("/"),function(n,u){if(this.length>2&&this[u+1]!==t)u&&r(this.slice(u,u+1).join("-").toLowerCase()+i.section);else{var f=n||"index",e=f.indexOf(".");e>0&&(f=f.substring(0,e)),c.id=f.toLowerCase()+i.page,u||r("root"+i.section)}}),u.screen={height:n.screen.height,width:n.screen.width},tt(),b=0,n.addEventListener?n.addEventListener("resize",it,!1):n.attachEvent("onresize",it)})(window);
    </script>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="cordova.js"></script>
    <link rel="stylesheet" href="node_modules/onsenui/css/onsenui.css"></link>
    <link rel="stylesheet" href="node_modules/onsenui/css/onsen-css-components.css"></link>
    <meta http-equiv="Content-Security-Policy" content="default-src * gap://ready file: blob: data: wss://*.firebase.io; style-src 'self' 'unsafe-inline' blob:; script-src http://connect.facebook.net https://cdn.firebase.com https://*.firebaseio.com https://*.firebaseapp.com https://www.googleapis.com 'self' 'unsafe-inline' 'unsafe-eval'">
  </head>
  <body>
    <div class="container"></div>
  </body>
  <script src="bundle.js"></script>
</html>

index.js


/**
 * @file index.js
 * @description application entry point
 */

import...
let wikitudePlugin;

document.addEventListener("deviceready", function() {

  wikitudePlugin = cordova.require("com.wikitude.phonegap.WikitudePlugin.WikitudePlugin");

  // Database
  Firebase.init();

  // Location Tracking
  var locationTracker = new LocationTracker(store);
  locationTracker.start();

  // React Router
  AppRouter.init(store);
}, false);

//being exported to the rest of the index.js app to use. 
export {wikitudePlugin}

indexArView.js


import { wikitudePlugin } from '../../index';
import WikitudeLauncher from './wikitudeLauncher.js';
import ...

class IndexArView extends Component {

  constructor(props) {
    super(props);
    this.state = { userVerified: false, cameraAccess: false};
    this.markieStream = null;
  }

  componentWillMount() {
    this.verifyUser();
  }

  componentDidMount() {
    this.setState({ cameraAccess: false});
    this.refs.loadingOverlay.show('Loading AR Experience', false);
    wikitudePlugin.isDeviceSupported(
      () => this.onWikitudeIsSupported(),
      (err) => this.onWikitudeIsNotSupported(err),
      ["image_tracking", "geo" ]
    );
  }

  componentWillReceiveProps(nextProps) {
    // console.log('nextProps', nextProps);
    this.setLoadingOverlay(nextProps.applicationIsLoading);
  }

  /**
   * @method
   * @description either show's or hides the loading overlay depending on state
   */
  setLoadingOverlay(applicationIsLoading) {
    if (applicationIsLoading.isLoading) {
      if(!applicationIsLoading.homeScreenLink) {
        applicationIsLoading.homeScreenLink = false;
      }
      this.refs.loadingOverlay.show(applicationIsLoading.context, applicationIsLoading.homeScreenLink);
    } else {
      this.refs.loadingOverlay.hide();
    }
  }

  /**
   * @method
   * @description callback function when the device does not support wikitude
   */
  onWikitudeIsSupported() {
    wikitudePlugin.requestAccess(
      // Success Callback
      () => this.onWikitudeIsAuthorized(),
      // Error Callback
      (err) => this.onWikitudeIsNotAuthorized(err),
      ["image_tracking", "geo"]
    );
  }

   onWikitudeIsNotSupported(errorMessage) {
    // Device is not supported
    alert('Device is not supported. Reason: ' + errorMessage);
    hashHistory.push('/IndexUserProfile');
  }

   onWikitudeIsAuthorized() {
    //  console.log('wikitude is authorized!');
    this.setState({cameraAccess: true});
    // this.props.setApplicationIsLoading(false);
   }

    onWikitudeIsNotAuthorized(error) {
      hashHistory.push('/IndexError');
    }

  verifyUser() {
    if ( this.props.applicationUser != null && 'id' in this.props.applicationUser ) {
      this.setState({userVerified: true});
      this.initializeMarkieStream();
    } else {
      hashHistory.push('/indexIntro');
    }
  }

  initializeMarkieStream() {
    this.markieStream = new MarkieSteam(store);
  }

    componentWillUnmount() {
      this.markieStream.close();
      this.markieStream = null;
    }

  render() {
    if (this.state.userVerified && this.state.cameraAccess) {
      return (
        <OnsPage id="ARView_Index">
          <WikitudeLauncher />
          <LoadingOverlay ref="loadingOverlay" />
        </OnsPage>
      );
    } else {
      return (
        <div>
          <LoadingOverlay ref="loadingOverlay" />
        </div>
      );
    }
  }

}

function mapDispatchToProps...

function mapStateToProps...

export default connect(mapStateToProps, mapDispatchToProps)(IndexArView);

wikitudeLauncher.js

/**
 * @file components/arview/WikitudeLauncher.js
 */

import { wikitudePlugin } from '../../index';
import ...

class WikitudeLauncher extends Component {

  constructor(props) {
    super(props);
    this.sendLoadedEvent = this.sendLoadedEvent.bind(this);
    this.loadMarkies = this.loadMarkies.bind(this);
  }

  componentWillUnmount() {
    document.removeEventListener("followingLoadeduserId" + this.props.applicationUser.id, this.sendLoadedEvent, false);
    document.removeEventListener('newMarkie', this.loadMarkies, false);
  }

  sendLoadedEvent() {
    // Load images into AR View
    this.loadMarkies();
    document.addEventListener('newMarkie', this.loadMarkies, false);
    wikitudePlugin.callJavaScript("World.setLoaded()");
  }

  componentWillMount() {
    this.loadArchitectWorld();
  }

  /**
   * @method
   * @description loads the wikitudePluginArchitectWorld
   */
  loadArchitectWorld() {
    // Device is supported, load the experience
    wikitudePlugin.loadARchitectWorld(
        // Success Callback
        (loadedUrl) => this.onWikitudeLoaded(loadedUrl),
        // Error Callback
        (err) => this.onWikitudeError(err),
        // Experience Path
        'www/indexAr.html',
        // Capabilities
        ["image_tracking", "geo"],
        // Config
        { "camera_position": "back" }
    );
  }

  ... other methods

  /**
   * @method
   * @description callback function when wikitude has loaded successfully
   * @param {String} loadedUrl - the loaded url sent from wikitude
   */
  onWikitudeLoaded(loadedUrl) {
    console.log('wikitudeLoaded loadedUrl', loadedUrl);
    this.props.setUserFollowingRequests(this.props.applicationUser);
    document.addEventListener("followingLoadeduserId" + this.props.applicationUser.id, this.sendLoadedEvent, false);

    // Set the ready event
    wikitudePlugin.callJavaScript('var readyEvent = new Event("arReady")');
    wikitudePlugin.callJavaScript('document.dispatchEvent(readyEvent)');

    // Load the AR Radar
    wikitudePlugin.callJavaScript('World.addRadar()');
    this.props.setApplicationIsLoading(false);

  }

  /**
   * @method
   * @description callback function when wikitude has not loaded successfully, redirects to error page.
   * @param {String} errorMessage- the error that ocurred when trying to launch wikitude
   */
  onWikitudeError(errorMessage) {
    console.log('onWikitude error', errorMessage, wikitudePlugin); 
    wikitudePlugin.close();
    hashHistory.push('/WikitudeErrorRedirect');
  }

  render() {
    return (
      <div id="ARView_Wikitude">
      </div>
    );
  }
}

function mapDispatchToProps...
  return bindActionCreators(actionCreators, dispatch);
}

function mapStateToProps...

export default connect(mapStateToProps, mapDispatchToProps)(WikitudeLauncher);

indexAr.html

<!DOCTYPE html>
<html>
  <head>
    <base href="./">
    <script src="architect://architect.js"></script>
    <!-- <script src="https://www.wikitude.com/libs/architect.js"></script> -->
    <script>
(function(n,t){"use strict";function r(n){a[a.length]=n}function k(n){var t=new RegExp(" ?\\b"+n+"\\b");c.className=c.className.replace(t,"")}function p(n,t){for(var i=0,r=n.length;i<r;i++)t.call(n,n[i],i)}function tt(){var t,e,f,o;c.className=c.className.replace(/ (w-|eq-|gt-|gte-|lt-|lte-|portrait|no-portrait|landscape|no-landscape)\d+/g,""),t=n.innerWidth||c.clientWidth,e=n.outerWidth||n.screen.width,u.screen.innerWidth=t,u.screen.outerWidth=e,r("w-"+t),p(i.screens,function(n){t>n?(i.screensCss.gt&&r("gt-"+n),i.screensCss.gte&&r("gte-"+n)):t<n?(i.screensCss.lt&&r("lt-"+n),i.screensCss.lte&&r("lte-"+n)):t===n&&(i.screensCss.lte&&r("lte-"+n),i.screensCss.eq&&r("e-q"+n),i.screensCss.gte&&r("gte-"+n))}),f=n.innerHeight||c.clientHeight,o=n.outerHeight||n.screen.height,u.screen.innerHeight=f,u.screen.outerHeight=o,u.feature("portrait",f>t),u.feature("landscape",f<t)}function it(){n.clearTimeout(b),b=n.setTimeout(tt,50)}var y=n.document,rt=n.navigator,ut=n.location,c=y.documentElement,a=[],i={screens:[240,320,480,640,768,800,1024,1280,1440,1680,1920],screensCss:{gt:!0,gte:!1,lt:!0,lte:!1,eq:!1},browsers:[{ie:{min:6,max:11}}],browserCss:{gt:!0,gte:!1,lt:!0,lte:!1,eq:!0},html5:!0,page:"-page",section:"-section",head:"head"},v,u,s,w,o,h,l,d,f,g,nt,e,b;if(n.head_conf)for(v in n.head_conf)n.head_conf[v]!==t&&(i[v]=n.head_conf[v]);u=n[i.head]=function(){u.ready.apply(null,arguments)},u.feature=function(n,t,i){return n?(Object.prototype.toString.call(t)==="[object Function]"&&(t=t.call()),r((t?"":"no-")+n),u[n]=!!t,i||(k("no-"+n),k(n),u.feature()),u):(c.className+=" "+a.join(" "),a=[],u)},u.feature("js",!0),s=rt.userAgent.toLowerCase(),w=/mobile|android|kindle|silk|midp|phone|(windows .+arm|touch)/.test(s),u.feature("mobile",w,!0),u.feature("desktop",!w,!0),s=/(chrome|firefox)[ \/]([\w.]+)/.exec(s)||/(iphone|ipad|ipod)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(android)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(webkit|opera)(?:.*version)?[ \/]([\w.]+)/.exec(s)||/(msie) ([\w.]+)/.exec(s)||/(trident).+rv:(\w.)+/.exec(s)||[],o=s[1],h=parseFloat(s[2]);switch(o){case"msie":case"trident":o="ie",h=y.documentMode||h;break;case"firefox":o="ff";break;case"ipod":case"ipad":case"iphone":o="ios";break;case"webkit":o="safari"}for(u.browser={name:o,version:h},u.browser[o]=!0,l=0,d=i.browsers.length;l<d;l++)for(f in i.browsers[l])if(o===f)for(r(f),g=i.browsers[l][f].min,nt=i.browsers[l][f].max,e=g;e<=nt;e++)h>e?(i.browserCss.gt&&r("gt-"+f+e),i.browserCss.gte&&r("gte-"+f+e)):h<e?(i.browserCss.lt&&r("lt-"+f+e),i.browserCss.lte&&r("lte-"+f+e)):h===e&&(i.browserCss.lte&&r("lte-"+f+e),i.browserCss.eq&&r("eq-"+f+e),i.browserCss.gte&&r("gte-"+f+e));else r("no-"+f);r(o),r(o+parseInt(h,10)),i.html5&&o==="ie"&&h<9&&p("abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|progress|section|summary|time|video".split("|"),function(n){y.createElement(n)}),p(ut.pathname.split("/"),function(n,u){if(this.length>2&&this[u+1]!==t)u&&r(this.slice(u,u+1).join("-").toLowerCase()+i.section);else{var f=n||"index",e=f.indexOf(".");e>0&&(f=f.substring(0,e)),c.id=f.toLowerCase()+i.page,u||r("root"+i.section)}}),u.screen={height:n.screen.height,width:n.screen.width},tt(),b=0,n.addEventListener?n.addEventListener("resize",it,!1):n.attachEvent("onresize",it)})(window);
    </script>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="cordova.js"></script>
    <link rel="stylesheet" href="node_modules/onsenui/css/onsenui.css"></link>
    <link rel="stylesheet" href="node_modules/onsenui/css/onsen-css-components.css"></link>
    <meta http-equiv="Content-Security-Policy" content="default-src * gap://ready file: blob: data: wss://*.firebase.io; style-src 'self' 'unsafe-inline' blob:; script-src http://connect.facebook.net https://cdn.firebase.com https://*.firebaseio.com https://*.firebaseapp.com https://www.googleapis.com 'self' 'unsafe-inline' 'unsafe-eval'">
  </head>
  <body class="ar__body">
    <div class="container"></div>
  </body>
  <script src="ar/scripts/arWorld.js"></script>
  <script src="bundleAr.js"></script>
</html>

I know this is a lot to read, but if you can take a look at the application structure and have any ideas about where the issue may be arising it would be much appreciated.

AndreasSchacherbauerWikitude commented 7 years ago

hi @pauwlsky, did you already tried to load an Architect World in a Cordova application that doesn't use react? Something like our Wikitude Cordova example app. I just want to avoid that something like react influences the initial integration of our SDK.

Another question: Are you using the latest version of the Wikitude Cordova plugin? I'm asking because the error message you mentioned in the title is not a string in any of our repos (according to grep).

Best regards, Andreas

pauwlsky commented 7 years ago

Hello @AndreasSchacherbauerWikitude,

Thanks for responding to my thread. Haven't tried integrating the plugin with a non react app. But to give you some back story on my situation, I have been put on a project that is now in beta that is a Cordova React app, the majority of the code and functionality is already finished and for the most part the plugin has been working just fine.

The issue occurs randomly when loading the AR world, there has been no pattern we can find around when or why this error occurs after closing the Wikitude ARworld and then navigating back to the part of the app that opens it.

One method that will usually resolve the bug, is routing the user to to a loading screen after the error, and then setting a timeout to attempt the ARWorld load again. This can sometimes cause a loop of successive errors where the app is unable to load indexAR.html, but the app is always able to eventually load it. This solution is NOT good, to say the least.

We are using WikitudePlugin version 6.1.0 with Cordova version 6.5.0 and Cordova ios version 4.4.0. Thanks again

pauwlsky commented 7 years ago

Hello again,

Started making improvements again to the current state of this project and am still working to resolve this issue.

I did just update to the latest release of the plugin (7.0.0), but am still getting the same error. On further research I've come across why this error can occur in the apple developer forums:

https://forums.developer.apple.com/thread/64841

One of the developers on our team with more swift experience is trying to resolve, but any recommendations your team has on further troubleshooting is appreciated.

Thanks

pauwlsky commented 6 years ago

@AndreasSchacherbauer one issue I realized above, cordova.js is being included in indexAr.js, which I've read could be an issue? We have not been using any cordova functionality in the AR world since you cannot do this, but might loading these scripts cause some issue in loading the AR world?

AndreasSchacherbauerWikitude commented 6 years ago

@pauwlsky , Where is indexAr.js coming from? it's not part of any Wikitude Cordova project/example (As far as I can see from a look at the repositories).

pauwlsky commented 6 years ago

@AndreasSchacherbauer indexAr.js is one of the source files in our project. Basically, this is the react web app and the components that it made up of which are rendered in indexAr.html

Please see my explanation above of the project structure.

We think that we have solved the issue for the time being by removing cordova.js from indexAr.html, but are continuing to watch for it.