web-dev-qa-db-ja.com

PhoneGap + Google Maps API v3:Android

状況

現在、Googleマップの統合を希望している顧客向けのアプリを開発しています。ユーザーがどこにいても自分のオフィスまでのルートを地図に表示したいと考えています。

IDE(Sublime Text 2を使用)を使用せずにWindows 8で作業しています。

私はそれを動作させることができましたa)私のChromeブラウザでローカルに、b)PhoneGap/Cordovaのリップルエミュレータ> 2.0.0で。しかし、それが私のAndroid電話(HTCセンセーション)の場合)は機能しません。 (静的マップまたはgeo:urlインターフェースのように)。

実際にマップを実装する前に、PhoneGap Geolocationの完全な例を実行しました here が見つかりました。 Android電話は私の現在の位置(緯度/経度/タイムスタンプなど)を正しく表示しました。したがって、正しい権限(場所->など)がオンに設定されていると思います私の電話。

問題

Googleマップが私のAndroidデバイスに表示されません。赤い背景(デバッグ用)が表示されるので、高さと幅は問題ありません。しかし、何の兆候も見られません。 googleマップ(ボタン、オーバーレイ、グリッドなどはありません)。

コード

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メソッドが呼び出されなかったようですが、ユーザーの位置が無効であることを示すアラートが表示されません。実際、私の電話での唯一の通知はdoです。

map is %s, undefined

リップルエミュレーターでは、アプリを読み込むたびに「ユーザーの位置が見つかりました」が表示されます。

助けてください!

[編集]私はAdobeの 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ジオロケーションと基本的なGoogleマップを使用して最小限の例を作成してみました。 Cordova v。2.9.0(最新)を使用してEclipseから手動でビルドしました。奇妙なことに、PhoneGapジオロケーションの例はそれ自体で問題なく機能しましたが、Googleマップのコードを導入すると、すべて機能しなくなりました。私は、Google 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-どれも機能しませんでした。電話の位置情報は正常に機能しますが、Googleマップは表示されません。デフォルトの灰色の背景のみが表示されます。

15
Rami

私はこれを直接解決したことはありませんが、Googleマップのプラグインの例が含まれている IntelのApp Framework を使い始めました(元のリンクは無効です。以下の編集を参照してください)。このプラグインは私にとってはうまく機能し、方向を追加することができました。

最終的に使用したコードは以下のとおりです。権限やその他の調整は必要ありません。コード内のコメントを参照してください。地図はジオロケーションの成功またはエラーに関係なく表示されますが、現在の位置を取得すると、地図にルートが追加されます。それ以外の場合は、静的なポイントを示します。

// @author Ian Maffett
// @copyright App Framework 2012
// Modified by [email protected] - 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
    });
}

[編集]例のプラグインの元のリンクが無効になっているようです。ここに、すばやく見つかった新しいリンクがあります(テストされておらず、すぐに読み飛ばされただけです): インテルのアプリフレームワーク用の新しいGoogleマッププラグインデモ

5
Rami

同じ問題がありましたが、電話ギャッププロジェクトを作成した後、ホワイトリストを更新しなかっただけでした。 PhonegapはGoogleマップのJS URLを拒否していたため、ダウンロードされて実行されることはありませんでした。

例えば:

 <access Origin="*.google.com"/>
    <access Origin="*.googleapis.com"/>
7
Tim

私にとっては、マップのdivの幅と高さをパーセンテージとして指定しても機能しないことがわかりました。それらをpxまたはvw/vhとして指定すると機能しました。

奇妙なことに-元の質問と同様に-パーセンテージサイズはブラウザーとiPhoneでは機能しましたが、Androidでは機能しませんでした。だから私は問題が別のものであると確信しました-多分許可またはネットワーク接続。ただし、パーセンテージサイズによってdivが非表示になっただけです。

3

何らかの理由で、assets/www /ディレクトリに別のconfig.xmlがあります

ホワイトリストにURLを追加するときは、正しいファイルを変更していることを確認してください。これは正しいものです:Android/res/xml/config.xml

1
julio