Merge pull request #66 from willum070/wfrench-current-place

Updates current place sample to use connectionless client
This commit is contained in:
Stephen McDonald 2017-08-16 09:36:03 +10:00 committed by GitHub
commit 746b79db41
4 changed files with 168 additions and 157 deletions

View File

@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android { android {
compileSdkVersion 25 compileSdkVersion 25
buildToolsVersion "23.0.3" buildToolsVersion "25.0.0"
defaultConfig { defaultConfig {
applicationId "com.example.currentplacedetailsonmap" applicationId "com.example.currentplacedetailsonmap"
minSdkVersion 15 minSdkVersion 15
@ -29,6 +29,6 @@ dependencies {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
compile 'com.android.support:appcompat-v7:25.1.1' compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.google.android.gms:play-services:10.0.1' compile 'com.google.android.gms:play-services:11.2.0'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
} }

View File

@ -16,13 +16,12 @@ import android.view.View;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.location.FusedLocationProviderClient;
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.location.LocationServices; import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.PlaceDetectionClient;
import com.google.android.gms.location.places.PlaceLikelihood; import com.google.android.gms.location.places.PlaceLikelihood;
import com.google.android.gms.location.places.PlaceLikelihoodBuffer; import com.google.android.gms.location.places.PlaceLikelihoodBufferResponse;
import com.google.android.gms.location.places.Places; import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap;
@ -32,21 +31,25 @@ import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
/** /**
* An activity that displays a map showing the place at the device's current location. * An activity that displays a map showing the place at the device's current location.
*/ */
public class MapsActivityCurrentPlace extends AppCompatActivity public class MapsActivityCurrentPlace extends AppCompatActivity
implements OnMapReadyCallback, implements OnMapReadyCallback {
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = MapsActivityCurrentPlace.class.getSimpleName(); private static final String TAG = MapsActivityCurrentPlace.class.getSimpleName();
private GoogleMap mMap; private GoogleMap mMap;
private CameraPosition mCameraPosition; private CameraPosition mCameraPosition;
// The entry point to Google Play services, used by the Places API and Fused Location Provider. // The entry points to the Places API.
private GoogleApiClient mGoogleApiClient; private GeoDataClient mGeoDataClient;
private PlaceDetectionClient mPlaceDetectionClient;
// The entry point to the Fused Location Provider.
private FusedLocationProviderClient mFusedLocationProviderClient;
// A default location (Sydney, Australia) and default zoom to use when location permission is // A default location (Sydney, Australia) and default zoom to use when location permission is
// not granted. // not granted.
@ -64,11 +67,11 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
private static final String KEY_LOCATION = "location"; private static final String KEY_LOCATION = "location";
// Used for selecting the current place. // Used for selecting the current place.
private final int mMaxEntries = 5; private static final int M_MAX_ENTRIES = 5;
private String[] mLikelyPlaceNames = new String[mMaxEntries]; private String[] mLikelyPlaceNames;
private String[] mLikelyPlaceAddresses = new String[mMaxEntries]; private String[] mLikelyPlaceAddresses;
private String[] mLikelyPlaceAttributions = new String[mMaxEntries]; private String[] mLikelyPlaceAttributions;
private LatLng[] mLikelyPlaceLatLngs = new LatLng[mMaxEntries]; private LatLng[] mLikelyPlaceLatLngs;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -83,17 +86,20 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
// Retrieve the content view that renders the map. // Retrieve the content view that renders the map.
setContentView(R.layout.activity_maps); setContentView(R.layout.activity_maps);
// Build the Play services client for use by the Fused Location Provider and the Places API. // Construct a GeoDataClient.
// Use the addApi() method to request the Google Places API and the Fused Location Provider. mGeoDataClient = Places.getGeoDataClient(this, null);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, // Construct a PlaceDetectionClient.
this /* OnConnectionFailedListener */) mPlaceDetectionClient = Places.getPlaceDetectionClient(this, null);
.addConnectionCallbacks(this)
.addApi(LocationServices.API) // Construct a FusedLocationProviderClient.
.addApi(Places.GEO_DATA_API) mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
.addApi(Places.PLACE_DETECTION_API)
.build(); // Build the map.
mGoogleApiClient.connect(); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
} }
/** /**
@ -108,36 +114,6 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
} }
} }
/**
* Builds the map when the Google Play services client is successfully connected.
*/
@Override
public void onConnected(Bundle connectionHint) {
// Build the map.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Handles failure to connect to the Google Play services client.
*/
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
// Refer to the reference doc for ConnectionResult to see what error codes might
// be returned in onConnectionFailed.
Log.d(TAG, "Play services connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
/**
* Handles suspension of the connection to the Google Play services client.
*/
@Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "Play services connection suspended");
}
/** /**
* Sets up the options menu. * Sets up the options menu.
* @param menu The options menu. * @param menu The options menu.
@ -184,7 +160,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
public View getInfoContents(Marker marker) { public View getInfoContents(Marker marker) {
// Inflate the layouts for the info window, title and snippet. // Inflate the layouts for the info window, title and snippet.
View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents, View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents,
(FrameLayout)findViewById(R.id.map), false); (FrameLayout) findViewById(R.id.map), false);
TextView title = ((TextView) infoWindow.findViewById(R.id.title)); TextView title = ((TextView) infoWindow.findViewById(R.id.title));
title.setText(marker.getTitle()); title.setText(marker.getTitle());
@ -196,6 +172,9 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
} }
}); });
// Prompt the user for permission.
getLocationPermission();
// Turn on the My Location layer and the related control on the map. // Turn on the My Location layer and the related control on the map.
updateLocationUI(); updateLocationUI();
@ -207,6 +186,42 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
* Gets the current location of the device, and positions the map's camera. * Gets the current location of the device, and positions the map's camera.
*/ */
private void getDeviceLocation() { private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (mLocationPermissionGranted) {
Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
mLastKnownLocation = task.getResult();
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
/**
* Prompts the user for permission to use the device location.
*/
private void getLocationPermission() {
/* /*
* Request location permission, so that we can get the location of the * Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback, * device. The result of the permission request is handled by a callback,
@ -221,27 +236,6 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} }
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
if (mLocationPermissionGranted) {
mLastKnownLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
// Set the map's camera position to the current location of the device.
if (mCameraPosition != null) {
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition));
} else if (mLastKnownLocation != null) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
} }
/** /**
@ -276,44 +270,69 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
if (mLocationPermissionGranted) { if (mLocationPermissionGranted) {
// Get the likely places - that is, the businesses and other points of interest that // Get the likely places - that is, the businesses and other points of interest that
// are the best match for the device's current location. // are the best match for the device's current location.
@SuppressWarnings("MissingPermission") @SuppressWarnings("MissingPermission") final
PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi Task<PlaceLikelihoodBufferResponse> placeResult =
.getCurrentPlace(mGoogleApiClient, null); mPlaceDetectionClient.getCurrentPlace(null);
result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() { placeResult.addOnCompleteListener
(new OnCompleteListener<PlaceLikelihoodBufferResponse>() {
@Override @Override
public void onResult(@NonNull PlaceLikelihoodBuffer likelyPlaces) { public void onComplete(@NonNull Task<PlaceLikelihoodBufferResponse> task) {
if (task.isSuccessful() && task.getResult() != null) {
PlaceLikelihoodBufferResponse likelyPlaces = task.getResult();
// Set the count, handling cases where less than 5 entries are returned.
int count;
if (likelyPlaces.getCount() < M_MAX_ENTRIES) {
count = likelyPlaces.getCount();
} else {
count = M_MAX_ENTRIES;
}
int i = 0; int i = 0;
mLikelyPlaceNames = new String[mMaxEntries]; mLikelyPlaceNames = new String[count];
mLikelyPlaceAddresses = new String[mMaxEntries]; mLikelyPlaceAddresses = new String[count];
mLikelyPlaceAttributions = new String[mMaxEntries]; mLikelyPlaceAttributions = new String[count];
mLikelyPlaceLatLngs = new LatLng[mMaxEntries]; mLikelyPlaceLatLngs = new LatLng[count];
for (PlaceLikelihood placeLikelihood : likelyPlaces) { for (PlaceLikelihood placeLikelihood : likelyPlaces) {
// Build a list of likely places to show the user. Max 5. // Build a list of likely places to show the user.
mLikelyPlaceNames[i] = (String) placeLikelihood.getPlace().getName(); mLikelyPlaceNames[i] = (String) placeLikelihood.getPlace().getName();
mLikelyPlaceAddresses[i] = (String) placeLikelihood.getPlace().getAddress(); mLikelyPlaceAddresses[i] = (String) placeLikelihood.getPlace()
.getAddress();
mLikelyPlaceAttributions[i] = (String) placeLikelihood.getPlace() mLikelyPlaceAttributions[i] = (String) placeLikelihood.getPlace()
.getAttributions(); .getAttributions();
mLikelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng(); mLikelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng();
i++; i++;
if (i > (mMaxEntries - 1)) { if (i > (count - 1)) {
break; break;
} }
} }
// Release the place likelihood buffer, to avoid memory leaks. // Release the place likelihood buffer, to avoid memory leaks.
likelyPlaces.release(); likelyPlaces.release();
// Show a dialog offering the user the list of likely places, and add a // Show a dialog offering the user the list of likely places, and add a
// marker at the selected place. // marker at the selected place.
openPlacesDialog(); openPlacesDialog();
} else {
Log.e(TAG, "Exception: %s", task.getException());
}
} }
}); });
} else { } else {
// The user has not granted permission.
Log.i(TAG, "The user did not grant location permission.");
// Add a default marker, because the user hasn't selected a place. // Add a default marker, because the user hasn't selected a place.
mMap.addMarker(new MarkerOptions() mMap.addMarker(new MarkerOptions()
.title(getString(R.string.default_info_title)) .title(getString(R.string.default_info_title))
.position(mDefaultLocation) .position(mDefaultLocation)
.snippet(getString(R.string.default_info_snippet))); .snippet(getString(R.string.default_info_snippet)));
// Prompt the user for permission.
getLocationPermission();
} }
} }
@ -322,8 +341,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
*/ */
private void openPlacesDialog() { private void openPlacesDialog() {
// Ask the user to choose the place where they are now. // Ask the user to choose the place where they are now.
DialogInterface.OnClickListener listener = DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
// The "which" argument contains the position of the selected item. // The "which" argument contains the position of the selected item.
@ -332,6 +350,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
if (mLikelyPlaceAttributions[which] != null) { if (mLikelyPlaceAttributions[which] != null) {
markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[which]; markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[which];
} }
// Add a marker for the selected place, with an info window // Add a marker for the selected place, with an info window
// showing information about that place. // showing information about that place.
mMap.addMarker(new MarkerOptions() mMap.addMarker(new MarkerOptions()
@ -359,22 +378,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
if (mMap == null) { if (mMap == null) {
return; return;
} }
try {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
if (mLocationPermissionGranted) { if (mLocationPermissionGranted) {
mMap.setMyLocationEnabled(true); mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true); mMap.getUiSettings().setMyLocationButtonEnabled(true);
@ -382,6 +386,10 @@ public class MapsActivityCurrentPlace extends AppCompatActivity
mMap.setMyLocationEnabled(false); mMap.setMyLocationEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false); mMap.getUiSettings().setMyLocationButtonEnabled(false);
mLastKnownLocation = null; mLastKnownLocation = null;
getLocationPermission();
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
} }
} }
} }

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@ -14,6 +14,9 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
maven {
url 'https://maven.google.com'
}
jcenter() jcenter()
} }
} }

View File

@ -1,6 +1,6 @@
#Mon Dec 28 10:00:20 PST 2015 #Tue Aug 15 11:46:14 PDT 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip