Cordova + ionic 0.9.23 'device plugin required'

i have the same problem here as well. tried also remove and add and still the same error. with ionic 0.9.21 it wasn’t

Did you use the ionic cli?

no. i just copied out the file and putted in my project folder.

Could you do the same via ionic cli?

I noticed this in an existing project I had and then to help in isolating the issue I created a new project using "ionic start " command. I didn’t alter anything within the project. I added android as the platform and did a build and then deployed to the device.

It looks like it is calling platform.detect() before cordova is initialized. I have added a breakpoint in the platform.js device function and it appears that window.device is undefined at the time it is called. But if I check for the variable after initialization it is defined.

Also ‘cordova plugin ls’ shows that the device plugin is configured and I can access it from the console after it is initialized. I am using ionic v0.9.23, cordova 3.3.1-0.4.2 and android 4.4.2. Below is the stack trace from the where the error is logged.

ionic.Platform.device (ionic.js:1801)
ionic.Platform.platform (ionic.js:1843)
ionic.Platform.is (ionic.js:1868)
ionic.Platform.isAndroid (ionic.js:1838)
initScroll (ionic-angular.js:1390)
(anonymous function) (ionic-angular.js:1371)
$get.Scope.$broadcast (angular.js:12220)
updateView (ionic-angular.js:3038)
directive.compile (ionic-angular.js:2995)
nodeLinkFn (angular.js:6224)
compositeLinkFn (angular.js:5630)
compositeLinkFn (angular.js:5637)
publicLinkFn (angular.js:5539)
(anonymous function) (ionic-angular.js:2468)
$get.Scope.$digest (angular.js:11789)
$get.Scope.$apply (angular.js:12042)
done (angular.js:7824)
completeRequest (angular.js:8007)
xhr.onreadystatechange (angular.js:7963)
1 Like

Do you have <script src="cordova.js"> before ionic in your html file?

In my case, I have seen this issue on two different apps. In my app, I have cordova.js before ionic and I also am using the default app created by “ionic start” command. In initial code created by the command ionic.js appears before cordova.js. The problem occurs in both cases.

And the problem only exists with ionic? If you create a app only with cordova/phonegap and add android as platform evertyhing works?

I resolved this by manually bootstrapping app with angular.bootstrap after ‘deviceready’ event. Basically - when using ng-app="myApp" angular initializes itself before ‘ondeviceready’ event thus window.device is empty thus all calls to ionic.Platform.is{Android,…} are failing.

I created a new cordova app, added the device plugin, added android as a platform, and I edited the default index.js to log whether window.device is defined in the receivedEvent function. It worked as expected and showed that device is defined. So this appears to be in the latest release of Ionic. In my existing project I had not seen this in the past only after updating to 0.9.23.

I do realize I can bootstrap the app myself but that is just a workaround. I was posting to provide additional details since this occurs even in the default app create by the ‘ionic start’ and might be confusing to people getting started with Ionic.

How do I bootstrap it myself? I am facing this same problem. I created the ionic framework in the console on my ubuntu VM and then brought it into Visual Studio because I am using Telerik’s App Builder. It is working beautifully in the emulator but I am getting the error:

device plugin required ionic.js:1824
ionic.Platform.device ionic.js:1824

device: function() {
      if(window.device) return window.device;
      if(this.isCordova()) console.error('device plugin required');
device plugin required (this is the error message)
      return {};

I do have cordova.js included ABOVE ionic.js. I had to manually move it, by default it is generated below ionic.js.

I found this page on Angular Bootstrap and used it in my index.html.

    <script>
        angular.element(document).ready(function () {
            angular.bootstrap(document, ['starter']);
        });
    </script>

But the same exact thing happens. It says the device isn’t defined. It is an enabled plugin using Teleriks interface for plugins. When I disable it I get 5 errors an when I enable it there is only 1 error so I know it is using those configurations.

Edit: I am using ionic v0.9.24

You can do something like the following:

(function (window, document) {

  function onWindowLoad() {
    if (!(!window.cordova && !window.PhoneGap && !window.phonegap)) {
      // on device add ready listener
      document.addEventListener('deviceready', onDeviceReady, false);
    } else {
      // on browser trigger onDeviceReady
      onDeviceReady();
    }
    window.removeEventListener('load', onWindowLoad, false);
  }
  window.addEventListener('load', onWindowLoad, false);

  function onDeviceReady() {
    // bootstrap app
    angular.element(document).ready(function () {
      angular.bootstrap(document, ['starter']);
    });
    document.removeEventListener('deviceready', onDeviceReady, false);
  }
})(window, document);

This confirms that the document is loaded and cordova is ready if running on the device. Then also remove the ng-app=‘starter’ from your markup.

Thank you! :smiley: I appreciate it

I am new to angular and ionic. Can you explain in detail how did you resolve this issue?

Not sure if this has been resolved…

I have used std cordova with another framework, I’m wanting to move to this … but its a deal breaker …

I use this approach in th past … with a angular bootrap method …

    // include angular loader, which allows the files to load in any order

    /*
 AngularJS v1.2.10
 (c) 2010-2014 Google, Inc. http://angularjs.org
 License: MIT
*/
    (function() {
        'use strict';

        function d(a) {
            return function() {
                var c = arguments[0],
                    b, c = "[" + (a ? a + ":" : "") + c + "] http://errors.angularjs.org/1.2.10/" + (a ? a + "/" : "") + c;
                for (b = 1; b < arguments.length; b++) c = c + (1 == b ? "?" : "&") + "p" + (b - 1) + "=" + encodeURIComponent("function" == typeof arguments[b] ? arguments[b].toString().replace(/ \{[\s\S]*$/, "") : "undefined" == typeof arguments[b] ? "undefined" : "string" != typeof arguments[b] ? JSON.stringify(arguments[b]) : arguments[b]);
                return Error(c)
            }
        }(function(a) {
            var c = d("$injector"),
                b = d("ng");
            a = a.angular ||
                (a.angular = {});
            a.$$minErr = a.$$minErr || d;
            return a.module || (a.module = function() {
                var a = {};
                return function(e, d, f) {
                    if ("hasOwnProperty" === e) throw b("badname", "module");
                    d && a.hasOwnProperty(e) && (a[e] = null);
                    return a[e] || (a[e] = function() {
                        function a(c, d, e) {
                            return function() {
                                b[e || "push"]([c, d, arguments]);
                                return g
                            }
                        }
                        if (!d) throw c("nomod", e);
                        var b = [],
                            h = [],
                            k = a("$injector", "invoke"),
                            g = {
                                _invokeQueue: b,
                                _runBlocks: h,
                                requires: d,
                                name: e,
                                provider: a("$provide", "provider"),
                                factory: a("$provide", "factory"),
                                service: a("$provide",
                                    "service"),
                                value: a("$provide", "value"),
                                constant: a("$provide", "constant", "unshift"),
                                animation: a("$animateProvider", "register"),
                                filter: a("$filterProvider", "register"),
                                controller: a("$controllerProvider", "register"),
                                directive: a("$compileProvider", "directive"),
                                config: k,
                                run: function(a) {
                                    h.push(a);
                                    return this
                                }
                            };
                        f && k(f);
                        return g
                    }())
                }
            }())
        })(window)
    })(window);
    //# sourceMappingURL=angular-loader.min.js.map

    // include a third-party async loader library
    /*!
     * $script.js v1.3
     * https://github.com/ded/script.js
     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
     * Follow our software http://twitter.com/dedfat
     * License: MIT
     */
    ! function(a, b, c) {
        function t(a, c) {
            var e = b.createElement("script"),
                f = j;
            e.onload = e.onerror = e[o] = function() {
                e[m] && !/^c|loade/.test(e[m]) || f || (e.onload = e[o] = null, f = 1, c())
            }, e.async = 1, e.src = a, d.insertBefore(e, d.firstChild)
        }

        function q(a, b) {
            p(a, function(a) {
                return !b(a)
            })
        }
        var d = b.getElementsByTagName("head")[0],
            e = {}, f = {}, g = {}, h = {}, i = "string",
            j = !1,
            k = "push",
            l = "DOMContentLoaded",
            m = "readyState",
            n = "addEventListener",
            o = "onreadystatechange",
            p = function(a, b) {
                for (var c = 0, d = a.length; c < d; ++c)
                    if (!b(a[c])) return j;
                return 1
            };
        !b[m] && b[n] && (b[n](l, function r() {
            b.removeEventListener(l, r, j), b[m] = "complete"
        }, j), b[m] = "loading");
        var s = function(a, b, d) {
            function o() {
                if (!--m) {
                    e[l] = 1, j && j();
                    for (var a in g) p(a.split("|"), n) && !q(g[a], n) && (g[a] = [])
                }
            }

            function n(a) {
                return a.call ? a() : e[a]
            }
            a = a[k] ? a : [a];
            var i = b && b.call,
                j = i ? b : d,
                l = i ? a.join("") : b,
                m = a.length;
            c(function() {
                q(a, function(a) {
                    h[a] ? (l && (f[l] = 1), o()) : (h[a] = 1, l && (f[l] = 1), t(s.path ? s.path + a + ".js" : a, o))
                })
            }, 0);
            return s
        };
        s.get = t, s.ready = function(a, b, c) {
            a = a[k] ? a : [a];
            var d = [];
            !q(a, function(a) {
                e[a] || d[k](a)
            }) && p(a, function(a) {
                return e[a]
            }) ? b() : ! function(a) {
                g[a] = g[a] || [], g[a][k](b), c && c(d)
            }(a.join("|"));
            return s
        };
        var u = a.$script;
        s.noConflict = function() {
            a.$script = u;
            return this
        }, typeof module != "undefined" && module.exports ? module.exports = s : a.$script = s
    }(this, document, setTimeout)

    // load all of the dependencies asynchronously.
    $script([
        'lib/angular/angular.js',
        'lib/angular/angular-animate.js',
        'lib/angular/angular-route.js',
        'lib/angular/angular-touch.js',
        'js/app.js',
        'js/services.js',
        'js/controllers.js',
        'js/filters.js',
        'js/directives.js',
        'js/Ctrl_Map.js',
        'js/Ctrl_Layers.js',
        'js/Ctrl_Settings.js',
        'js/Ctrl_Downloads.js'
    ], function() {
        // when all is done, execute bootstrap angular application
        // wait for cordova angular.bootstrap(document, ['starter']);
        if (isNative == 'true') {
            app.initialize();
        } else {
            angular.bootstrap(document, ['starter']);
        }
    });

    var app = {
        // Application Constructor
        initialize: function() {
            this.bindEvents();
        },
        // Bind any events that are required on startup. Common events are:
        // 'load', 'deviceready', 'offline', and 'online'.
        bindEvents: function() {
            document.addEventListener('load', this.onLoad, false);
            document.addEventListener('deviceready', this.onDeviceReady, false);
            window.addEventListener("orientationchange", orientationChange, true);
        },
        onLoad: function() {
             console.log('um at onload html state');
        },
        // deviceready Event Handler
        onDeviceReady: function() {
            console.log('um at cordova ready state');
            angular.bootstrap(document, ['starter']);
    	   //start file helper
        //fileSystemHelper = new FileSystemHelper();
        }
    };

this seems to work, as in the GPS is actually using the native code in cordova, but I still get errors relating to device even if i switch tabs?

  // include angular loader, which allows the files to load in any order

/*
 AngularJS v1.2.10
 (c) 2010-2014 Google, Inc. http://angularjs.org
 License: MIT
 */
(function() {
 'use strict';
 
 function d(a) {
 return function() {
 var c = arguments[0],
 b, c = "[" + (a ? a + ":" : "") + c + "] http://errors.angularjs.org/1.2.10/" + (a ? a + "/" : "") + c;
 for (b = 1; b < arguments.length; b++) c = c + (1 == b ? "?" : "&") + "p" + (b - 1) + "=" + encodeURIComponent("function" == typeof arguments[b] ? arguments[b].toString().replace(/ \{[\s\S]*$/, "") : "undefined" == typeof arguments[b] ? "undefined" : "string" != typeof arguments[b] ? JSON.stringify(arguments[b]) : arguments[b]);
 return Error(c)
 }
 }(function(a) {
   var c = d("$injector"),
   b = d("ng");
   a = a.angular ||
   (a.angular = {});
   a.$$minErr = a.$$minErr || d;
   return a.module || (a.module = function() {
                       var a = {};
                       return function(e, d, f) {
                       if ("hasOwnProperty" === e) throw b("badname", "module");
                       d && a.hasOwnProperty(e) && (a[e] = null);
                       return a[e] || (a[e] = function() {
                                       function a(c, d, e) {
                                       return function() {
                                       b[e || "push"]([c, d, arguments]);
                                       return g
                                       }
                                       }
                                       if (!d) throw c("nomod", e);
                                       var b = [],
                                       h = [],
                                       k = a("$injector", "invoke"),
                                       g = {
                                       _invokeQueue: b,
                                       _runBlocks: h,
                                       requires: d,
                                       name: e,
                                       provider: a("$provide", "provider"),
                                       factory: a("$provide", "factory"),
                                       service: a("$provide",
                                                  "service"),
                                       value: a("$provide", "value"),
                                       constant: a("$provide", "constant", "unshift"),
                                       animation: a("$animateProvider", "register"),
                                       filter: a("$filterProvider", "register"),
                                       controller: a("$controllerProvider", "register"),
                                       directive: a("$compileProvider", "directive"),
                                       config: k,
                                       run: function(a) {
                                       h.push(a);
                                       return this
                                       }
                                       };
                                       f && k(f);
                                       return g
                                       }())
                       }
                       }())
   })(window)
 })(window);
 //# sourceMappingURL=angular-loader.min.js.map
 
 // include a third-party async loader library
 /*!
  * $script.js v1.3
  * https://github.com/ded/script.js
  * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
  * Follow our software http://twitter.com/dedfat
  * License: MIT
  */
! function(a, b, c) {
    function t(a, c) {
        var e = b.createElement("script"),
        f = j;
        e.onload = e.onerror = e[o] = function() {
            e[m] && !/^c|loade/.test(e[m]) || f || (e.onload = e[o] = null, f = 1, c())
        }, e.async = 1, e.src = a, d.insertBefore(e, d.firstChild)
    }
    
    function q(a, b) {
        p(a, function(a) {
          return !b(a)
          })
    }
    var d = b.getElementsByTagName("head")[0],
    e = {}, f = {}, g = {}, h = {}, i = "string",
    j = !1,
    k = "push",
    l = "DOMContentLoaded",
    m = "readyState",
    n = "addEventListener",
    o = "onreadystatechange",
    p = function(a, b) {
        for (var c = 0, d = a.length; c < d; ++c)
        if (!b(a[c])) return j;
        return 1
    };
    !b[m] && b[n] && (b[n](l, function r() {
                           b.removeEventListener(l, r, j), b[m] = "complete"
                           }, j), b[m] = "loading");
                           var s = function(a, b, d) {
                               function o() {
                                   if (!--m) {
                                       e[l] = 1, j && j();
                                       for (var a in g) p(a.split("|"), n) && !q(g[a], n) && (g[a] = [])
                                   }
                               }
                               
                               function n(a) {
                                   return a.call ? a() : e[a]
                               }
                               a = a[k] ? a : [a];
                               var i = b && b.call,
                               j = i ? b : d,
                               l = i ? a.join("") : b,
                               m = a.length;
                               c(function() {
                                 q(a, function(a) {
                                   h[a] ? (l && (f[l] = 1), o()) : (h[a] = 1, l && (f[l] = 1), t(s.path ? s.path + a + ".js" : a, o))
                                   })
                                 }, 0);
                                 return s
                           };
                           s.get = t, s.ready = function(a, b, c) {
                               a = a[k] ? a : [a];
                               var d = [];
                               !q(a, function(a) {
                                  e[a] || d[k](a)
                                  }) && p(a, function(a) {
                                          return e[a]
                                          }) ? b() : ! function(a) {
                                   g[a] = g[a] || [], g[a][k](b), c && c(d)
                               }(a.join("|"));
                                          return s
                           };
                           var u = a.$script;
                           s.noConflict = function() {
                               a.$script = u;
                               return this
                           }, typeof module != "undefined" && module.exports ? module.exports = s : a.$script = s
}(this, document, setTimeout)

// load all of the dependencies asynchronously.
$script([
         'lib/ionic/js/ionic.js',
         'lib/ionic/js/angular/angular.js',
         'lib/ionic/js/angular/angular-animate.js',
         'lib/ionic/js/angular/angular-sanitize.js',
         'lib/ionic/js/angular-ui/angular-ui-router.js',
         'lib/ionic/js/ionic-angular.js',
         'js/app.js',
         'js/services.js',
         'js/controllers.js',
         'js/contrlMap.js'
         ], function() {
        // when all is done, execute bootstrap angular application
        // wait for cordova angular.bootstrap(document, ['starter']);
        app.initialize();
        });

</script>

For me the ‘device plugin required’ error went away with 0.9.25.

1 Like

Hi,

I’m using 0.9.26 version and the problem continues… How to fix it?

Detail: I used the ionic generator to create my project.

Did you install the Cordova device plugin?

What error are you getting?

“device plugin required”

I reinstall using pure ionic (via getting started) and everything works.
I’ll start develop using ionic and later i’ll see how to minify, uglify, etc… lol

thanks.