ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.02k stars 13.51k forks source link

Function inside ionic.Platform.ready() is never fired on android #1751

Closed ThiagoNP3 closed 10 years ago

ThiagoNP3 commented 10 years ago

I have an app that needs to use the cordova plugins in it's initialization process.

So I tried to do the following:

ionic.Platform.ready(function(){
  angular.bootstrap(document.getElementsByTagName('body')[0], ['myApp'])
});

But the function never gets called and my app does not initialize. On the IOS simulator and on google chrome, this works fine.

Any ideas?

perrygovier commented 10 years ago

Hey @ThiagoNP, is this in a starter app too? I'm seeing it fire on a basic project. Also, double check cordova's loading properly.

If that doesn't help, could you post an example of your project somewhere?

ThiagoNP3 commented 10 years ago

Yes, it's in the starter app. The cordova is loading properly, because if I put the ng-app directive in the body and set a timeout to do the initialization, it works and everything loads properly. The code that I need the plugins to be loaded is this:

var ws = new WebSocket("ws://78785cdf.ngrok.com");

Because there is not support for websocket in android < 4.4.

perrygovier commented 10 years ago

Thanks @ThiagoNP, what device are you seeing this on? Does it reproduce in the emulator? What version of android?

ThiagoNP3 commented 10 years ago

I tried it with a xt860 (motorola milestone 3 - stock - android 2.3) and in the emulator (android 4.4 api 19, and 4.3 api 18 - x86 images) both didn't fired the angular bootstrap.

I don't know if this is relevant, but here is the import order of the scripts:

    script src="lib/ionic/js/ionic.bundle.js"
    script src="cordova.js"
    script src="js/app.js"
    script src="js/controllers.js"
    script src="js/services.js" 

The bootstrap is in the app.js file.

perrygovier commented 10 years ago

Hey @ThiagoNP try switching the order of cordova and the ionic bundle.

ThiagoNP3 commented 10 years ago

@perrygovier I tried switching the order of the imports, but still no success

jimthedev commented 10 years ago

It was my impression that cordova.js should be last and at the end of the page, no?

ThiagoNP3 commented 10 years ago

Thanks, it worked now. So, we need to change the starter app to import it at the end of the page, or add this to the docs in case someone have this issue too, right?

jimthedev commented 10 years ago

@ThiagoNP correct. I've put in a pull request for this. Thanks for the reminder.

perrygovier commented 10 years ago

@jimthedev @ThiagoNP, it's working fine in my tests, regardless of where I position the cordova.js file. Are you able to provide a complete sample project that reproduces this? Also what device/android version are you seeing this on?

ThiagoNP3 commented 10 years ago

Here is the relevant code:

app.js:

ionic.Platform.ready(function(){
  try{
    angular.bootstrap(document.getElementsByTagName('body')[0], ['starter'])
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  }
  catch(e){
    alert(e)
  }
})
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a  attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.config(function($stateProvider, $urlRouterProvider) {
  // Ionic uses AngularUI Router which uses the concept of states
  // Learn more here: https://github.com/angular-ui/ui-router
  // Set up the various states which the app can be in.
  // Each state's controller can be found in controllers.js
  $stateProvider
    // setup an abstract state for the tabs directive
    .state('tab', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html"
    })
    // Each tab has its own nav history stack:
    .state('tab.dash', {
      url: '/dash',
      views: {
        'tab-dash': {
          templateUrl: 'templates/tab-dash.html',
          controller: 'DashCtrl'
        }
      }
    })
    .state('tab.downloads', {
      url: '/downloads',
      views: {
        'tab-downloads': {
          templateUrl: 'templates/tab-downloads.html',
          controller: 'FileDownloadCtrl'
        }
      }
    })
    .state('tab.download-detail', {
      url: '/download/:id',
      views: {
        'tab-downloads': {
          templateUrl: 'templates/download-detail.html',
          controller: 'ShowDownloadCtrl'
        }
      }
    })
    .state('tab.account', {
      url: '/account',
      views: {
        'tab-account': {
          templateUrl: 'templates/tab-account.html',
          controller: 'AccountCtrl'
        }
      }
    })
  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/tab/dash');
});

index.html:

|!DOCTYPE html|
|html|
  |head|
    |meta charset="utf-8"|
    |meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"|
    |title||/title|
    |link href="lib/ionic/css/ionic.css" rel="stylesheet"|
    |link href="css/style.css" rel="stylesheet"|
    |!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    |link href="css/ionic.app.css" rel="stylesheet"|
    --|
    |!-- cordova script (this will be a 404 during development) --|
    |!-- ionic/angularjs js --|
    |script src="lib/ionic/js/ionic.bundle.js"||/script|
    |!-- your app's js --|
    |script src="js/app.js"||/script|
    |script src="js/controllers.js"||/script|
    |script src="js/services.js"||/script|
  |/head|
  |body animation="slide-left-right-ios7"|
    |!--
      The nav bar that will be updated as we navigate between views.
    --|
    |ion-nav-bar class="bar-stable nav-title-slide-ios7"|
      |ion-nav-back-button class="button-icon icon  ion-ios7-arrow-back"|
        Back
      |/ion-nav-back-button|
    |/ion-nav-bar|
    |!--
      The views will be rendered in the |ion-nav-view| directive below
      Templates are in the /templates folder (but you could also
      have templates inline in this html file if you'd like).
    --|
    |ion-nav-view||/ion-nav-view|
    |script src="cordova.js"||/script|
  |/body|
|/html|

package.json:

{
  "name": "ionic-project",
  "version": "1.0.0",
  "description": "An Ionic project",
  "dependencies": {
    "gulp": "^3.5.6",
    "gulp-sass": "^0.7.1",
    "gulp-concat": "^2.2.0",
    "gulp-minify-css": "^0.3.0",
    "gulp-rename": "^1.2.0"
  },
  "devDependencies": {
    "bower": "^1.3.3",
    "gulp-jade": "^0.6.1",
    "gulp-util": "^2.2.14",
    "shelljs": "^0.3.0"
  }
}

bower.json:

{
  "name": "HelloIonic",
  "private": "true",
  "devDependencies": {
    "ionic": "driftyco/ionic-bower#1.0.0-beta.9"
  }
}

I am using the following plugins:

I think thats all the relevant code, this code sample was after the issue, but I think it can reproduce the issue. I cant post the entire project, because it is in my company repository now.

adamdbradley commented 10 years ago

@ThiagoNP what version of Android were you having this issue with? The order of the scripts "shouldn't" matter, which is why I'm curious to see if something else is wrong.

diaspar commented 10 years ago

I was having this problem all day. The only thing I found was a problem on the system.log (using the simulator).

ERROR: Plugin 'Device' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.

I found other threads, and I realized this may be related to the plugins and the way the platforms/ folder is created/updated. I ran this:

The system.log message disappeared and $ionicPlatform began working.

This is an educated guess: maybe the ionicPlatform service depends on the org.apache.cordova.device plugin in some way or its affected if there are plugin issues.

adamdbradley commented 10 years ago

@diaspar Was this problem only for iOS?

diaspar commented 10 years ago

I just tested on IOS.

adamdbradley commented 10 years ago

If reinstalled the device plugin worked then I'm going to call this closed. Thanks

pinocchio-geppetto commented 9 years ago

I refer to the post by ThiagoNP above, dated Jul 15, 2014.

I further refer to the code, reproduced here:

ionic.Platform.ready(function(){
    try{
        angular.bootstrap(document.getElementsByTagName('body')[0], ['starter'])

        if(window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if(window.StatusBar) {
            StatusBar.styleDefault();
        }
    }
   catch(e){
     alert(e)
   }
})

Look at the first 3 lines of the code. We have embed an "angular.bootstrap()" inside ionic.Platform.ready().

If angular does not bootstrap (assuming no ng-app="starter"), will ionic.Platform.ready() ever fire?

jimthedev commented 9 years ago

@slownslower The code shown would be used instead of having an ng-app="starter" on your body tag. Essentially angular.bootstrap does the same thing as ng-app except it does it using javascript. It is also sometimes referred to as manual bootstrapping. You can read a bit more about it here: http://icelab.com.au/articles/manually-bootstrapping-angularjs-for-asynchronous-loading-in-internet-explorer/