Google Maps Android api v2 和当前位置

Posted

技术标签:

【中文标题】Google Maps Android api v2 和当前位置【英文标题】:Google Maps Android api v2 and current location 【发布时间】:2012-11-30 10:04:34 【问题描述】:

我正在尝试使用新的 google maps android api v2,并且我正在开发适用于 android 2.3.3 或更高版本的应用程序。 这是一个非常简单的应用程序: 它需要用户当前位置(使用 gps 或网络信号) 它从 db 获取 POI 使用direction api,将用户带到POI。

我的问题是获取用户当前位置。感谢这篇文章How to get the current location in Google Maps Android API v2? 我了解到我无法使用新的 google api 更新当前位置。 另一个问题是我可以使用GoogleMap setMyLocationEnabled(boolean enabled) 设置我的位置,但我不能使用getMyLocation() 知道用户在哪里。

我使用此指南http://www.vogella.com/articles/AndroidLocationAPI/article.html#maps_mylocation 获取我的位置,并尝试集成到我的 Activity 中以绘制用户位置。

这是我的代码:

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="it.mappe"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="it.mappe.permission.MAPS_RECEIVE" />

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

         <meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="MYGMAPSKEY" />
        <activity
            android:name="it.mappe.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

主要活动

package it.mappe;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;

import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.FragmentActivity;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements LocationListener 
    private GoogleMap map;
    private static final LatLng ROMA = new LatLng(42.093230818037,11.7971813678741);
    private LocationManager locationManager;
    private String provider;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

        LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
        boolean enabledGPS = service
                .isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean enabledWiFi = service
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        // Check if enabled and if not send user to the GSP settings
        // Better solution would be to display a dialog and suggesting to 
        // go to the settings
        if (!enabledGPS) 
            Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG).show();
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);
        

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        // Define the criteria how to select the locatioin provider -> use
        // default
        Criteria criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria, false);
        Location location = locationManager.getLastKnownLocation(provider);

        // Initialize the location fields
        if (location != null) 
            Toast.makeText(this, "Selected Provider " + provider,
                    Toast.LENGTH_SHORT).show();
            onLocationChanged(location);
         else 

            //do something
        

    

    /* Request updates at startup */
    @Override
    protected void onResume() 
        super.onResume();
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    

    /* Remove the locationlistener updates when Activity is paused */
    @Override
    protected void onPause() 
        super.onPause();
        locationManager.removeUpdates(this);
    

    @Override
    public void onLocationChanged(Location location) 
        double lat =  location.getLatitude();
        double lng = location.getLongitude();
        Toast.makeText(this, "Location " + lat+","+lng,
                Toast.LENGTH_LONG).show();
        LatLng coordinate = new LatLng(lat, lng);
        Toast.makeText(this, "Location " + coordinate.latitude+","+coordinate.longitude,
                Toast.LENGTH_LONG).show();
        Marker startPerc = map.addMarker(new MarkerOptions()
        .position(coordinate)
        .title("Start")
        .snippet("Inizio del percorso")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
    


    @Override
    public void onProviderDisabled(String provider) 
        Toast.makeText(this, "Enabled new provider " + provider,
                Toast.LENGTH_SHORT).show();

    


    @Override
    public void onProviderEnabled(String provider) 
        Toast.makeText(this, "Disabled provider " + provider,
                Toast.LENGTH_SHORT).show();

    


    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) 
        // TODO Auto-generated method stub

    


主布局

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:layout_
    android:layout_
    class="com.google.android.gms.maps.SupportMapFragment" />

它可以工作,但不是那么好,正如您在图片中看到的那样,每一次都有一个新位置,它添加了一个新标记(我认为前叠加层......我从不使用旧的谷歌地图 api)。

如何只显示一个标记?

此外,在我的地图上,我还需要显示 POI 的标记,所以我认为这不是一个好的解决方案,将所有标记删除并在地图上重新绘制。 还有另一种获取用户当前位置的最佳方法,每时每刻都更新它,只显示一个自定义标记?!

【问题讨论】:

【参考方案1】:

您可以调用startPerc.remove(); 仅删除此标记。

来自here

【讨论】:

我正在尝试,我想我可以添加一个私有标记 currentLocation 并将其设置为当前用户位置,这样我可以在我有新位置并添加新标记时将其删除。 它有效。谢谢。只是一个快速的问题:你能解释一下为什么 locationMenager 决定总是获得网络私有者而不是 gps 提供吗? 你试过这个标准吗? Criteria criteria = Criteria() Accuracy = Accuracy.Fine ; 不,现在我试试...但我认为另一个问题是我在 onCreate(..) 方法中决定提供程序。现在我也在阅读这个developer.android.com/training/basics/location/…,它解释了如何处理多个位置更新来源【参考方案2】:

为什么不直接使用startPerc.setPosition 来移动标记而不是继续添加和删除...

【讨论】:

【参考方案3】:

通过此方法获取另一个位置时设置标记的位置

marker. set position (location)

【讨论】:

【参考方案4】:

您应该在添加标记之前使用 googlemap.clear(),因为每次更改位置时,它都会在地图上添加最旧标记的新标记。所以在更改位置添加标记之前使用 googlemap.clear() 。它将删除最旧的标记并添加新标记。 googlemap 是 GoogleMap 类的实例。

【讨论】:

【参考方案5】:

您可以用新的标记替换标记:

if(userMarker!=null) userMarker.remove();
    userMarker = theMap.addMarker(new MarkerOptions()
    .position(lastLatLng)
    .title("You are here")
    .icon(BitmapDescriptorFactory.fromResource(R.drawable.your_loc_icon))
    .snippet("Your current location"));

【讨论】:

【参考方案6】:

在android中定义谷歌地图android v2的完整快捷方式......

XML 文件:

<fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_
        android:layout_ />

菜单文件:

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

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<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_NETWORK_STATE" />

<!-- Map permission Starts -->
<permission
    android:name="com.example.mapdemoapiv2.permission.MAPS_RECEIVE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.example.mapdemoapiv2.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />

<!-- Map permission Starts -->

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.mapdemoapiv2.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".MapDetail" >
    </activity>

    <meta-data
        android:name="com.google.android.maps.v2.API_KEY"
        android:value="Your Key" />

    <uses-library android:name="com.google.android.maps" />
</application>

活动类:

public class MainActivity extends android.support.v4.app.FragmentActivity

   GoogleMap googleMap;
    MarkerOptions markerOptions;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    setUpMapIfNeeded();

    GetCurrentLocation();

    

private void setUpMapIfNeeded() 
    if (googleMap == null) 

        Log.e("", "Into null map");
        googleMap = ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map)).getMap();

        googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(
                MainActivity.this));

        if (googleMap != null) 
            Log.e("", "Into full map");
            googleMap.setMapType(googleMap.MAP_TYPE_NORMAL);
            googleMap.getUiSettings().setZoomControlsEnabled(false);
        
    


private void GetCurrentLocation() 

    double[] d = getlocation();
    Share.lat = d[0];
    Share.lng = d[1];

     googleMap
            .addMarker(new MarkerOptions()
                    .position(new LatLng(Share.lat, Share.lng))
                    .title("Current Location")
                    .icon(BitmapDescriptorFactory
                            .fromResource(R.drawable.dot_blue)));

             googleMap
                .animateCamera(CameraUpdateFactory.newLatLngZoom(
                        new LatLng(Share.lat, Share.lng), 5));


public double[] getlocation() 
    LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    List<String> providers = lm.getProviders(true);

    Location l = null;
    for (int i = 0; i < providers.size(); i++) 
        l = lm.getLastKnownLocation(providers.get(i));
        if (l != null)
            break;
    
    double[] gps = new double[2];

    if (l != null) 
        gps[0] = l.getLatitude();
        gps[1] = l.getLongitude();
    
    return gps;

【讨论】:

【参考方案7】:

首先在 map api v2 中使用 LocationClient 来检索您的位置,请参阅:http://developer.android.com/training/location/retrieve-current.html

重要提示:要启动 API,请在主 Activity 的 onStart 中调用它:

private void kickStardedLocationManager()

 // Acquire a reference to the system Location Manager
    LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

 // Define a listener that responds to location updates
    android.location.LocationListener locationListener = new android.location.LocationListener() 
        public void onLocationChanged(Location location) 
          // Called when a new location is found by the network location provider.
            //MainActivity.this.makeUseOfNewLocation(location);
        

        public void onStatusChanged(String provider, int status, Bundle extras) 

        public void onProviderEnabled(String provider) 

        public void onProviderDisabled(String provider) 
      ;

      long l = 10;
      float f = 100;
   // Register the listener with the Location Manager to receive location updates
      locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); //LocationManager.GPS_PROVIDER

【讨论】:

以上是关于Google Maps Android api v2 和当前位置的主要内容,如果未能解决你的问题,请参考以下文章

Maps SDK for Android v.3.0.0 BETA "是否可以在没有Google Play服务的设备上运行?

Google Maps API v.3.31更新会破坏StageWebView和StageWebViewBridge

Google Maps Android API V2 检查 Google Maps 应用程序是不是被禁用

无法运行 Google Maps Android API Utility Demo

Google Geolocation API 和 Google Maps Android SDK

Android:使用 Google API 获取实时方向,还是与 Google Maps 通信?