Android

Get location in Android using Fused Location Provider Api

How to get location in Android : Fused Location Provider Api

How to get location in Android : Fused Location Provider Api

Hi…Today if we see the current application trends then there is huge requirement of tracking or knowing location related activities of user.

Note :

FusedLocationProvider api is deprecated from Google Play services version 11.6.0 release.

You can read it here: https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi

FusedLocationProviderClient is new way to fetch the user current location in terms of latitude and longitude.

For latest demo on FusedLocationProviderClient please check demo on:

https://github.com/askfortricks/FusedLocationProviderClient/

Think of  the scenario (e.g) :

 

1.How to display the custom products to user by based on user’s current location

 

2.Show nearby restaurants ,hospitals.

 

3.Show the user what’s other people is buying near them in e-commerce application and many more.

 

 

And all these uses the users current location to make the magic happen.

So content of post will go like this:

  • Configure the code for Fused Location Provider
  • Fetch current latitude and longitude
  • Refresh interval for updating latitude and longitude
  • Mapping the latitude and longitude using Reverse Geocoding to fetch address details like         pincode,city and other details.

So today we will see one api provided by Google which helps to fetch user’s latitude and longitude and by reverse Geocoding it binds that latitude and longitude to print city name with pincode.

Fused Location Provider Api

is the latest api  released by Google Play Services and thus today in this tutorial we will explore  the sample code to detect the location in Android application using Fused Location Provider Api.

Note: Please run the app in real devices and don’t use in emulators,Update your sdk to have the latest Google Play Services.

Top 10 free Android libraries for app development in android studio

And also this app requires the Google Play Services installed phone.

Finally what we read earlier in this post below is the video which shares more info about the usage of fused location provider api :

You can watch this video :

Advantages:

1.Simple Api Implementation:

Api implementation is very clear and simple as compared to old Location Api.

2. Versatility:

Meets wide range of requirements even those app which requires frequent location updates or accurate location updates.

3.Power Efficient:

Based on all incoming location requests and available sensors,this api chooses the most efficient way to meet those needs.

Main benefit: We do not have to switch to location settings to on the location or GPS ,instead this api will automatically show us the settings screen if it detects that location is not on.

Fused Location Provider
fused location provider


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.com.fusedlocationprovidermarshmallow">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".FusedLocationWithSettingsDialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>


apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "askfortricks.com.fusedlocationdemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.google.android.gms:play-services-location:10.0.0'
}

view raw

build.gradle

hosted with ❤ by GitHub


import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
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.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.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* Created by https://askfortricks.com
*
* step1 :buildGoogleApiClient
* step2: createLocationRequest
* step3: buildLocationSettingsRequest
*
*
* step 4:on click of button detect location check the location is on/off using checkLocationSettings method.
*
* step 5:on click of the options in location dialog
*
* step 6 :depending on the action taken on dialog (startResolution for result and check the action in onActivityResult
*
*/
public class FusedLocationWithSettingsDialog extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
ResultCallback<LocationSettingsResult> {
//Ui widgets
private Button btn_location;
private TextView txt_location;
protected TextView mLastUpdateTimeTextView;
protected TextView mLatitudeTextView;
protected TextView mLongitudeTextView;
//New views for city and pincode
protected TextView tv_pincode,tv_city;
protected static final String TAG = "MainActivity";
//Any random number you can take
public static final int REQUEST_PERMISSION_LOCATION = 10;
/**
* Constant used in the location settings dialog.
*/
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
/**
* The desired interval for location updates. Inexact. Updates may be more or less frequent.
*/
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
/**
* The fastest rate for active location updates. Exact. Updates will never be more frequent
* than this value.
*/
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
// Keys for storing activity state in the Bundle.
protected final static String KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected final static String KEY_LOCATION = "location";
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Stores the types of location services the client is interested in using. Used for checking
* settings to determine if the device has optimal location settings.
*/
protected LocationSettingsRequest mLocationSettingsRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
// Labels.
protected String mLatitudeLabel;
protected String mLongitudeLabel;
protected String mLastUpdateTimeLabel;
/**
* Tracks the status of the location updates request. Value changes when the user presses the
* Start Updates and Stop Updates buttons.
*/
protected Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
int RQS_GooglePlayServices=0;
@Override
protected void onStart() {
super.onStart();
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(this);
if (resultCode == ConnectionResult.SUCCESS) {
mGoogleApiClient.connect();
} else {
googleAPI.getErrorDialog(this,resultCode, RQS_GooglePlayServices);
}
}
@Override
protected void onResume() {
super.onResume();
// Within {@code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
// Toast.makeText(FusedLocationWithSettingsDialog.this, "location was already on so detecting location now", Toast.LENGTH_SHORT).show();
startLocationUpdates();
}
}
@Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
@Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_fused_location);
btn_location = (Button) findViewById(R.id.btn_detect_fused_location);
//total six textviews
txt_location = (TextView) findViewById(R.id.txt_location);
mLatitudeTextView = (TextView) findViewById(R.id.mLatitudeTextView);
mLongitudeTextView = (TextView) findViewById(R.id.mLongitudeTextView);
mLastUpdateTimeTextView = (TextView) findViewById(R.id.mLastUpdateTimeTextView);
tv_city=(TextView)findViewById(R.id.tv_city);
tv_pincode=(TextView)findViewById(R.id.tv_pincode);
// Set labels.
mLatitudeLabel = getResources().getString(R.string.latitude_label);
mLongitudeLabel = getResources().getString(R.string.longitude_label);
mLastUpdateTimeLabel = getResources().getString(R.string.last_update_time_label);
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Kick off the process of building the GoogleApiClient, LocationRequest, and
// LocationSettingsRequest objects.
//step 1
buildGoogleApiClient();
//step 2
createLocationRequest();
//step 3
buildLocationSettingsRequest();
btn_location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkLocationSettings();
}
});
}
//step 1
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
//step 2
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
//step 3
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
//step 4
protected void checkLocationSettings() {
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
);
result.setResultCallback(this);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);
}
else
{
goAndDetectLocation();
}
}
public void goAndDetectLocation()
{
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this
).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
mRequestingLocationUpdates = true;
// setButtonsEnabledState();
}
});
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
mRequestingLocationUpdates = false;
// setButtonsEnabledState();
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_PERMISSION_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
goAndDetectLocation();
}
break;
}
}
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to GoogleApiClient");
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
}
@Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "Connection suspended");
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
/**
* Invoked when settings dialog is opened and action taken
* @param locationSettingsResult
* This below OnResult will be used by settings dialog actions.
*/
//step 5
@Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
Toast.makeText(FusedLocationWithSettingsDialog.this, "Location is already on.", Toast.LENGTH_SHORT).show();
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to" +
"upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
Toast.makeText(FusedLocationWithSettingsDialog.this, "Location dialog will be open", Toast.LENGTH_SHORT).show();
//
//move to step 6 in onActivityResult to check what action user has taken on settings dialog
status.startResolutionForResult(FusedLocationWithSettingsDialog.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
"not created.");
break;
}
}
/**
* This OnActivityResult will listen when
* case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: is called on the above OnResult
*/
//step 6:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
break;
}
break;
}
}
/**
* Sets the value of the UI fields for the location latitude, longitude and last update time.
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
mLatitudeTextView.setText(String.format("%s: %f", mLatitudeLabel,
mCurrentLocation.getLatitude()));
mLongitudeTextView.setText(String.format("%s: %f", mLongitudeLabel,
mCurrentLocation.getLongitude()));
mLastUpdateTimeTextView.setText(String.format("%s: %s", mLastUpdateTimeLabel,
mLastUpdateTime));
updateCityAndPincode(mCurrentLocation.getLatitude(),mCurrentLocation.getLongitude());
}
}
/**
* This updateCityAndPincode method uses Geocoder api to map the latitude and longitude into city location or pincode.
* We can retrieve many details using this Geocoder class.
*
And yes the Geocoder will not work unless you have data connection or wifi connected to internet.
*/
private void updateCityAndPincode(double latitude, double longitude)
{
try
{
Geocoder gcd = new Geocoder(FusedLocationWithSettingsDialog.this, Locale.getDefault());
List<Address> addresses = gcd.getFromLocation(latitude, longitude, 1);
if (addresses.size() > 0)
{
tv_city.setText("City="+addresses.get(0).getLocality());
tv_pincode.setText("Pincode="+addresses.get(0).getPostalCode());
// System.out.println(addresses.get(0).getLocality());
}
}
catch (Exception e)
{
Log.e(TAG,"exception:"+e.toString());
}
}
}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">
<Button
android:id="@+id/btn_detect_fused_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Detect location"
/>
<TextView
android:id="@+id/txt_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="10dp"/>
<TextView
android:id="@+id/mLatitudeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/mLongitudeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/mLastUpdateTimeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/tv_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<TextView
android:id="@+id/tv_pincode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
</LinearLayout>

You can get the complete demo on GitHub:
HostSoch Web Hosting

https://github.com/askfortricks/FusedLocationProvider-Api-Demo

Google had recently updated the Fused Location Provider api with Fused Location Provider Client to just get the location in very few lines of code and with very less overhead involved. Infact  there is one issue related to Google Location fetching which can result into Null Pointer Exception was also solved.

In addition to above repository I am sharing the Fused Location Provider Client which is new addition to already great apis. This new api makes the enhancement in solving one bug in Fused Location Provider api. 

But that’s very basic code to fetch the latitude and longitude(SettingsClient Api also included to check if Location Services is enabled or not).

https://github.com/askfortricks/FusedLocationProviderClient 

In conclusion we can say that Fused Location Provider Client  will be new future and hope this post will guide you in right direction.

Please comment if you like this post and give your suggestions..so we can improve together.

You can visit this link to know more:

developer.android.com/training/location/index.html

Happy Blogging…

 

Feeling glad to receive your comment