Tuesday, December 1, 2015

Calculate Speed from GPS Location Change in Android Mobile Device





From today’s article we are going to discuss how to calculate current moving speed of a mobile phone. (Actually we are going to calculate current moving speed of a mobile phone user through his or her mobile device).


        Mainly there are two ways to calculate the speed from mobile phone.
  • ·         Calculate speed from Accelerometer
  • ·          Calculate speed from GPS Technology

Unlike Accelerometer from GPS Technology if you going to calculate speed you must enable data connection and GPS connection.

So Today we are going to calculate speed using GPS connection.
In this method we using how frequency the GPS Location points are changing during single time period. Then if we have the real distance between the geo locations points be can get the speed. Because we have the distance and the time.
Speed = distance/time
But getting the distance between two location points is not very easy. Because the world is a goal in shape the diastase between two geo points is different from place to place and angle to angle. So we have to use  Haversine Algorithm


First we have to give permission for Get Location data in Manifest file

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

1.      Make the GUI




<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/txtCurrentSpeed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="000.0 miles/hour"
        android:textAppearance="?android:attr/textAppearanceLarge" />
   
    <CheckBox android:id="@+id/chkMetricUnits"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Use metric units?"/>

1.      Then make an interface to get the speed

package com.isuru.speedometer;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;

public interface IBaseGpsListener extends LocationListener, GpsStatus.Listener {
     
      public void onLocationChanged(Location location);
     
      public void onProviderDisabled(String provider);
     
      public void onProviderEnabled(String provider);
     
      public void onStatusChanged(String provider, int status, Bundle extras);
     
      public void onGpsStatusChanged(int event);

}



2.      Implement the logic to get the speed using the GPS Location

package com.isuru.speedometer;

import android.location.Location;

public class CLocation extends Location {

      private boolean bUseMetricUnits = false;
     
      public CLocation(Location location)
      {
            this(location, true);
      }

      public CLocation(Location location, boolean bUseMetricUnits) {
            // TODO Auto-generated constructor stub
            super(location);
            this.bUseMetricUnits = bUseMetricUnits;
      }
     
     
      public boolean getUseMetricUnits()
      {
            return this.bUseMetricUnits;
      }
     
      public void setUseMetricunits(boolean bUseMetricUntis)
      {
            this.bUseMetricUnits = bUseMetricUntis;
      }

      @Override
      public float distanceTo(Location dest) {
            // TODO Auto-generated method stub
            float nDistance = super.distanceTo(dest);
            if(!this.getUseMetricUnits())
            {
                  //Convert meters to feet
                  nDistance = nDistance * 3.28083989501312f;
            }
            return nDistance;
      }

      @Override
      public float getAccuracy() {
            // TODO Auto-generated method stub
            float nAccuracy = super.getAccuracy();
            if(!this.getUseMetricUnits())
            {
                  //Convert meters to feet
                  nAccuracy = nAccuracy * 3.28083989501312f;
            }
            return nAccuracy;
      }

      @Override
      public double getAltitude() {
            // TODO Auto-generated method stub
            double nAltitude = super.getAltitude();
            if(!this.getUseMetricUnits())
            {
                  //Convert meters to feet
                  nAltitude = nAltitude * 3.28083989501312d;
            }
            return nAltitude;
      }

      @Override
      public float getSpeed() {
            // TODO Auto-generated method stub
            float nSpeed = super.getSpeed() * 3.6f;
            if(!this.getUseMetricUnits())
            {
                  //Convert meters/second to miles/hour
                  nSpeed = nSpeed * 2.2369362920544f/3.6f;
            }
            return nSpeed;
      }
     
     
     
}

3.      Combine logic to GUI

package com.isuru.speedometer;

import java.util.Formatter;
import java.util.Locale;

import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;

public class MainActivity extends Activity implements IBaseGpsListener {

      @Override
      protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
            this.updateSpeed(null);
           
            CheckBox chkUseMetricUntis = (CheckBox) this.findViewById(R.id.chkMetricUnits);
            chkUseMetricUntis.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                 
                  @Override
                  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        // TODO Auto-generated method stub
                        MainActivity.this.updateSpeed(null);
                  }
            });
      }
     
      public void finish()
      {
            super.finish();
            System.exit(0);
      }

      private void updateSpeed(CLocation location) {
            // TODO Auto-generated method stub
            float nCurrentSpeed = 0;
           
            if(location != null)
            {
                  location.setUseMetricunits(this.useMetricUnits());
                  nCurrentSpeed = location.getSpeed();
            }
           
            Formatter fmt = new Formatter(new StringBuilder());
            fmt.format(Locale.US, "%5.1f", nCurrentSpeed);
            String strCurrentSpeed = fmt.toString();
            strCurrentSpeed = strCurrentSpeed.replace(' ', '0');
           
            String strUnits = "miles/hour";
            if(this.useMetricUnits())
            {
                  strUnits = "meters/second";
            }
           
            TextView txtCurrentSpeed = (TextView) this.findViewById(R.id.txtCurrentSpeed);
            txtCurrentSpeed.setText(strCurrentSpeed + " " + strUnits);
      }

      private boolean useMetricUnits() {
            // TODO Auto-generated method stub
            CheckBox chkUseMetricUnits = (CheckBox) this.findViewById(R.id.chkMetricUnits);
            return chkUseMetricUnits.isChecked();
      }

      @Override
      public void onLocationChanged(Location location) {
            // TODO Auto-generated method stub
            if(location != null)
            {
                  CLocation myLocation = new CLocation(location, this.useMetricUnits());
                  this.updateSpeed(myLocation);
            }
      }

      @Override
      public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub
           
      }

      @Override
      public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
           
      }

      @Override
      public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub
           
      }

      @Override
      public void onGpsStatusChanged(int event) {
            // TODO Auto-generated method stub
           
      }
     
     

}


If you want to convert Meters/Second to  kmph-1   then you need to multipl the  Meters/Second answer from 3.6


Speed from kmph-1 =    3.6 * (Speed from ms-1)