title: PhoneGap + Google Maps API v3 : Not displaying (at all) on Android
body: <p><strong>The Situation</strong></p>
  
  <p>I'm currently developing an app for a customer, who wishes to have a Google Maps integration. He wants the map to show the route from wherever the user is to his office. </p>
  
  <p>I'm working on a Windows 8, without any IDE (using Sublime Text 2).</p>
  
  <p>I've managed to get it working a) in my Chrome browser locally, b) in the Ripple Emulator for PhoneGap/Cordova >2.0.0. However, it simply will not work on my Android phone (HTC Sensation) whenever I try. It's driving me nuts and I'm just about to drop it and find some other, "dumber" solution (like a static map or the geo:url interface). </p>
  
  <p>Before I tried to actually implement the map, I ran the the PhoneGap Geolocation full example, found <a href="http://docs.phonegap.com/en/2.9.0/cordova_geolocation_geolocation.md.html#Geolocation" rel="nofollow noreferrer">here</a>. I noted that my Android Phone did display my current position (lat/long/timestamp etc.) correctly. Thus, I believe that the correct permissions (Location -> etc.) has been set on my phone.</p>
  
  <p><strong>The Problem</strong></p>
  
  <p>Google Maps does not show up at all on my Android Device. I see the red background (for debugging), so I know the height and width are fine. But I do not see any sign of google maps (no buttons, overlays, grids or anything).</p>
  
  <p><strong>The Code</strong></p>
  
  <p>HTML code for loading jQuery, Cordova and Maps API v3:</p>
  
  <pre><code>&lt;script type="text/javascript" src="js/jquery-1.10.0.min.js" &gt;&lt;/script&gt;
  &lt;script type="text/javascript" charset="utf-8" src="cordova.js"&gt;&lt;/script&gt;
  &lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&amp;sensor=true&amp;language=da"&gt;&lt;/script&gt;
  </code></pre>
  
  <p>This is the HTML I use to place the map:</p>
  
  <pre><code>&lt;div id="map-canvas"
      style="display:block;
              overflow:hidden;
              position:relative;
              border:1px solid #aaaaaa;
              width: 100%;
              height: 400px;
              background: red;"&gt;
  &lt;/div&gt;
  &lt;div id="map-panel" style="width:100%; height:90%; position:relative; "&gt;&lt;/div&gt;
  </code></pre>
  
  <p>And here is my full Google Maps JS (in its own file):</p>
  
  <pre><code>var map,
      userPosition,
      officeLocation,
      directionsDisplay,
      directionsService;
  
  google.maps.event.addDomListener(window, 'load', setup);
  
  function setup() {
      document.addEventListener("deviceready", onDeviceReady, false);
  
      function onDeviceReady() {
          navigator.geolocation.getCurrentPosition(onSuccess, onError, {enableHighAccuracy:true});
      }
  }
  
  function onSuccess(position) {
      userPosition = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
      navigator.notification.alert("Found user position");
  
      initializeMaps();
      //$('#map-canvas').css({'height': $(window).height()/2, 'width': '99%'});
  }
  
  function onError(error) {
      navigator.notification.alert("code: " + error.code + ",\n" +
                                   "message: " + error.message);
  }
  
  function initializeMaps() {
      directionsDisplay = new google.maps.DirectionsRenderer();
      directionsService = new google.maps.DirectionsService();
  
      officeLocation = new google.maps.LatLng(55.689403, 12.521281);
  
      var myOptions = {
          mapTypeId: google.maps.MapTypeId.ROADMAP,
          center: officeLocation
      };
  
      map = new google.maps.Map(document.getElementById('map-canvas'), myOptions);
      directionsDisplay.setMap(map);
  
      if (userPosition != '') {
          var userPosMarker = new google.maps.Marker({
              position: userPosition,
              map: map,
              title: "Din Placering"
          });
  
          calculateRoute();
      }
      else {
          navigator.notification.alert("userPosition is null");
      }
  }
  
  function calculateRoute() {
      //navigator.notification.alert("calculateRoute");
      var request = {
          origin: userPosition,
          destination: officeLocation,
          travelMode: google.maps.DirectionsTravelMode["DRIVING"]
      };
  
      directionsService.route(request, function(response, status) {
          if (status == google.maps.DirectionsStatus.OK) {
              directionsDisplay.setPanel(document.getElementById('map-panel'));
              directionsDisplay.setDirections(response);
  
              //navigator.notification.alert("Show directions");
          }
          else {
              navigator.notification.alert("Got status NOT OK from google");
          }
      });
  }
  
  function reloadGoogleMap() {
      if (map === null || map === undefined) {
          navigator.notification.alert("map is %s", map);
      }
      else {
          var currCenter = map.getCenter();
          google.maps.event.trigger(map, "resize");
          map.setCenter(currCenter);
          map.setZoom(12);
          //navigator.notification.alert("reloaded map");
      }
  }
  </code></pre>
  
  <p>This is my initialization code (placed at the bottom of my <em>head</em> tag):</p>
  
  <pre><code>&lt;script type="text/javascript" charset="utf-8"&gt;
      //navigator.notification.alert("listen for deviceready");
      document.addEventListener("deviceready", onDeviceReady, false);
  
      function onDeviceReady() {
          //navigator.notification.alert("device ready");
          ... 
          // calls other initialization functions
          ...
          initMaps();
          ..
      }
  &lt;/script&gt;
  </code></pre>
  
  <p>And I have these (among others) in my AndroidManifest.xml:</p>
  
  <pre><code>&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
  &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
  &lt;uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /&gt;
  &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
  </code></pre>
  
  <p>And I have these in my config.xml (located in /assets/www/config.xml):</p>
  
  <pre><code>&lt;access origin="*" /&gt;
  
  ...
  
  &lt;feature name="http://api.phonegap.com/1.0/device"/&gt;
  &lt;feature name="http://api.phonegap.com/1.0/geolocation"/&gt;
  &lt;feature name="http://api.phonegap.com/1.0/notification"/&gt;
  </code></pre>
  
  <p>It seems to my that my onSuccess method is never called, but I do not see any of the alerts stating that the user position is invalid. In fact, the only notification on my phone I <em>do</em> see is:</p>
  
  <pre><code>map is %s, undefined
  </code></pre>
  
  <p>In the ripple emulator I get the "Found user position" whenever I load the app.</p>
  
  <p>Please help!</p>
  
  <p>[EDIT]
  I forgot to mention that I'm using Adobe's <a href="http://build.phonegap.com" rel="nofollow noreferrer">http://build.phonegap.com</a> to actually build the application.</p>
  
  <p>[EDIT2]
  I now tried to use Google API key like so:</p>
  
  <pre><code>&lt;script src="http://maps.google.com/maps/api/js?key=AIzaSyB1uhDdWjtNEl9K35lJtuq5Sw2BjKR8-OM&amp;sensor=false" type="text/javascript"&gt;&lt;/script&gt;
  </code></pre>
  
  <p>But alas, no change. Still nothing.</p>
  
  <p>[EDIT3]</p>
  
  <p>Here is my full <code>androidManifest.xml</code>:</p>
  
  <pre><code>&lt;code&gt;
      &lt;?xml version="1.0" encoding="utf-8"?&gt;
      &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
                  package="com.alphastagestudios.danmarksflyttemand" android:versionName="1.0" android:versionCode="2" android:hardwareAccelerated="true"&gt;
              &lt;supports-screens
                      android:largeScreens="true"
                      android:normalScreens="true"
                      android:smallScreens="true"
                      android:xlargeScreens="true"
                      android:resizeable="true"
                      android:anyDensity="true"
                      /&gt;
  
              &lt;uses-permission android:name="android.permission.CAMERA" /&gt;
              &lt;uses-permission android:name="android.permission.VIBRATE" /&gt;
              &lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt;
              &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
              &lt;uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /&gt;
              &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
              &lt;uses-permission android:name="android.permission.RECEIVE_SMS" /&gt;
              &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
              &lt;uses-permission android:name="android.permission.RECORD_VIDEO"/&gt;
              &lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
              &lt;uses-permission android:name="android.permission.READ_CONTACTS" /&gt;
              &lt;uses-permission android:name="android.permission.WRITE_CONTACTS" /&gt;
              &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
              &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
              &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
              &lt;uses-permission android:name="android.permission.BROADCAST_STICKY" /&gt;
  
  
              &lt;application android:icon="@drawable/icon" android:label="@string/app_name"
                      android:hardwareAccelerated="true"
                      android:debuggable="true"&gt;
                      &lt;activity android:name="DanmarksFlyttemandApp" android:label="@string/app_name"
                                      android:theme="@android:style/Theme.Black.NoTitleBar"
                                      android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"&gt;
                              &lt;intent-filter&gt;
                                      &lt;action android:name="android.intent.action.MAIN" /&gt;
                                      &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
                              &lt;/intent-filter&gt;
                      &lt;/activity&gt;
              &lt;/application&gt;
  
              &lt;uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/&gt;
  
              &lt;permission android:name="com.alphastagestudios.danmarksflyttemand.permission.MAPS_RECEIVE" android:protectionLevel="signature"/&gt;
              &lt;uses-permission android:name="com.alphastagestudios.danmarksflyttemand.permission.MAPS_RECEIVE"/&gt;
      &lt;/manifest&gt;
  
  &lt;/code&gt;
  </code></pre>
  
  <p>[EDIT4]
  I now tried building a minimal example with PhoneGap geolocation and a basic google map. I built it manually through Eclipse with Cordova v. 2.9.0 (the newest). 
  Weird thing is, the PhoneGap geolocation example on its own worked fine, but when I introduce google maps code it all stopped working. I tried this minimal example with and without the google API key. No difference.</p>
  
  <p>This is the index.html I was using:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;title&gt;Device Properties Example&lt;/title&gt;
      &lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no"&gt;
      &lt;meta charset="utf-8"&gt;
  
      &lt;style&gt;
          body, html, #map-canvas {
              width: 100%;
              height: 400px;
              margin: 0;
              padding: 0;
          }
      &lt;/style&gt;
  
      &lt;script type="text/javascript" src="cordova.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&amp;sensor=false"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" charset="utf-8"&gt;
  
      // Wait for device API libraries to load
      document.addEventListener("deviceready", onDeviceReady, false);
  
      // device APIs are available
      function onDeviceReady() {
          navigator.geolocation.getCurrentPosition(onSuccess, onError);
      }
  
      // onSuccess Geolocation
      function onSuccess(position) {
          var element = document.getElementById('geolocation');
          element.innerHTML = 'Latitude: '           + position.coords.latitude              + '&lt;br /&gt;' +
                              'Longitude: '          + position.coords.longitude             + '&lt;br /&gt;' +
                              'Altitude: '           + position.coords.altitude              + '&lt;br /&gt;' +
                              'Accuracy: '           + position.coords.accuracy              + '&lt;br /&gt;' +
                              'Altitude Accuracy: '  + position.coords.altitudeAccuracy      + '&lt;br /&gt;' +
                              'Heading: '            + position.coords.heading               + '&lt;br /&gt;' +
                              'Speed: '              + position.coords.speed                 + '&lt;br /&gt;' +
                              'Timestamp: '          + position.timestamp                    + '&lt;br /&gt;';
          initMap();
      }
  
      // onError Callback receives a PositionError object
      function onError(error) {
          alert('code: '    + error.code    + '\n' +
                'message: ' + error.message + '\n');
      }
  
      var map,
          userPosition,
          officeLocation,
          directionsDisplay,
          directionsService;
  
      function initMap() {
          //directionsDisplay = new google.maps.DirectionsRenderer();
          //directionsService = new google.maps.DirectionsService();
  
          officeLocation = new google.maps.LatLng(55.689403, 12.521281);
          var myOptions = {
              mapTypeId: google.maps.MapTypeId.ROADMAP,
              center: officeLocation
          };
  
          map = new google.maps.Map(document.getElementById('map-canvas'), myOptions);
          //directionsDisplay.setMap(map);
      }
  
      &lt;/script&gt;
  
    &lt;/head&gt;
    &lt;body&gt;
      &lt;p id="geolocation"&gt;Finding geolocation...&lt;/p&gt;
  
      &lt;div id="map-canvas"&gt;&lt;/div&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>[EDIT5]
  I have now attempted to build the application with PhoneGap (Cordova)v. 2.6.0, 2.9.0 and 2.8.1 - none worked. The phone's geolocation works fine, but google maps does not show up. I only see the default grey background of where it should be. </p>