I have successfully developed a program to update the marker as the user travels, however the text will only say "Current Location"
I would also like to populate the marker with Address information to the user when clicked. Below are some snippets of code emphasizing my intention, any help will be greatly appreciated! Thank you
Here is my current MapsActivity.java
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Camera;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
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 java.io.IOException;
import java.util.List;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mMap;
private GoogleApiClient client;
private LocationRequest locationRequest;
private Location lastLocation;
private Marker currentLocationMarker;
public static final int REQUEST_LOCATION_CODE = 99;
TextView textView;
Geocoder geocoder;
List<Address> addresses;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
checkLocationPermission();
}
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode)
{
case REQUEST_LOCATION_CODE:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//permission is granted
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if(client == null){
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
}
else {
Toast.makeText(this, "Permission Denied!", Toast.LENGTH_LONG).show();
//Permission is denied
}
return;
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
Toast.makeText(this, "Click Icon in Top right for Current Location", Toast.LENGTH_LONG).show();
mMap = googleMap;
LatLng Phoenix = new LatLng(33.6056711, -112.4052378);
mMap.addMarker(new MarkerOptions().position(Phoenix).title("Default Location: Phoenix, AZ"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(Phoenix));
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient(){
client = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
client.connect();
}
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
if(currentLocationMarker != null){
currentLocationMarker.remove();
}
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
textView = (TextView) findViewById(R.id.textView);
geocoder = new Geocoder(this, Locale.getDefault());
try {
addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
String address = addresses.get(0).getAddressLine(0);
String area = addresses.get(0).getLocality();
String city = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalcode = addresses.get(0).getPostalCode();
String fullAddress = address+", "+area+", " +city+", " + country+ "," + postalcode;
textView.setText(fullAddress);
} catch (IOException e) {
e.printStackTrace();
}
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomBy(10));
if(client != null){
LocationServices.FusedLocationApi.removeLocationUpdates(client, this);
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
locationRequest = new LocationRequest();
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(1000);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this);
}
}
public boolean checkLocationPermission(){
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION))
{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE);
}
else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_CODE);
}
return false;
}
else
return true;
}
public void onZoom(View view) {
if (view.getId() == R.id.zoomIn) {
mMap.animateCamera(CameraUpdateFactory.zoomIn());
}
if (view.getId() == R.id.zoomOut) {
mMap.animateCamera(CameraUpdateFactory.zoomOut());
}
}
public void ChangeType(View view) {
if (mMap.getMapType() == GoogleMap.MAP_TYPE_NORMAL) {
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
Toast.makeText(this, "Satellite Map Style", Toast.LENGTH_LONG).show();
}
else if (mMap.getMapType() == GoogleMap.MAP_TYPE_SATELLITE) {
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
Toast.makeText(this, "Hybrid Map Style", Toast.LENGTH_LONG).show();
}
else if (mMap.getMapType() == GoogleMap.MAP_TYPE_HYBRID) {
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
Toast.makeText(this, "Terrain Map Style", Toast.LENGTH_LONG).show();
}
else if (mMap.getMapType() == GoogleMap.MAP_TYPE_TERRAIN) {
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
Toast.makeText(this, "Normal Map Style", Toast.LENGTH_LONG).show();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}
Here is the corresponding xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/img_header" >
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="Test"
android:layout_centerHorizontal="true"
android:textSize="22sp"/>
</RelativeLayout>
StackTrace
05-17 09:15:49.411 15842-15842/edu.phoenix.mbl402.week3apptt2163 E/AndroidRuntime: FATAL EXCEPTION: main
Process: edu.phoenix.mbl402.week3apptt2163, PID: 15842
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at edu.phoenix.mbl402.week3apptt2163.MapsActivity.onLocationChanged(MapsActivity.java:139)
at com.google.android.gms.internal.location.zzay.notifyListener(Unknown Source:4)
at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(Unknown Source:8)
at com.google.android.gms.common.api.internal.ListenerHolder$zza.handleMessage(Unknown Source:16)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
FINAL EDIT:
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
if(currentLocationMarker != null){
currentLocationMarker.remove();
}
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(getAddressForLatLng());
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
currentLocationMarker = mMap.addMarker((markerOptions));
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
public static Address getAddressForLatLng(Context context, LatLng location) {
final int MAX_RESULTS = 1;
final Geocoder geocoder = new Geocoder(context, Locale.getDefault());
Address address = new Address(Locale.getDefault());
try {
final List<Address> addresses = geocoder.getFromLocation(location.latitude, location.longitude, MAX_RESULTS);
if (addresses != null && addresses.size() != 0) {
address = addresses.get(0);
}
return address;
} catch (IOException e) {
Log.e("Geocoding", "Geocoding was not possible");
}
return address;
}
You don't have to remove marker from map on each location update. reuse existing marker store reference to it.
Marker mMarker = mMap.addMarker(new MarkerOptions()......)
After creating mMarkerObject refresh its location in OnLocationChanged
mMarker.setTitle() mMarker.setPosition(latLng);
If for some reason You still want to implement on click action add interface to Your main activity OnMarkerClickListener and override OnMarkerClick and use showInfoWindow or something :)
EDIT: for geocrush try following ->
public static Address getAddressForLatLng(final Context context, final LatLng location) {
final int MAX_RESULTS = 1;
final Geocoder geocoder = new Geocoder(context, Locale.getDefault());
Address address = new Address(Locale.getDefault());
try {
final List<Address> addresses = geocoder.getFromLocation(location.latitude, location.longitude, MAX_RESULTS);
if (addresses != null && addresses.size() != 0) {
address = addresses.get(0);
}
return address;
} catch (IOException e) {
Log.e("Geocoding", "Geocoding was not possible");
}
return address;
}
Simplified more efficient version of onLocationChanged()
@Override
public void onLocationChanged(Location location) {
lastLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
currentLocationMarker.setPosition(latLng);
// make sure following setTitle gets String from getAddressForLatLng
currentLocationMarker.setTitle(getAddressForLatLng(latLng));
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
You can use reverse geocoding to get a human-readable address string from your latitude and longitude. Then use that address as the marker title, instead of "Current Location"
.
Specifically:
addresses = geocoder.getFromLocation(
location.getLatitude(),
location.getLongitude(),
// In this sample, get just a single address.
1);
address = adresses[0];
markerOptions.title(address);
(Error handling etc. left out, see link).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.