简体   繁体   中英

Populate Marker with current location in MapsActivity

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM