【问题标题】:PhoneGap + Google Maps API v3 : Not displaying (at all) on AndroidPhoneGap + Google Maps API v3:在 Android 上(根本)不显示
【发布时间】:2013-07-02 10:45:52
【问题描述】:

情况

我目前正在为希望集成 Google 地图的客户开发应用。他希望地图显示从用户所在的任何地方到他的办公室的路线。

我正在使用 Windows 8,没有任何 IDE(使用 Sublime Text 2)。

我已经设法让它在本地运行 a) 我的 Chrome 浏览器,b) 在 Ripple Emulator for PhoneGap/Cordova >2.0.0 中。但是,无论何时尝试,它都无法在我的 Android 手机 (HTC Sensation) 上运行。它让我发疯,我正要放弃它并找到其他一些“愚蠢”的解决方案(如静态地图或 geo:url 界面)。

在我尝试实际实现地图之前,我运行了 PhoneGap Geolocation 完整示例,发现 here。我注意到我的 Android 手机确实正确显示了我的当前位置(纬度/经度/时间戳等)。因此,我相信我的手机上已设置了正确的权限(位置 -> 等)。

问题

Google 地图根本没有显示在我的 Android 设备上。我看到红色背景(用于调试),所以我知道高度和宽度都很好。但我没有看到任何谷歌地图的迹象(没有按钮、叠加层、网格或任何东西)。

守则

用于加载 jQuery、Cordova 和 Maps API v3 的 HTML 代码:

<script type="text/javascript" src="js/jquery-1.10.0.min.js" ></script>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3&sensor=true&language=da"></script>

这是我用来放置地图的 HTML:

<div id="map-canvas"
    style="display:block;
            overflow:hidden;
            position:relative;
            border:1px solid #aaaaaa;
            width: 100%;
            height: 400px;
            background: red;">
</div>
<div id="map-panel" style="width:100%; height:90%; position:relative; "></div>

这是我完整的 Google Maps JS(在它自己的文件中):

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");
    }
}

这是我的初始化代码(放在我的 head 标签的底部):

<script type="text/javascript" charset="utf-8">
    //navigator.notification.alert("listen for deviceready");
    document.addEventListener("deviceready", onDeviceReady, false);

    function onDeviceReady() {
        //navigator.notification.alert("device ready");
        ... 
        // calls other initialization functions
        ...
        initMaps();
        ..
    }
</script>

我的 AndroidManifest.xml 中有这些(以及其他):

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />

我的 config.xml 中有这些(位于 /assets/www/config.xml):

<access origin="*" />

...

<feature name="http://api.phonegap.com/1.0/device"/>
<feature name="http://api.phonegap.com/1.0/geolocation"/>
<feature name="http://api.phonegap.com/1.0/notification"/>

在我看来,我的 onSuccess 方法从未被调用,但我没有看到任何表明用户位置无效的警报。事实上,我确实在我的手机上看到的唯一通知是:

map is %s, undefined

在涟漪模拟器中,每当我加载应用程序时,我都会得到“找到的用户位置”。

请帮忙!

[编辑] 我忘了提到我正在使用 Adob​​e 的 http://build.phonegap.com 来实际构建应用程序。

[编辑2] 我现在尝试像这样使用 Google API 密钥:

<script src="http://maps.google.com/maps/api/js?key=AIzaSyB1uhDdWjtNEl9K35lJtuq5Sw2BjKR8-OM&sensor=false" type="text/javascript"></script>

但是很遗憾,没有变化。还是什么都没有。

[编辑3]

这是我完整的androidManifest.xml

<code>
    <?xml version="1.0" encoding="utf-8"?>
    <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">
            <supports-screens
                    android:largeScreens="true"
                    android:normalScreens="true"
                    android:smallScreens="true"
                    android:xlargeScreens="true"
                    android:resizeable="true"
                    android:anyDensity="true"
                    />

            <uses-permission android:name="android.permission.CAMERA" />
            <uses-permission android:name="android.permission.VIBRATE" />
            <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
            <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
            <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
            <uses-permission android:name="android.permission.INTERNET" />
            <uses-permission android:name="android.permission.RECEIVE_SMS" />
            <uses-permission android:name="android.permission.RECORD_AUDIO" />
            <uses-permission android:name="android.permission.RECORD_VIDEO"/>
            <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
            <uses-permission android:name="android.permission.READ_CONTACTS" />
            <uses-permission android:name="android.permission.WRITE_CONTACTS" />
            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
            <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
            <uses-permission android:name="android.permission.GET_ACCOUNTS" />
            <uses-permission android:name="android.permission.BROADCAST_STICKY" />


            <application android:icon="@drawable/icon" android:label="@string/app_name"
                    android:hardwareAccelerated="true"
                    android:debuggable="true">
                    <activity android:name="DanmarksFlyttemandApp" android:label="@string/app_name"
                                    android:theme="@android:style/Theme.Black.NoTitleBar"
                                    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale">
                            <intent-filter>
                                    <action android:name="android.intent.action.MAIN" />
                                    <category android:name="android.intent.category.LAUNCHER" />
                            </intent-filter>
                    </activity>
            </application>

            <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/>

            <permission android:name="com.alphastagestudios.danmarksflyttemand.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
            <uses-permission android:name="com.alphastagestudios.danmarksflyttemand.permission.MAPS_RECEIVE"/>
    </manifest>

</code>

[编辑4] 我现在尝试使用 PhoneGap 地理位置和基本的谷歌地图构建一个最小的示例。我通过 Eclipse 使用 Cordova v. 2.9.0(最新版本)手动构建了它。 奇怪的是,PhoneGap 地理定位示例本身运行良好,但是当我介绍谷歌地图代码时,它都停止工作了。我尝试了这个使用和不使用谷歌 API 密钥的最小示例。没有区别。

这是我使用的 index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Device Properties Example</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">

    <style>
        body, html, #map-canvas {
            width: 100%;
            height: 400px;
            margin: 0;
            padding: 0;
        }
    </style>

    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
    <script type="text/javascript" charset="utf-8">

    // 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              + '<br />' +
                            'Longitude: '          + position.coords.longitude             + '<br />' +
                            'Altitude: '           + position.coords.altitude              + '<br />' +
                            'Accuracy: '           + position.coords.accuracy              + '<br />' +
                            'Altitude Accuracy: '  + position.coords.altitudeAccuracy      + '<br />' +
                            'Heading: '            + position.coords.heading               + '<br />' +
                            'Speed: '              + position.coords.speed                 + '<br />' +
                            'Timestamp: '          + position.timestamp                    + '<br />';
        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);
    }

    </script>

  </head>
  <body>
    <p id="geolocation">Finding geolocation...</p>

    <div id="map-canvas"></div>
  </body>
</html>

[编辑5] 我现在尝试使用 PhoneGap (Cordova)v 构建应用程序。 2.6.0、2.9.0 和 2.8.1 - 没有工作。手机的地理位置工作正常,但谷歌地图没有显示。我只看到它应该在哪里的默认灰色背景。

【问题讨论】:

    标签: javascript android google-maps cordova


    【解决方案1】:

    我遇到了同样的问题,结果只是我在创建 phonegap 项目后没有更新白名单。 Phonegap 拒绝了 google maps JS URL,因此它从未被下载和执行。

    例如:

     <access origin="*.google.com"/>
        <access origin="*.googleapis.com"/>
    

    【讨论】:

    • 我明白了,很高兴你解决了你的问题,我相信很多人都经历过同样的事情。对我来说不幸的是,我正在使用 进行测试,所以情况并非如此。无论如何感谢您的回答!
    【解决方案2】:

    我从来没有直接解决过这个问题,但我开始使用Intel's App Framework,它有一个用于谷歌地图的示例插件(原始链接已失效,请参阅下面的编辑)。这个插件对我很有用,我可以给它添加方向。

    我最终使用的代码如下。无需权限或任何其他调整。请参阅代码中的 cmets。无论地理定位成功或错误,地图都会显示,但如果它获得当前位置,则会向地图添加方向。否则它显示一个静态点。

    // @author Ian Maffett
    // @copyright App Framework 2012
    // Modified by Rami@alphastagestudios.com - 2013
    // - Added markers & directions
    
    (function () {
        var gmapsLoaded = false; //internal variable to see if the google maps API is available
    
        //We run this on document ready.  It will trigger a gmaps:available event if it's ready
        // or it will include the google maps script for you
        $(document).ready(function () {
            if(window["google"]&&google.maps){
                $(document).trigger("gmaps:available");
                gmapsLoaded = true;
                return true;
            }
            var gmaps = document.createElement("script");
            gmaps.src = "http://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true&callback=gmapsPluginLoaded";
            // Updated API url
            $("head").append(gmaps);
            window["gmapsPluginLoaded"] = function () {
                $(document).trigger("gmaps:available");
                gmapsLoaded = true;
            }
        });
    
        //Local cache of the google maps objects
        var mapsCache = {};
    
        //We can invoke this in two ways
        //If we pass in positions, we create the google maps object
        //If we do not pass in options, it returns the object
        // so we can act upon it.
    
        $.fn.gmaps = function (opts) {
            if (this.length == 0) return;
            if (!opts) return mapsCache[this[0].id];
            //Special resize event
            if(opts=="resize"&&mapsCache[this[0].id])
            {
                var map = mapsCache[this[0].id];
                var center = map.getCenter();
                google.maps.event.trigger(map, "resize");
                map.setCenter(center);
                map.setZoom(13);
                // Extended resize to recenter and reset zoom
    
                return map;
            }
    
            //loop through the items and create the new gmaps object
            for (var i = 0; i < this.length; i++) {
                new gmaps(this[i], opts);
            }
        };
    
    
        //This is a local object that gets created from the above.
        var gmaps = function (elem, opts) {
            var createMap = function () {
                var officePos = new google.maps.LatLng(55.689403, 12.521281);
                if (!opts || Object.keys(opts).length == 0) {
                    opts = {
                        zoom: 13,
                        center: officePos,
                        mapTypeId: google.maps.MapTypeId.ROADMAP
                    }
                }
                mapsCache[elem.id] = new google.maps.Map(elem, opts);
    
                // Added marker for static location 
                var officeMarker = new google.maps.Marker({
                    position: officePos,
                    map: mapsCache[elem.id],
                    title: 'Danmarks Flyttemand ApS'
                });
    
                // Added custom event listener for availability of userPosition
                $(document).one('userPositionAvailable', function(evt, userPos) {
                    if (userPos != null && userPos != '') {
                        addDirections(mapsCache[elem.id], userPos);
                    }
                });
            }
    
            // Adds directions on gmap from userPos to a fixed position
            var addDirections = function(gmap, userPos) {
                var officePos = new google.maps.LatLng(55.689403, 12.521281); // fixed position
                var userMarker = new google.maps.Marker({
                    icon: {
                        path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
                        strokeColor: "green",
                        scale: 5
                    },
                    position: userPos,
                    map: gmap,
                    title: 'Your location'
                });
    
                var directionsService = new google.maps.DirectionsService();
                var directionsDisplay = new google.maps.DirectionsRenderer({suppressMarkers: true});
                directionsDisplay.setMap(gmap);
                directionsDisplay.setPanel(document.getElementById('googledirections')); // add id here
    
                var request = {
                    origin: userPos,
                    destination: officePos,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };
                directionsService.route(request, function(response, status) {
                    if (status == google.maps.DirectionsStatus.OK) {
                        directionsDisplay.setDirections(response);
                    }
                });
            }
    
            //If we try to create a map before it is available
            //listen to the event
            if (!gmapsLoaded) {
                $(document).one("gmaps:available", function () {
                    createMap()
                });
            } else {
                createMap();
            }
        }
    })(af);
    
    
    function onGeoSuccess(position) {
        var userPos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
        $(document).trigger('userPositionAvailable', userPos);
    }
    
    function onGeoError(error) {
        navigator.notification.alert('Geolocation error: ' + error.message);
    }
    
    function initMaps() {
        navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError);
    
        var mapOptions = {
            zoom: 13,
            center: new google.maps.LatLng(55.689403, 12.521281),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        $('#googlemap').gmaps(mapOptions); // update id selector
    
        $('#googlemap-panel').on('loadpanel', function() { // update event for other framework and id selector
            $('#googlemap').gmaps('resize'); // update id selector
        });
    }
    

    [编辑] 示例插件的原始链接似乎已失效,因此这是一个快速找到的新链接(未经测试,仅快速浏览):New Google Maps Plugin Demo for Intel's App-Framework

    【讨论】:

    • 谢谢我也遇到了同样的问题,intels 框架好多了,没有麻烦
    • 示例插件的链接已失效。
    【解决方案3】:

    对我来说,事实证明将地图的 div 宽度和高度指定为百分比是行不通的。将它们指定为 px 或 vw/vh 有效。

    奇怪的是 - 与最初的问题一样 - 百分比大小在浏览器和 iPhone 上确实有效,但在 Android 上无效。所以我确信问题出在其他问题上——可能是权限或网络连接。但只是百分比大小使 div 不可见。

    【讨论】:

    • 但这意味着您将无法让 div 在每台设备上采用精确的高度,您是如何解决该问题的
    • @PirateApp: px 是绝对的,所以在不同的设备上会出现不同的显示 - 但 vw 和 vh 是相对的,所以会显示相同。
    【解决方案4】:

    由于某种原因,assets/www/ 目录中还有另一个 config.xml

    确保在将 url 添加到白名单时修改了正确的文件。 这是正确的: android/res/xml/config.xml

    【讨论】:

    • 其实在使用PhoneGap Build的时候,是没有android/res/xml文件夹的。据称,PhoneGap Build 仅使用了 1 个 config.xml,位于 /www/ 目录中。如果不使用 PhoneGap 构建服务,那么您是绝对正确的。有关 PhoneGap 构建中的 config.xml 的更多信息,请参阅:build.phonegap.com/docs/config-xml
    猜你喜欢
    • 2012-01-29
    • 2012-07-17
    • 2013-06-27
    • 1970-01-01
    • 2012-02-26
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 2012-04-12
    相关资源
    最近更新 更多