Jun 5, 2013

Fused location provider example

src :http://developer.android.com/google/play-services/location.html
Fused location provider beckoned the first radical improvement that Location Management has witnessed in Android. It used to be a very challenging and complex task to develop location aware applications in Android until Fused location provider was introduced. I recommend to read the article "A Deep Drive into location" by +Reto Meier and study these two open source libraries "Andorid protips location" and "little fluffy location library" to understand challenge and complexity

Fused Location provider makes things very easy for the developers.The Fused Location Provider intelligently manages the underlying location technology and gives you the best location according to your needs. It's simple to use, provide immediate location, power efficient and part of Google Play Service.

Fused location provider provide three ways to fetch location

1.  Last Location: Use when you want to know current location once.
2. Request Location using Listener: Use when application is on screen / frontend and require continues location.
3. Request Location using Pending Intent: Use when application in background and require continues location.

Let's develop a simple application which demonstrate all the three methods

 

 

Code Snippet for all three methods

1. Last Location
private LocationClient locationclient;
..
..
locationclient = new LocationClient(this,this,this);
locationclient.connect();
..
..
Location loc =locationclient.getLastLocation();
Log.i(TAG, "Last Known Location :" + loc.getLatitude() + "," + loc.getLongitude());
..
..
locationclient.disconnect();

2. Request location using listener
private LocationClient locationclient;
private LocationRequest locationrequest;
..
..
locationclient = new LocationClient(this,this,this);
locationclient.connect();
..
..
locationrequest = LocationRequest.create();
locationrequest.setInterval(100);
locationclient.requestLocationUpdates(locationrequest, this);
..
..
@Override
public void onLocationChanged(Location location) {
 if(location!=null){
  Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
 }
  
}
..
..
locationclient.disconnect();

3. Request location using pendingintent
private LocationClient locationclient;
private LocationRequest locationrequest;
private Intent mIntentService;
private PendingIntent mPendingIntent;
..
..
locationclient = new LocationClient(this,this,this);
locationclient.connect();
// you will receive location update in LocationService
mIntentService = new Intent(this,LocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
locationrequest = LocationRequest.create();
locationrequest.setInterval(100);
locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
..
..
locationclient.disconnect();

Full Source Code Example

Step 1: Set up Google Play Service in current eclipse workspace, please refer this link for more information : http://developer.android.com/google/play-services/setup.html
Step 2: Create new project in eclipse named "Fused Location"
Step 3: Open activity_main.xml and add following code, activity content main three section for 1. last location 2. location request using listener 3. location request using pendingintent, for 3rd method we need to create one intentservice.
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/txtConnectionStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:gravity="center"
        android:text="Connection Status"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/txtLastKnownLoc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnLastLoc"
        android:layout_alignRight="@+id/btnLastLoc"
        android:layout_below="@+id/btnLastLoc"
        android:gravity="center"
        android:text="0.0,0.0"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <Button
        android:id="@+id/btnLastLoc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/txtConnectionStatus"
        android:layout_alignRight="@+id/txtConnectionStatus"
        android:layout_below="@+id/txtConnectionStatus"
        android:layout_marginTop="18dp"
        android:onClick="buttonClicked"
        android:text="Fetch Last Location" />

    <Button
        android:id="@+id/btnStartRequest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_alignRight="@+id/txtLastKnownLoc"
        android:layout_below="@+id/etLocationInterval"
        android:onClick="buttonClicked"
        android:text="Start" />

    <TextView
        android:id="@+id/txtLocationRequest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btnStartRequest"
        android:layout_alignRight="@+id/btnStartRequest"
        android:layout_below="@+id/btnStartRequest"
        android:gravity="center"
        android:text="0.0,0.0"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <EditText
        android:id="@+id/etLocationInterval"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/txtLastKnownLoc"
        android:layout_alignTop="@+id/textView1"
        android:ems="3"
        android:inputType="number"
        android:text="100" >
    </EditText>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/txtLastKnownLoc"
        android:layout_below="@+id/txtLastKnownLoc"
        android:layout_marginTop="51dp"
        android:text="Location Request Listener"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/txtLocationRequest"
        android:layout_alignRight="@+id/txtLocationRequest"
        android:layout_below="@+id/txtLocationRequest"
        android:layout_marginTop="50dp"
        android:text="Request Location PendingIntent"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <Button
        android:id="@+id/btnRequestLocationIntent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView2"
        android:layout_alignRight="@+id/textView2"
        android:layout_below="@+id/textView2"
        android:onClick="buttonClicked"
        android:text="Start" />

</RelativeLayout>

Step 4: Open MainActivity.java file and add following code.
package com.kpbird.fusedlocation;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
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.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener {

 private String TAG = this.getClass().getSimpleName();
 
 private TextView txtConnectionStatus;
 private TextView txtLastKnownLoc;
 private EditText etLocationInterval;
 private TextView txtLocationRequest;
 
 private LocationClient locationclient;
 private LocationRequest locationrequest;
 private Intent mIntentService;
 private PendingIntent mPendingIntent;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  txtConnectionStatus = (TextView) findViewById(R.id.txtConnectionStatus);
  txtLastKnownLoc = (TextView) findViewById(R.id.txtLastKnownLoc);
  etLocationInterval = (EditText) findViewById(R.id.etLocationInterval);
  txtLocationRequest = (TextView) findViewById(R.id.txtLocationRequest);
  
  mIntentService = new Intent(this,LocationService.class);
  mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);
  
  int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
  if(resp == ConnectionResult.SUCCESS){
   locationclient = new LocationClient(this,this,this);
   locationclient.connect();
  }
  else{
   Toast.makeText(this, "Google Play Service Error " + resp, Toast.LENGTH_LONG).show();
   
  }
  
 }
 public void buttonClicked(View v){
  if(v.getId() == R.id.btnLastLoc){
   if(locationclient!=null && locationclient.isConnected()){
    Location loc =locationclient.getLastLocation();
    Log.i(TAG, "Last Known Location :" + loc.getLatitude() + "," + loc.getLongitude());
    txtLastKnownLoc.setText(loc.getLatitude() + "," + loc.getLongitude()); 
   }
  }
  if(v.getId() == R.id.btnStartRequest){
   if(locationclient!=null && locationclient.isConnected()){
    
    if(((Button)v).getText().equals("Start")){
     locationrequest = LocationRequest.create();
     locationrequest.setInterval(Long.parseLong(etLocationInterval.getText().toString()));
     locationclient.requestLocationUpdates(locationrequest, this);
     ((Button) v).setText("Stop"); 
    }
    else{
     locationclient.removeLocationUpdates(this);
     ((Button) v).setText("Start");
    }
    
   }
  }
  if(v.getId() == R.id.btnRequestLocationIntent){
   if(((Button)v).getText().equals("Start")){
    
    locationrequest = LocationRequest.create();
    locationrequest.setInterval(100);
    locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
    
    ((Button) v).setText("Stop");
   }
   else{
    locationclient.removeLocationUpdates(mPendingIntent);
    ((Button) v).setText("Start");
   }
  }
 }
 
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(locationclient!=null)
   locationclient.disconnect();
 }

 @Override
 public void onConnected(Bundle connectionHint) {
  Log.i(TAG, "onConnected");
  txtConnectionStatus.setText("Connection Status : Connected");
  
 }

 @Override
 public void onDisconnected() {
  Log.i(TAG, "onDisconnected");
  txtConnectionStatus.setText("Connection Status : Disconnected");
  
 }

 @Override
 public void onConnectionFailed(ConnectionResult result) {
  Log.i(TAG, "onConnectionFailed");
  txtConnectionStatus.setText("Connection Status : Fail");

 }

 @Override
 public void onLocationChanged(Location location) {
  if(location!=null){
   Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
   txtLocationRequest.setText(location.getLatitude() + "," + location.getLongitude());
  }
  
 }
}

Step 5 : Create new class for IntentService, named "LocationService", LocationService will receive location from 3rd method and display notification in notification bar.
package com.kpbird.fusedlocation;

import android.app.IntentService;
import android.app.NotificationManager;
import android.content.Intent;
import android.location.Location;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;

import com.google.android.gms.location.LocationClient;

public class LocationService extends IntentService {

 private String TAG = this.getClass().getSimpleName();
 public LocationService() {
  super("Fused Location");
 }
 public LocationService(String name) {
  super("Fused Location");
 }
 @Override
 protected void onHandleIntent(Intent intent) {
   
   Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
   if(location !=null){
    Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
    Builder noti = new NotificationCompat.Builder(this);
    noti.setContentTitle("Fused Location");
    noti.setContentText(location.getLatitude() + "," + location.getLongitude());
    noti.setSmallIcon(R.drawable.ic_launcher);
    notificationManager.notify(1234, noti.build());
   }
 }

}

Step 6 : Open AndroidManifest.xml and add user permission for location and register LocationService.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kpbird.fusedlocation"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="14" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="LocationService"></service>
    </application>

</manifest>

Grab full source code from Github : Download
How to use ?
1. clone code from github
2. import google play service in eclipse
3. import my example
4. change google play service library path from project properties->android