Hi there, in this Android SpeedoMeter Tutorial you will learn how to fetch your live speed, distance and duration on your android app as you move around with your phone. This Android SpeedoMeter app makes use of the Google’s Location Service to calculate the speed of your mobile. It’s quite simple the way it functions. You can see the sample output of this Android Speedometer in the below image.

That’s what you are gonna get through in this project. So, Let’s get started with it.
Creating our Android SpeedoMeter
New Android Studio Project
So now lets begin creating our Android Speedometer.
- As usual, begin with creating a new Android Studio Project with empty Activity.
- To access the Google’s Location Service, add google play services dependency to your app level gradle and then sync it.
1 2 3 | compile 'com.google.android.gms:play-services:8.4.0' |
Creating a Location Service
- Create a class named LocationService.java and add the following code. It consists of a method called updateUI() which updates the live values of the Speed, Distance and Duration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | package chutka.bitman.com.speedometersimplified; import android.app.Service; import android.content.Intent; import android.location.Location; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.SystemClock; import android.support.annotation.Nullable; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import java.text.DecimalFormat; import java.util.concurrent.TimeUnit; /** * Created by vipul on 12/13/2015. */ public class LocationService extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static final long INTERVAL = 1000 * 2; private static final long FASTEST_INTERVAL = 1000 * 1; LocationRequest mLocationRequest; GoogleApiClient mGoogleApiClient; Location mCurrentLocation, lStart, lEnd; static double distance = 0; double speed; private final IBinder mBinder = new LocalBinder(); @Nullable @Override public IBinder onBind(Intent intent) { createLocationRequest(); mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); mGoogleApiClient.connect(); return mBinder; } protected void createLocationRequest() { mLocationRequest = new LocationRequest(); mLocationRequest.setInterval(INTERVAL); mLocationRequest.setFastestInterval(FASTEST_INTERVAL); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onConnected(Bundle bundle) { try { LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); } catch (SecurityException e) { } } protected void stopLocationUpdates() { LocationServices.FusedLocationApi.removeLocationUpdates( mGoogleApiClient, this); distance = 0; } @Override public void onConnectionSuspended(int i) { } @Override public void onLocationChanged(Location location) { MainActivity.locate.dismiss(); mCurrentLocation = location; if (lStart == null) { lStart = mCurrentLocation; lEnd = mCurrentLocation; } else lEnd = mCurrentLocation; //Calling the method below updates the live values of distance and speed to the TextViews. updateUI(); //calculating the speed with getSpeed method it returns speed in m/s so we are converting it into kmph speed = location.getSpeed() * 18 / 5; } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } public class LocalBinder extends Binder { public LocationService getService() { return LocationService.this; } } //The live feed of Distance and Speed are being set in the method below . private void updateUI() { if (MainActivity.p == 0) { distance = distance + (lStart.distanceTo(lEnd) / 1000.00); MainActivity.endTime = System.currentTimeMillis(); long diff = MainActivity.endTime - MainActivity.startTime; diff = TimeUnit.MILLISECONDS.toMinutes(diff); MainActivity.time.setText("Total Time: " + diff + " minutes"); if (speed > 0.0) MainActivity.speed.setText("Current speed: " + new DecimalFormat("#.##").format(speed) + " km/hr"); else MainActivity.speed.setText("......."); MainActivity.dist.setText(new DecimalFormat("#.###").format(distance) + " Km's."); lStart = lEnd; } } @Override public boolean onUnbind(Intent intent) { stopLocationUpdates(); if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect(); lStart = null; lEnd = null; distance = 0; return super.onUnbind(intent); } } |
- Now, when we have created the Location Service, its time to configure the uses of this service and that’ll be done in MainActivity.java. Hence, add the following code to your MainActivity.java. It consists of methods to bind and unbind the location service as per required.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | package chutka.bitman.com.speedometersimplified; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class MainActivity extends AppCompatActivity { LocationService myService; static boolean status; LocationManager locationManager; static TextView dist, time, speed; Button start, pause, stop; static long startTime, endTime; ImageView image; static ProgressDialog locate; static int p = 0; private ServiceConnection sc = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { LocationService.LocalBinder binder = (LocationService.LocalBinder) service; myService = binder.getService(); status = true; } @Override public void onServiceDisconnected(ComponentName name) { status = false; } }; void bindService() { if (status == true) return; Intent i = new Intent(getApplicationContext(), LocationService.class); bindService(i, sc, BIND_AUTO_CREATE); status = true; startTime = System.currentTimeMillis(); } void unbindService() { if (status == false) return; Intent i = new Intent(getApplicationContext(), LocationService.class); unbindService(sc); status = false; } @Override protected void onResume() { super.onResume(); } @Override protected void onStart() { super.onStart(); } @Override protected void onDestroy() { super.onDestroy(); if (status == true) unbindService(); } @Override public void onBackPressed() { if (status == false) super.onBackPressed(); else moveTaskToBack(true); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dist = (TextView) findViewById(R.id.distancetext); time = (TextView) findViewById(R.id.timetext); speed = (TextView) findViewById(R.id.speedtext); start = (Button) findViewById(R.id.start); pause = (Button) findViewById(R.id.pause); stop = (Button) findViewById(R.id.stop); image = (ImageView) findViewById(R.id.image); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //The method below checks if Location is enabled on device or not. If not, then an alert dialog box appears with option //to enable gps. checkGps(); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { return; } if (status == false) //Here, the Location Service gets bound and the GPS Speedometer gets Active. bindService(); locate = new ProgressDialog(MainActivity.this); locate.setIndeterminate(true); locate.setCancelable(false); locate.setMessage("Getting Location..."); locate.show(); start.setVisibility(View.GONE); pause.setVisibility(View.VISIBLE); pause.setText("Pause"); stop.setVisibility(View.VISIBLE); } }); pause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (pause.getText().toString().equalsIgnoreCase("pause")) { pause.setText("Resume"); p = 1; } else if (pause.getText().toString().equalsIgnoreCase("Resume")) { checkGps(); locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { //Toast.makeText(this, "GPS is Enabled in your devide", Toast.LENGTH_SHORT).show(); return; } pause.setText("Pause"); p = 0; } } }); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (status == true) unbindService(); start.setVisibility(View.VISIBLE); pause.setText("Pause"); pause.setVisibility(View.GONE); stop.setVisibility(View.GONE); p = 0; } }); } //This method leads you to the alert dialog box. void checkGps() { locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { showGPSDisabledAlertToUser(); } } //This method configures the Alert Dialog box. private void showGPSDisabledAlertToUser() { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setMessage("Enable GPS to use application") .setCancelable(false) .setPositiveButton("Enable GPS", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent callGPSSettingIntent = new Intent( android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(callGPSSettingIntent); } }); alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = alertDialogBuilder.create(); alert.show(); } } |
- By now, we are done with the Java part.
Creating User Interface
- Now, we need to configure the activity_main.xml. Add the following code to activity_main.xml which consists of TextViews to display the speed, distance and duration and some buttons.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/black" android:orientation="vertical"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:src="@mipmap/ic_launcher" android:visibility="gone" /> <TextView android:id="@+id/distancetext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:gravity="center" android:singleLine="true" android:text="Total Distance:" android:textColor="@android:color/white" android:textSize="25sp" android:textStyle="bold" /> <TextView android:id="@+id/speedtext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="150dp" android:gravity="center" android:singleLine="true" android:text="Instantaneous Speed:" android:textColor="@android:color/white" android:textSize="18sp" /> <TextView android:id="@+id/timetext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="190dp" android:gravity="center" android:singleLine="true" android:text="Total Time:" android:textColor="@android:color/white" android:textSize="17sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:orientation="horizontal"> <Button android:id="@+id/start" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:background="@android:color/white" android:paddingBottom="0dp" android:text="Start Calculating" /> <Button android:id="@+id/pause" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_weight="1" android:background="@android:color/white" android:text="Pause" android:visibility="gone" /> <Button android:id="@+id/stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginLeft="2dp" android:layout_weight="1" android:background="@android:color/white" android:text="Stop" android:visibility="gone" /> </LinearLayout> </FrameLayout> |
- We are almost done. Just update the AndroidManifest.xml and mention the Location Service as it is in the code below.
- Please note that the app will only work below Android Lollipop versions. If you want to make the app work in above Android Lollipop then you need to ask the permissions at run time. To modify this app and ask the permission at run time you can refer to this Android Marshmallow Permission Example Tutorial.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="chutka.bitman.com.speedometersimplified"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <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=".MainActivity" android:label="@string/app_name" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".LocationService"></service> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> </application> </manifest> |
- And you did it. Run the app now and hit the start calculating button. It would ask you to enable your gps. As you do, its gonna fetch your location and then show your live speed and all.
- If you are facing some problems then you can download my source code from the link given below.
If you still find some problem, let me know in the comments section I will try my best to sort out your queries. Thank You 🙂
Hello, I am Manish Kumar. I am a B.Tech Student at NIT Jamshedpur. Fortunately, I find myself quite passionate about Computers and Technology. Android is my most recent Crush.
nice tutorial.. can u tell me how Uber or Ola calculates live distance?? and what’s difference between these all
Location.distanceTo()
Location.distanceBetween()
SphericalUtil.computeDistanceBetween()
It is very difficult to comment onto how ola calculates live distance as there are numerous ways. As as far these methods you mentioned are concerned, as there name suggests, these methods are used to calculate distance between two geographical locations .For example:-
Location locationA = new Location(“point A”);
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location(“point B”);
locationB.setLatitude(latB);
locationB.setLongitude(lngB);
float distance = locationA.distanceTo(locationB);
i know these all calculate distance between two locations. i wanted to know the difference between these three. i have made taxi sharing app for a client in which i used direction api for estimated distance and location.distanceBetween() method for live distance calculation. i wanted to know if there’s a better approach to do the same .thanks for replying.
Hello boss
Can you share PEDOMETER code..for counting foot steps…
https://github.com/bagilevi/android-pedometer/archive/master.zip Here you go. Hope this helps:)
hello manish,
can you share a simple gps live tracker code.
Try this and then let me know.
https://github.com/nickfox/GpsTracker/archive/master.zip
Hi Manish,
Can you share a webservices project where we can do CURD operations using PHP and MySql…?
Its already on the website
https://www.simplifiedcoding.net/android-mysql-tutorial-to-perform-basic-crud-operation/
when i open application it take long time to getting location and stop at this screen i dont know why
can you help me to made an alert or message box when speed reach 120
i wouldbe grateful thnx
Sir tutorials is good for me Thanks..
But i have one query,
When I run my app speed continuously increasing after some seconds..
I am a beginner, maybe this question is nasty one but please reply ASAP..
Thanks 🙂
hey, the app doesnt ask for activation of gps once i click start calculating button it just gets stuck on trying to get my location.
same with how to fix it it display getting location
Can you tell more details about how to fix it?
i want to create a gauge of speed from 1 to 60 but i have no idea how to crate it using android studio
kindly help me.
where you get the google maps json ? this will be cool if you can Help me.
First, thx for your awesome work.
I have one Problem, using your app it’s searching all time “getting location” and nothing happens. GPS is on im on outside still no works, debug mod says all is ok, any idea? thx
Running Android-Version: 7.0
I run it under version 7 but still not working
Plz help me
Hello sir this code work fine for me . i want to show path on map with this code i get current location from on_location_changed method.
My question is this that how can i get last location when i press stop button in the above code.??
Please help me I am just stuck in this for 2 weeks.
Excellent example of location updation with fuesApi
It works fine. But some times it start increasing distance(10 – 400 meters) without even I move from my place. what should i do for its accuracy
When I start the application, it says getting location forever. It does not asks for any permissions. Please help. I need to submit this project in my college
Hi, great code
But in the dependencies (compile ‘com.google.android.gms:play-services:8.4.0’) this cause the app to crash at run time. what is the fix or it says (All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions 28.0.0, 23.0.0. Examples include)
Please help?