Location based services in Android-Where Am I demo application


                This is a sample application for showing how to use Location based services(lbs) in an Android device. We have to use LocationManager to find out the location. The location can be identified by available resources such as GPS, Wireless network. In this example we have created mock location since the emulator does not have GPS support. In real devices there is no need to use mock locations. We use Geocoder to convert this location to an address.

The location is identified by longitude and latitude values. Geocoder will search online for known addresses. It will return number of matched results. This number can be manually specified while calling getFromLocation() method. This method will return empty list if no results found or if no back end services are available.
The application should implement LocationListener. This interface will be used my LocationManager to notify the change of locations. We are creating local reference to LocationManage from the current context using location manager system service. Then we create Geocoder local reference and pass the current context to it.

Then we have added mock location provider as shown below; Note that this is not needed in real applications.

// Initialize with the last known location
if (Settings.Secure.getInt(this.getContentResolver(),
    Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
}
// remove test provider if left over from an aborted run
    LocationProvider lp = locationManager
  .getProvider(TEST_MOCK_PROVIDER_NAME);
    if (lp != null) {
 locationManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
    }
addTestProvider(TEST_MOCK_PROVIDER_NAME);
Location location = new Location(TEST_MOCK_PROVIDER_NAME);
location.setLatitude(12.9377);
location.setLongitude(80.2153);
location.setTime(System.currentTimeMillis());
locationManager.setTestProviderLocation(TEST_MOCK_PROVIDER_NAME,
 location);

In real application no need to add the location details, it can be automatically be fetched using GPS.

Location lastLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);

The location manager memorizes its last known location. This is useful because it might take a while until we get the location lock via GPS or network provider.
onResume() method will be called en route to running state. We can use request requestLocationUpdates() method of location manager to register for location updates.
onPause() method will be invoked before the application goes to stopped state.
onLocationChanged() is the callback method which will be invoked by the location manager when it detects the location change.
We did not use other callback methods of the LocationListener.


AndroidManifest.xml
In order to use location based services we need to have number of permissions. Those permissions can be added in the manifest xml file.
android.permission.ACCESS_MOCK_LOCATION permission is used to mock provider.
android.permission.ACCESS_COARSE_LOCATION permission is used to access network provider
android.permission.ACCESS_FINE_LOCATION permission is used to access GPS provider
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS permission is usedn to send extra commands to GPS provider

Make sure that you are using necessary permissions in your application.
Most commonly used location providers are GPS and network provider. In future Android might add more and more. So Android breaks down location permission into abstract FINE location and COARSE location permissions.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.whereami"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="16" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.whereami.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>
    </application>

</manifest>

Layout xml file:
<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"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textOut"
        android:layout_width="254dp"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true"
        android:text="Waiting..."
        android:textColor="#333"
        android:textSize="25dp" >

        </TextView>
</RelativeLayout>

Activity java class:
addTestProvider() method in this class is used to add mock location provider. This is not needed in real applications. Use GPS provider or Network provider instead of TEST_MOCK_PROVIDER_NAME.


package com.example.whereami;

import java.io.IOException;
import java.util.List;

import android.app.Activity;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

/**
 * @author Prabu
 * 
 *         Requires the permissions 
 *         <br/>
 *         android.permission.ACCESS_MOCK_LOCATION to mock provider 
 *         <br/>
 *         android.permission.ACCESS_COARSE_LOCATION to access network provider 
 *         <br/>
 *         android.permission.ACCESS_FINE_LOCATION to access GPS provider 
 *         <br/>
 *         android.permission.ACCESS_LOCATION_EXTRA_COMMANDS to send extra commands to GPS provider
 */
public class MainActivity extends Activity implements LocationListener {

    LocationManager locationManager;
    Geocoder geocoder;
    TextView textOut;
    private static final String TEST_MOCK_PROVIDER_NAME = "test_provider";
    @Override
    public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 textOut = (TextView) findViewById(R.id.textOut);
 locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
 geocoder = new Geocoder(this);
 // Initialize with the last known location
 if (Settings.Secure.getInt(this.getContentResolver(),
  Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
 }
 // remove test provider if left over from an aborted run
 LocationProvider lp = locationManager
  .getProvider(TEST_MOCK_PROVIDER_NAME);
 if (lp != null) {
    locationManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
 }

 addTestProvider(TEST_MOCK_PROVIDER_NAME);
 Location location = new Location(TEST_MOCK_PROVIDER_NAME);
 location.setLatitude(12.9377);
 location.setLongitude(80.2153);
 location.setTime(System.currentTimeMillis());
 locationManager.setTestProviderLocation(TEST_MOCK_PROVIDER_NAME,
  location);
 Location lastLocation = locationManager
  .getLastKnownLocation(TEST_MOCK_PROVIDER_NAME);
 if (lastLocation != null)
    onLocationChanged(lastLocation);
 }

 @Override
 protected void onResume() {
     super.onRestart();
     locationManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 1000,10, this);
 }

 @Override
 protected void onPause() {
     super.onPause();
     locationManager.removeUpdates(this);
 }

 // Called when location has changed
 public void onLocationChanged(Location location) {
  String text = String.format(
  "Lat:\t %f\nLong:\t %f\nAlt:\t %f\nBearing:\t %f",
  location.getLatitude(), location.getLongitude(),
  location.getAltitude(), location.getBearing());
  textOut.setText(text);
  // Perform geocoding for this location
  try {
      List<Address> addresses = geocoder.getFromLocation(
   location.getLatitude(), location.getLongitude(), 10);
   for (Address address : addresses) {
       textOut.append("\n" + address.getAddressLine(0));
   }
  } catch (IOException e) {
      Log.e("WhereAmI", "Couldn't get Geocoder data", e);
  }
 }

 // Methods required by LocationListener
 public void onProviderDisabled(String provider) {
 }

 public void onProviderEnabled(String provider) {
 }

 public void onStatusChanged(String provider, int status, Bundle extras) {
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

 /**
  * Helper method to add a test provider with given name.
  */
 private void addTestProvider(final String providerName) {
  locationManager.addTestProvider(
  providerName, 
  true, // requiresNetwork,
  false, // requiresSatellite,
  true, // requiresCell,
  false, // hasMonetaryCost,
  false, // supportsAltitude,
  false, // supportsSpeed,
  false, // supportsBearing,
  Criteria.POWER_MEDIUM, // powerRequirement
  Criteria.ACCURACY_FINE); // accuracy
  locationManager.setTestProviderEnabled(providerName, true);
 }

}


Output screenshot:




Source code of this application:
WhereAmI.zip

 



Reactions:

0 comments :

Post a Comment