How to implement draggable map like uber? I am using Google maps v2. Actually i got the solution referring this post and sharing my complete solution here
You can try out this example done by me....
Example done by me
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/map"
android:name="com.rajeshvijayakumar.map.demo.ui.CustomMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/marker_view_incl"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="@layout/marker_view" />
<include
android:id="@+id/location_display_incl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_margin="7dp"
layout="@layout/location_display_view" />
</RelativeLayout>
marker_view.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/marker_icon_view"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:layout_marginTop="162dp"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
location_display_view.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@android:color/white" >
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center"
android:text="Set Location"
android:textColor="@android:color/holo_green_dark"
android:textSize="12sp" />
<TextView
android:id="@+id/location_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text_view"
android:layout_centerHorizontal="true"
android:gravity="center"
android:text="Set Location"
android:textColor="@android:color/black"
android:textSize="14sp" />
MapWrapperLayout.java
package com.rajeshvijayakumar.map.demo.wrapper;
public class MapWrapperLayout extends FrameLayout {
public interface OnDragListener {
public void onDrag(MotionEvent motionEvent);
}
private OnDragListener mOnDragListener;
public MapWrapperLayout(Context context) {
super(context);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mOnDragListener != null) {
mOnDragListener.onDrag(ev);
}
return super.dispatchTouchEvent(ev);
}
public void setOnDragListener(OnDragListener mOnDragListener) {
this.mOnDragListener = mOnDragListener;
}
}
CustomMapFragment.java
package com.rajeshvijayakumar.map.demo.ui;
public class CustomMapFragment extends MapFragment {
private View mOriginalView;
private MapWrapperLayout mMapWrapperLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mOriginalView = super.onCreateView(inflater, container, savedInstanceState);
mMapWrapperLayout = new MapWrapperLayout(getActivity());
mMapWrapperLayout.addView(mOriginalView);
return mMapWrapperLayout;
}
@Override
public View getView() {
return mOriginalView;
}
public void setOnDragListener(MapWrapperLayout.OnDragListener onDragListener) {
mMapWrapperLayout.setOnDragListener(onDragListener);
}
}
MainActivity.java
public class MainActivity extends Activity implements OnDragListener {
// Google Map
private GoogleMap googleMap;
private CustomMapFragment mCustomMapFragment;
private View mMarkerParentView;
private ImageView mMarkerImageView;
private int imageParentWidth = -1;
private int imageParentHeight = -1;
private int imageHeight = -1;
private int centerX = -1;
private int centerY = -1;
private TextView mLocationTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// InitializeUI
initializeUI();
}
private void initializeUI() {
try {
// Loading map
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
mLocationTextView = (TextView) findViewById(R.id.location_text_view);
mMarkerParentView = findViewById(R.id.marker_view_incl);
mMarkerImageView = (ImageView) findViewById(R.id.marker_icon_view);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
imageParentWidth = mMarkerParentView.getWidth();
imageParentHeight = mMarkerParentView.getHeight();
imageHeight = mMarkerImageView.getHeight();
centerX = imageParentWidth / 2;
centerY = (imageParentHeight / 2) + (imageHeight / 2);
}
private void initilizeMap() {
if (googleMap == null) {
mCustomMapFragment = ((CustomMapFragment) getFragmentManager()
.findFragmentById(R.id.map));
mCustomMapFragment.setOnDragListener(MainActivity.this);
googleMap = mCustomMapFragment.getMap();
// check if map is created successfully or not
if (googleMap == null) {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
// CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng,
// 10);
// googleMap.animateCamera(cameraUpdate);
// locationManager.removeUpdates(this);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public void onDrag(MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
Projection projection = (googleMap != null && googleMap
.getProjection() != null) ? googleMap.getProjection()
: null;
//
if (projection != null) {
LatLng centerLatLng = projection.fromScreenLocation(new Point(
centerX, centerY));
updateLocation(centerLatLng);
}
}
}
private void updateLocation(LatLng centerLatLng) {
if (centerLatLng != null) {
Geocoder geocoder = new Geocoder(MainActivity.this,
Locale.getDefault());
List<Address> addresses = new ArrayList<Address>();
try {
addresses = geocoder.getFromLocation(centerLatLng.latitude,
centerLatLng.longitude, 1);
} catch (IOException e) {
e.printStackTrace();
}
if (addresses != null && addresses.size() > 0) {
String addressIndex0 = (addresses.get(0).getAddressLine(0) != null) ? addresses
.get(0).getAddressLine(0) : null;
String addressIndex1 = (addresses.get(0).getAddressLine(1) != null) ? addresses
.get(0).getAddressLine(1) : null;
String addressIndex2 = (addresses.get(0).getAddressLine(2) != null) ? addresses
.get(0).getAddressLine(2) : null;
String addressIndex3 = (addresses.get(0).getAddressLine(3) != null) ? addresses
.get(0).getAddressLine(3) : null;
String completeAddress = addressIndex0 + "," + addressIndex1;
if (addressIndex2 != null) {
completeAddress += "," + addressIndex2;
}
if (addressIndex3 != null) {
completeAddress += "," + addressIndex3;
}
if (completeAddress != null) {
mLocationTextView.setText(completeAddress);
}
}
}
}
}
GPSClass From #Shvet ans.
public class CarSelectActivity extends BaseActivity implements GoogleApiClient.OnConnectionFailedListener, LocationListener, OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks {
private GoogleApiClient mGoogleApiClient;
private static final LatLngBounds BOUNDS_GREATER_SYDNEY = new LatLngBounds(
new LatLng(-34.041458, 150.790100), new LatLng(-33.682247, 151.383362));
private GoogleMap mGoogleMap;
private ImageView mMarkerImageView;
private GPSTracker gps;
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
setContentView(R.layout.activit_carselect);
final SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
inilizviews();
}
private void inilizviews() {
gps = new GPSTracker(this);
mMarkerImageView = (ImageView) findViewById(R.id.im_marker);
}
@Override
public void onConnectionFailed(@NonNull final ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(final Location location) {
}
@Override
public void onMapReady(final GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mGoogleMap.getUiSettings().isMyLocationButtonEnabled();
mGoogleMap.getUiSettings().isZoomControlsEnabled();
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
}
@Override
public void onConnected(@Nullable final Bundle bundle) {
mGoogleApiClient.connect();
setUpDragListners();
}
@Override
public void onConnectionSuspended(int i) {
}
private void setUpDragListners() {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
gps.canGetLocation();
LatLng curentpoint = new LatLng(gps.getLatitude(), gps.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(curentpoint).zoom(15f).tilt(30).build();
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
mGoogleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition arg0) {
// TODO Auto-generated method stub
LatLng center = mGoogleMap.getCameraPosition().target;
try {
getLocation(center.latitude, center.longitude);
} catch (final Exception e) {
e.printStackTrace();
}
}
});
private void getLocation(double latitude, double longitude) {
Geocoder geocoder = new Geocoder(CarSelectActivity.this, Locale.ENGLISH);
addresses = geocoder.getFromLocation(latitude, longitude, 1);
textView_places.setText(addresses.get(0).getAddressLine(0)
+ addresses.get(0).getAddressLine(1) + " ");
}
}
Shorter Kotlin way: wrap xml with Relative layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:mapType="normal"
tools:context=".MapStartedActivity"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:id="@+id/imgLocationPinUp"
android:src="@drawable/location_pin_up"
/>
</RelativeLayout>
fun mapInit(googleMap: GoogleMap){
googleMap.apply {
// just a random location our map will point to when its launched
val klcc = LatLng(3.1579513, 101.7116233)
addMarker(MarkerOptions().apply {
position(klcc)
title("Marker pointed at klcc")
draggable(false)
})
// setup zoom level
animateCamera(CameraUpdateFactory.newLatLngZoom(klcc,18f))
// maps events we need to respond to
setOnCameraMoveListener(this@MapStartedActivity)
setOnCameraIdleListener(this@MapStartedActivity)
}
}
override fun onCameraMove() {
mMap.clear()
// display imageView
imgPinUp?.visibility = View.VISIBLE
}
override fun onCameraIdle() {
// hiding imageView
imgPinUp?.visibility = View.GONE
// customizing map marker with a custom icon
// and place it on the current map camera position
val markerOptions = MarkerOptions().position(mMap.cameraPosition.target)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.location_pin))
mMap.addMarker(markerOptions)
}
As LocationClient
is deprected, I have used GoogleApiClient
, Here is code for anyone who want to implement it.
Just Replacing LocationClient
with GoogleApiClient
else is same as @Sishin's code.
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.app.Dialog;
import android.content.IntentSender.SendIntentException;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.app.anycabs.R;
import com.app.common.GPSTracker;
import com.app.modle.GData;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
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.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends AppCompatActivity implements
LocationListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
// A request to connect to Location Services
private LocationRequest mLocationRequest;
GoogleMap mGoogleMap;
public static String ShopLat;
public static String ShopPlaceId;
public static String ShopLong;
// Stores the current instantiation of the location client in this object
private GoogleApiClient mGoogleApiClient;
boolean mUpdatesRequested = false;
private TextView markerText;
private LatLng center;
private LinearLayout markerLayout;
private Geocoder geocoder;
private List<Address> addresses;
private TextView Address;
double latitude;
double longitude;
private GPSTracker gps;
private LatLng curentpoint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_curent_locations);
markerText = (TextView) findViewById(R.id.locationMarkertext);
Address = (TextView) findViewById(R.id.adressText);
markerLayout = (LinearLayout) findViewById(R.id.locationMarker);
// Getting Google Play availability status
int status = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getBaseContext());
if (status != ConnectionResult.SUCCESS) { // Google Play Services are
// not available
int requestCode = 10;
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this,
requestCode);
dialog.show();
} else { // Google Play Services are available
// Getting reference to the SupportMapFragment
// Create a new global location parameters object
mLocationRequest = LocationRequest.create();
/*
* Set the update interval
*/
mLocationRequest.setInterval(GData.UPDATE_INTERVAL_IN_MILLISECONDS);
// Use high accuracy
mLocationRequest
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest
.setFastestInterval(GData.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
// Note that location updates are off until the user turns them on
mUpdatesRequested = false;
/*
* Create a new location client, using the enclosing class to handle
* callbacks.
*/
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
}
}
private void stupMap() {
try {
mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.curentlocationmapfragment)).getMap();
// Enabling MyLocation in Google Map
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setZoomControlsEnabled(false);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
mGoogleMap.getUiSettings().setCompassEnabled(true);
mGoogleMap.getUiSettings().setRotateGesturesEnabled(true);
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
PendingResult<Status> result = LocationServices.FusedLocationApi
.requestLocationUpdates(mGoogleApiClient, mLocationRequest,
new LocationListener() {
@Override
public void onLocationChanged(Location location) {
markerText.setText("Location received: "
+ location.toString());
}
});
Log.e("Reached", "here");
result.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e("Result", "success");
} else if (status.hasResolution()) {
// Google provides a way to fix the issue
try {
status.startResolutionForResult(MainActivity.this,
100);
} catch (SendIntentException e) {
e.printStackTrace();
}
}
}
});
gps = new GPSTracker(this);
gps.canGetLocation();
latitude = gps.getLatitude();
longitude = gps.getLongitude();
curentpoint = new LatLng(latitude, longitude);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(curentpoint).zoom(19f).tilt(70).build();
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
// Clears all the existing markers
mGoogleMap.clear();
mGoogleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition arg0) {
// TODO Auto-generated method stub
center = mGoogleMap.getCameraPosition().target;
markerText.setText(" Set your Location ");
mGoogleMap.clear();
markerLayout.setVisibility(View.VISIBLE);
try {
new GetLocationAsync(center.latitude, center.longitude)
.execute();
} catch (Exception e) {
}
}
});
markerLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
LatLng latLng1 = new LatLng(center.latitude,
center.longitude);
Marker m = mGoogleMap.addMarker(new MarkerOptions()
.position(latLng1)
.title(" Set your Location ")
.snippet("")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.pin_last)));
m.setDraggable(true);
markerLayout.setVisibility(View.GONE);
} catch (Exception e) {
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
@Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
stupMap();
}
private class GetLocationAsync extends AsyncTask<String, Void, String> {
// boolean duplicateResponse;
double x, y;
StringBuilder str;
public GetLocationAsync(double latitude, double longitude) {
// TODO Auto-generated constructor stub
x = latitude;
y = longitude;
}
@Override
protected void onPreExecute() {
Address.setText(" Getting location ");
}
@Override
protected String doInBackground(String... params) {
try {
geocoder = new Geocoder(MainActivity.this, Locale.ENGLISH);
addresses = geocoder.getFromLocation(x, y, 1);
str = new StringBuilder();
if (Geocoder.isPresent()) {
Address returnAddress = addresses.get(0);
String localityString = returnAddress.getLocality();
String city = returnAddress.getCountryName();
String region_code = returnAddress.getCountryCode();
String zipcode = returnAddress.getPostalCode();
str.append(localityString + "");
str.append(city + "" + region_code + "");
str.append(zipcode + "");
} else {
}
} catch (IOException e) {
Log.e("tag", e.getMessage());
}
return null;
}
@Override
protected void onPostExecute(String result) {
try {
Address.setText(addresses.get(0).getAddressLine(0)
+ addresses.get(0).getAddressLine(1) + " ");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
@Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
}
Where GPSTracker
is as below:
public class GPSTracker extends Service implements LocationListener {
private final FragmentActivity mActivity;
// flag for GPS Status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude;
double longitude;
// The minimum distance to change updates in metters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10
// metters
// The minimum time beetwen updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public GPSTracker(FragmentActivity activity) {
this.mActivity = activity;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) mActivity
.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateGPSCoordinates();
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateGPSCoordinates();
}
}
}
}
} catch (Exception e) {
// e.printStackTrace();
Log.e("Error : Location",
"Impossible to connect to LocationManager", e);
}
return location;
}
public void updateGPSCoordinates() {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
/**
* Stop using GPS listener Calling this function will stop using GPS in your
* app
*/
public void stopUsingGPS() {
if (locationManager != null) {
locationManager.removeUpdates(GPSTracker.this);
locationManager = null;
}
}
/**
* Function to get latitude
*/
public double getLatitude() {
if (location != null) {
latitude = location.getLatitude();
}
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (location != null) {
longitude = location.getLongitude();
}
return longitude;
}
/**
* Function to check GPS/wifi enabled
*/
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
*/
public void showSettingsAlert() {
if (mActivity == null || mActivity.isFinishing()) {
return;
}
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(
mActivity);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog
.setMessage("Your GPS is disabled, Enable GPS in settings or continue with approximate location");
// On pressing Settings button
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mActivity.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog,
int which) {
// UserSerch doSerch = new UserSerch();
// doSerch.doserchOn();
// dialog.cancel();
}
});
// Showing Alert Message
alertDialog.create().show();
}
});
}
/**
* Get list of address by latitude and longitude
*
* @return null or List<Address>
*/
public List<Address> getGeocoderAddress(Context context) {
if (location != null) {
Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
try {
List<Address> addresses = geocoder.getFromLocation(latitude,
longitude, 1);
return addresses;
} catch (IOException e) {
// e.printStackTrace();
Log.e("Error : Geocoder", "Impossible to connect to Geocoder",
e);
}
}
return null;
}
/**
* Try to get AddressLine
*
* @return null or addressLine
*/
public String getAddressLine(Context context) {
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
String addressLine = address.getAddressLine(0);
return addressLine;
} else {
return null;
}
}
/**
* Try to get Locality
*
* @return null or locality
*/
public String getLocality(Context context) {
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
String locality = address.getLocality();
return locality;
} else {
return null;
}
}
/**
* Try to get Postal Code
*
* @return null or postalCode
*/
public String getPostalCode(Context context) {
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
String postalCode = address.getPostalCode();
return postalCode;
} else {
return null;
}
}
/**
* Try to get CountryName
*
* @return null or postalCode
*/
public String getCountryName(Context context) {
List<Address> addresses = getGeocoderAddress(context);
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
String countryName = address.getCountryName();
return countryName;
} else {
return null;
}
}
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onProviderDisabled(String provider) {
showSettingsAlert();
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
I hope it will be helpful to anyone.
Updated with latest code also included change location with autocomplete
Complete project can be found here
Logic is Simple we need a framelayout
and add a map and marker layout inside that framelayout
then make maker layout gravity to center and get latitude and longitude of the centre point of the map on camera change
refer this answer
here is my code
create activity_maps.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical">
<LinearLayout
android:id="@+id/container_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="5dp"
android:orientation="vertical">
<TextView android:gravity="center_vertical"
android:id="@+id/Locality"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_btn_current_location"
android:drawablePadding="@dimen/list_row_padding"
android:ellipsize="end"
android:padding="10dp"
android:singleLine="true"
android:text="Click to change location"
android:textSize="@dimen/font_22" />
<EditText
android:id="@+id/Address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:enabled="false"
android:hint="Address"
android:singleLine="true" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/container_toolbar">
<fragment
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sample.sishin.maplocation.MapsActivity" />
<LinearLayout
android:id="@+id/locationMarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="30dp"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/locationMarkertext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/rounded_corner_map"
android:gravity="center"
android:minWidth="250dp"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:text=" Set your Location "
android:textColor="@android:color/white" />
<ImageView
android:id="@+id/imageMarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/add_marker" />
</LinearLayout>
</FrameLayout>
create TextView
backgound xml here rounded_corner_map.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#000000" />
<stroke
android:width="2dp"
android:color="#FFFFFF" />
<padding
android:bottom="8dp"
android:left="1dp"
android:right="1dp"
android:top="8dp" />
<corners
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"
android:topLeftRadius="15dp"
android:topRightRadius="15dp" />
</shape>
and here is my activity class MainActivity.java
package com.sample.sishin.maplocation;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Handler;
import android.os.ResultReceiver;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
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.GoogleApiAvailability;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
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.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static String TAG = "MAP LOCATION";
Context mContext;
TextView mLocationMarkerText;
private LatLng mCenterLatLong;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* The formatted location address.
*/
protected String mAddressOutput;
protected String mAreaOutput;
protected String mCityOutput;
protected String mStateOutput;
EditText mLocationAddress;
TextView mLocationText;
private static final int REQUEST_CODE_AUTOCOMPLETE = 1;
Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mContext = this;
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mLocationMarkerText = (TextView) findViewById(R.id.locationMarkertext);
mLocationAddress = (EditText) findViewById(R.id.Address);
mLocationText = (TextView) findViewById(R.id.Locality);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle(getResources().getString(R.string.app_name));
mLocationText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openAutocompleteActivity();
}
});
mapFragment.getMapAsync(this);
mResultReceiver = new AddressResultReceiver(new Handler());
if (checkPlayServices()) {
// If this check succeeds, proceed with normal processing.
// Otherwise, prompt user to get valid Play Services APK.
if (!AppUtils.isLocationEnabled(mContext)) {
// notify user
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setMessage("Location not enabled!");
dialog.setPositiveButton("Open location settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt) {
// TODO Auto-generated method stub
}
});
dialog.show();
}
buildGoogleApiClient();
} else {
Toast.makeText(mContext, "Location not supported in this device", Toast.LENGTH_SHORT).show();
}
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "OnMapReady");
mMap = googleMap;
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
Log.d("Camera postion change" + "", cameraPosition + "");
mCenterLatLong = cameraPosition.target;
mMap.clear();
try {
Location mLocation = new Location("");
mLocation.setLatitude(mCenterLatLong.latitude);
mLocation.setLongitude(mCenterLatLong.longitude);
startIntentService(mLocation);
mLocationMarkerText.setText("Lat : " + mCenterLatLong.latitude + "," + "Long : " + mCenterLatLong.longitude);
} catch (Exception e) {
e.printStackTrace();
}
}
});
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
// mMap.setMyLocationEnabled(true);
// mMap.getUiSettings().setMyLocationButtonEnabled(true);
//
// // Add a marker in Sydney and move the camera
// LatLng sydney = new LatLng(-34, 151);
// mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
// mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
@Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
changeMap(mLastLocation);
Log.d(TAG, "ON connected");
} else
try {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} catch (Exception e) {
e.printStackTrace();
}
try {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
try {
if (location != null)
changeMap(location);
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
protected void onStart() {
super.onStart();
try {
mGoogleApiClient.connect();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onStop() {
super.onStop();
try {
} catch (RuntimeException e) {
e.printStackTrace();
}
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
//finish();
}
return false;
}
return true;
}
private void changeMap(Location location) {
Log.d(TAG, "Reaching map" + mMap);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
// check if map is created successfully or not
if (mMap != null) {
mMap.getUiSettings().setZoomControlsEnabled(false);
LatLng latLong;
latLong = new LatLng(location.getLatitude(), location.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLong).zoom(19f).tilt(70).build();
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
mLocationMarkerText.setText("Lat : " + location.getLatitude() + "," + "Long : " + location.getLongitude());
startIntentService(location);
} else {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
/**
* Receiver for data sent from FetchAddressIntentService.
*/
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
/**
* Receives data sent from FetchAddressIntentService and updates the UI in MainActivity.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(AppUtils.LocationConstants.RESULT_DATA_KEY);
mAreaOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_AREA);
mCityOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_CITY);
mStateOutput = resultData.getString(AppUtils.LocationConstants.LOCATION_DATA_STREET);
displayAddressOutput();
// Show a toast message if an address was found.
if (resultCode == AppUtils.LocationConstants.SUCCESS_RESULT) {
// showToast(getString(R.string.address_found));
}
}
}
/**
* Updates the address in the UI.
*/
protected void displayAddressOutput() {
// mLocationAddressTextView.setText(mAddressOutput);
try {
if (mAreaOutput != null)
// mLocationText.setText(mAreaOutput+ "");
mLocationAddress.setText(mAddressOutput);
//mLocationText.setText(mAreaOutput);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
protected void startIntentService(Location mLocation) {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(AppUtils.LocationConstants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(AppUtils.LocationConstants.LOCATION_DATA_EXTRA, mLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
}
private void openAutocompleteActivity() {
try {
// The autocomplete activity requires Google Play Services to be available. The intent
// builder checks this and throws an exception if it is not the case.
Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
.build(this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
} catch (GooglePlayServicesRepairableException e) {
// Indicates that Google Play Services is either not installed or not up to date. Prompt
// the user to correct the issue.
GoogleApiAvailability.getInstance().getErrorDialog(this, e.getConnectionStatusCode(),
0 /* requestCode */).show();
} catch (GooglePlayServicesNotAvailableException e) {
// Indicates that Google Play Services is not available and the problem is not easily
// resolvable.
String message = "Google Play Services is not available: " +
GoogleApiAvailability.getInstance().getErrorString(e.errorCode);
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
}
/**
* Called after the autocomplete activity has finished to return its result.
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check that the result was from the autocomplete widget.
if (requestCode == REQUEST_CODE_AUTOCOMPLETE) {
if (resultCode == RESULT_OK) {
// Get the user's selected place from the Intent.
Place place = PlaceAutocomplete.getPlace(mContext, data);
// TODO call location based filter
LatLng latLong;
latLong = place.getLatLng();
//mLocationText.setText(place.getName() + "");
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(latLong).zoom(19f).tilt(70).build();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
mMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
} else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
Status status = PlaceAutocomplete.getStatus(mContext, data);
} else if (resultCode == RESULT_CANCELED) {
// Indicates that the activity closed before a selection was made. For example if
// the user pressed the back button.
}
}
}
And manifest file is
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sample.sishin.maplocation">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="your key here" />
<activity
android:name="com.sample.sishin.maplocation.MapsActivity"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.sample.sishin.maplocation.FetchAddressIntentService"
android:exported="false" />
</application>
</manifest>