There is no Driving Mode for SupportMapFragment
and no possibilities to change default My Location Marker
, but you can:
1) launch Google Maps
application in Driving mode via intent as in this answer of 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);
or
2) change custom current location indicator via custom marker on GoogleMap
object like in that answer of antonio.
Because of unpredictability of LocationListener update I think better use NMEA data (RMC sentence) from GPS via GpsStatus.NmeaListener (OnNmeaMessageListener for API >= 24) for updating current location. In that case source code can be something like that:
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);
}
}
}
and R.drawable.ic_marker_move
& R.drawable.ic_marker_stop
- drawable resources like:
(North orientation is important)
and
respectively.
NB! This is a quick and dirty example without NMEA checksum test, GPS data filtering, saving and restoring marker position on Activity visible/hide, etc.