java - 谷歌地图设置为免费驾驶模式

标签 java android google-maps location

<分区>

我有一个在 xml 文件中添加了 SupportMapFragment 的 Android 应用程序。 在 fragment 中,我按如下方式设置我的位置:mMap.setMyLocationEnabled(true); 以显示我的当前位置

主要问题是默认启用步行模式[蓝点],我希望启用自由驾驶模式[蓝色箭头]

如何实现自由驾驶模式?将蓝色箭头作为我的位置而不是蓝点

enter image description here

最佳答案

SupportMapFragment 没有驾驶模式,也无法更改默认的 My Location Marker,但您可以:

1) 通过 intent 在驾驶模式下启动 Google Maps 应用程序,如 this Jason Maderski的答案:

Intent intent = getPackageManager().getLaunchIntentForPackage("com.google.android.apps.maps");
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("google.navigation:/?free=1&mode=d&entry=fnls"));
startActivity(intent);

2) 通过 GoogleMap 对象上的自定义标记更改自定义当前位置指示符,如 that antonio的答案.

因为unpredictability of LocationListener update我认为最好使用 NMEA数据(RMC 句子)来自 GPS 通过 GpsStatus.NmeaListener (OnNmeaMessageListener 对于 API >= 24)用于更新当前位置。在那种情况下,源代码可以是这样的:

CustomNmeaListener.java:

public class CustomNmeaListener implements GpsStatus.NmeaListener{

    private GoogleMap mGoogleMap;
    private Marker mMarkerPosition = null;
    private BitmapDescriptor mMarkerMoveDescriptor;
    private BitmapDescriptor mMarkerStopDescriptor;

    public CustomNmeaListener(GoogleMap googleMap, int markerMoveResource, int markerStopResource){
        this.mGoogleMap = googleMap;

        mMarkerMoveDescriptor = BitmapDescriptorFactory.fromResource(markerMoveResource);
        mMarkerStopDescriptor = BitmapDescriptorFactory.fromResource(markerStopResource);
    }

    @Override
    public void onNmeaReceived(long timestamp, String nmea) {
        double latitude;
        double longitude;
        float speed;
        float angle;

        // parse NMEA RMC sentence
        // Example $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
        //   nmea    [0]   [1]  [2]  [3]   [4]   [5]   [6] [7]   [8]   [9]   [10]  [11]
        if (nmea.startsWith("$GPRMC")) {

            String[] nmeaParts = nmea.split(",");

            // if RMC data valid ("active")
            if (nmeaParts[2].equals("A")) {
                latitude = parseLatitude(nmeaParts[3], nmeaParts[4]);
                longitude = parseLongitude(nmeaParts[5], nmeaParts[6]);
                speed = parseSpeed(nmeaParts[7]);
                angle = parseAngle(nmeaParts[8]);

                // remove marker on "old" position
                if (mMarkerPosition != null) {
                    mMarkerPosition.remove();
                }

                MarkerOptions positionMarkerOptions;

                if (speed > 0) {
                    positionMarkerOptions = new MarkerOptions()
                            .position(new LatLng(latitude, longitude))
                            .icon(mMarkerMoveDescriptor)
                            .anchor(0.5f, 0.5f)
                            .rotation(angle);
                } else {
                    positionMarkerOptions = new MarkerOptions()
                            .position(new LatLng(latitude, longitude))
                            .icon(mMarkerStopDescriptor)
                            .anchor(0.5f, 0.5f)
                            .rotation(0);
                }
                mMarkerPosition = mGoogleMap.addMarker(positionMarkerOptions);
            }
        }

    }

    static float parseLatitude(String lat, String sign) {
        float latitude = Float.parseFloat(lat.substring(2)) / 60.0f;
        latitude +=  Float.parseFloat(lat.substring(0, 2));
        if(sign.startsWith("S")) {
            latitude = -latitude;
        }
        return latitude;
    }

    static float parseLongitude(String lon, String sign) {
        float longitude = Float.parseFloat(lon.substring(3)) / 60.0f;
        longitude +=  Float.parseFloat(lon.substring(0, 3));
        if(sign.startsWith("W")) {
            longitude = -longitude;
        }
        return longitude;
    }

    static float parseSpeed(String knots) {
        float speed;
        try {
            speed = Float.parseFloat(knots);
        } catch (Exception e) {
            speed = 0;
        }
        return speed;
    }

    static float parseAngle(String ang) {
        float angle;
        try {
            angle = Float.parseFloat(ang);
        } catch (Exception e) {
            angle = 0;
        }
        return angle;
    }
}

MainActivity.java:

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, LocationListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 101;

    private static final int LOCATION_INTERVAL = 1000;
    private static final float LOCATION_DISTANCE = 10f;

    private GoogleMap mGoogleMap;
    private MapFragment mMapFragment;

    private LocationManager mLocationManager = null;
    private CustomNmeaListener mNmeaListener = null;


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

        mMapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mMapFragment.getMapAsync(this);

    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (locationPermission != PackageManager.PERMISSION_GRANTED) {
                makeLocationPermissionRequest();
            } else {
                setCustomLocationListener();
            }
        } else {
            setCustomLocationListener();
        }
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

    @Override
    public void onProviderDisabled(String s) {

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case LOCATION_PERMISSION_REQUEST_CODE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    setCustomLocationListener();
                } else {
                }
                return;
            }
        }
    }

    private void makeLocationPermissionRequest() {
        ActivityCompat.requestPermissions(this,
                new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
    }

    private void setCustomLocationListener() {
        // disable "standard" location marker
        mGoogleMap.setMyLocationEnabled(false);

        initializeLocationManager();
        mNmeaListener = new CustomNmeaListener(mGoogleMap, R.drawable.ic_marker_move, R.drawable.ic_marker_stop);
        mLocationManager.addNmeaListener(mNmeaListener);

        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    this
            );
        } catch (java.lang.SecurityException ex) {
            Log.d(TAG, "fail to request location update, ignore", ex);
        }
    }

    private void initializeLocationManager() {
        Log.d(TAG, "initializeLocationManager - LOCATION_INTERVAL: "+ LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }

}

R.drawable.ic_marker_move & R.drawable.ic_marker_stop - 可绘制资源如:

Marker for movement (speed > 0)

(北向很重要)

Marker for movement (speed = 0)

分别。

注意!这是一个没有 NMEA 校验和测试的快速而肮脏的例子,GPS data filtering , 保存和恢复 Activity 上的标记位置可见/隐藏等。

关于java - 谷歌地图设置为免费驾驶模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46995113/

相关文章:

java - 我的@component 有什么问题吗?

java - 为什么列表列表 <? super E> 是列表 <?扩展列表 <? super E>> 但不是 List<List<? super E>>

android - 从 ORDERBY 和 GROUPBY 函数无法正常工作的表中选择前 5 个值

jquery - 根据其背后的颜色动态更改文本颜色(谷歌地图)

javascript - 谷歌地图距离矩阵和融合表

java - Hashmap结果只显示一行

java - 如何使用 Gradle 从项目文件(*.java、*.js、*、xml 等)创建源 JAR?

java - Android NDK : JNI GetMethodID called with pending exception java. lang.ClassNotFoundException:未找到类

android - 是否可以通过编程方式从 Firebase Analytics 控制台收集数据?

api - 应用程序运行时 Flutter Google Map API 问题