In my app, I have a speedometer class and I want to be able to say in my Broadcast Receiver class that when the speed goes over 25, do some action.
How would I go about doing that?
I have searched various questions but all lead me to a dead end.
Heres the Speedometer Code
package com.rrithvik.idrive;
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.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() * 2.24;
}
#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) * 0.00062);
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) + " mph");
}
else {
MainActivity.speed.setText(".......");
}
MainActivity.dist.setText("Total Distance " + new DecimalFormat("#.###").format(distance) + " miles.");
lStart = lEnd;
}
}
#Override
public boolean onUnbind(Intent intent) {
stopLocationUpdates();
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
lStart = null;
lEnd = null;
distance = 0;
return super.onUnbind(intent);
}
}
So once again, this action has to be done in the Broadcast Receiver Class
Maybe this is what you are searching
double speedNum = Double.parseDouble(speed)
and then do the checking whether the speedNum is larger than 25 or not.
If you convert your String to a Double value, you will can verify this number.
double speedDouble = Double.parseDouble(speedText);
if(speedDouble > 25) {
// Do something
}
Related
I want to create an App which fetch user's location in every 5 min between 9:00 AM to 9:00 PM. Now i am not able to think the flow. I am confused on:
Should i implement 2 repeating alarm managers , one for every 5 min and another one for time slot. ?
Or do it in a way, fire alarm every 5 min and check if it is in between time slot then only run location service and upload to server work. ?
Please help me with suggestions/advice. How to achieve this in best approach in terms of phone battery, efficiency.
You should not use Handler.postDelayer() for time intervals, longer than 30sec, because it may cause memory leaks. Develop a couple of strategies - one for short time intervals - less than 30 secs, which use Handler and another - with AlarmManager (for longer intervals).
refer https://codelabs.developers.google.com/codelabs/background-location-updates-android-o/index.html?index=..%2F..%2Findex#0
you can set update interval as 5 min in location request.it is compatible with Android "O" also.
Here I have created a service which gives current location at interval of 1 Minute.You can modify it as per your requirement-
Also add this in gradle file-
compile 'com.google.android.gms:play-services:9.4.0'
LocationService.class
import android.Manifest;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
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.SimpleDateFormat;
import java.util.Date;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
protected static final String TAG = "location-updates";
private static final long day = 24 * 60 * 60 * 1000;
private static final long hours = 60 * 60 * 1000;
private static final long minute = 60 * 1000;
private static final long fiveSec = 5 * 1000;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
#Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(minute);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setSmallestDisplacement(0);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
//Location Listener
#Override
public void onLocationChanged(final Location location) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
String currentDateandTime = sdf.format(new Date());
Log.e("Location ", location.getLatitude() + " " + location.getLongitude() + " " + currentDateandTime);
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
boolean isGranted = false;
for (int i = 0; i < grantResults.length; i++)
if (permissions[i].equals(Manifest.permission.ACCESS_FINE_LOCATION) && (grantResults[i] == PackageManager.PERMISSION_GRANTED))
isGranted = true;
if (isGranted) {
startService(new Intent(this, LocationService.class));
} else {
}
}
}
Well you can use handler for querying the location, you can do something like this
Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
currentLocation = getCurrentUserLocation();
handler.postDelayed(this, 1000*60*5);
}
}
};
handler.postDelayed(runnable, 1000*60*5);
And for checking the time interval is between, you can set a Alarm manager for this task,
And once time limit is reached, you need to remove the handler callbacks by
handleLocation.removeCallbacksAndMessages(null);
I want to know how to implement to get location on one mobile phone and show that mobile phone location.
Just like uber cab application. When we ask for the ride from one place to another place. They assign one cab for us Meanwhile there app also display the location of the cab driver. I want to know how they implement if some body guide us or give related document for this. Thanks in Advance, Its very Appriciable
You this following code to track changes in location events
DeviceLocation.java
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Result;
import com.google.android.gcm.server.Sender;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
public class DeviceLocation extends Service {
private GPSTracker gpsTracker;
private Handler handler = new Handler();
private Timer timer = new Timer();
private Distance pastDistance = new Distance();
private Distance currentDistance = new Distance();
public static double DISTANCE;
boolean flag = true;
private double totalDistance;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.v("Location1", "********* " + Thread.currentThread().getId());
gpsTracker = new GPSTracker(this);
// below code is to track change in past and present location events
// TimerTask timerTask = new TimerTask() {
//
// #Override
// public void run() {
// Log.v("Location2", "********* " + Thread.currentThread().getId());
// handler.post(new Runnable() {
//
// #Override
// public void run() {
// Log.v("Location3", "********* " + Thread.currentThread().getId());
// if (flag) {
// pastDistance.setLatitude(gpsTracker.getLocation().getLatitude());
// pastDistance.setLongitude(gpsTracker.getLocation().getLongitude());
// flag = false;
// } else {
// currentDistance.setLatitude(gpsTracker.getLocation().getLatitude());
// currentDistance.setLongitude(gpsTracker.getLocation().getLongitude());
// flag = comapre_LatitudeLongitude();
// }
// }
// });
// }
// };
// timer.schedule(timerTask, 0, 5000);
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
Log.v("Location2", "********* " + Thread.currentThread().getId());
handler.post(new Runnable() {
#Override
public void run() {
// send to server or device you need to send via GCM
SendMessage(String.valueOf(gpsTracker.getLocation().getLatitude())
String.valueOf(gpsTracker.getLocation().getLongitude()));
}
});
}
};
timer.schedule(timerTask, 0, 5000);
return START_STICKY;
}
public void Track(String lat, String lng) {
Sender sender = new Sender("AIzaSyAlXGdj3TGPAnKBiuhn4yxXgLKxwmHJnMY");
String GcmId = new TrackPref(this).getTrackId();
Message message = new Message.Builder()
.collapseKey("and_app")
.delayWhileIdle(true)
.addData("action", "location")
.addData("Lat", lat)
.addData("Long", lng)
.timeToLive(600)
.build();
Result result = null;
try {
result = sender.send(message, GcmId, 2);
} catch (IOException e) {
e.printStackTrace();
}
if (result.getMessageId() != null) {
String canonicalRegId = result.getCanonicalRegistrationId();
Log.d("abc", result.toString());
} else {
String error = result.getErrorCodeName();
}
}
private void SendMessage(final String lat, final String lng) {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
Track(lat, lng);
return null;
}
#Override
protected void onPostExecute(String msg) {
}
}.execute();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("--------------------------------onDestroy -stop service ");
timer.cancel();
DISTANCE = totalDistance ;
}
private double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
public boolean comapre_LatitudeLongitude() {
Log.v("Location4", "********* " + Thread.currentThread().getId());
if (pastDistance.getLatitude() == currentDistance.getLatitude() && pastDistance.getLongitude() == currentDistance.getLongitude()) {
return false;
} else {
final double distance = distance(pastDistance.getLatitude(), pastDistance.getLongitude(), currentDistance.getLatitude(), currentDistance.getLongitude());
System.out.println("Distance in mile :" + distance);
handler.post(new Runnable() {
#Override
public void run() {
float kilometer = 1.609344f;
Log.v("Location5", "********* " + Thread.currentThread().getId());
totalDistance = totalDistance + distance * kilometer;
DISTANCE = totalDistance;
}
});
return true;
}
}
}
For detailed information follow the code from below library.
https://github.com/raviteja06/TrackMyClient
this was done while back, make sure to update libraries to latest.
Try with following code:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{
GoogleApiClient googleApiClient;
int REQUEST_CHECK_SETTINGS = 1;
Location mLastLocation;
LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
checkForGPS();
}
public void checkForGPS(){
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
googleApiClient.connect();
if(!((LocationManager)getSystemService(Context.LOCATION_SERVICE)).isProviderEnabled(LocationManager.GPS_PROVIDER)) {
//prompt user to enable gps
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(3000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates states = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
}
}
#Override
public void onConnected(Bundle bundle) {
startLocationUpdates();
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
// put your code here to play with Location object
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
Here are some useful imports you may require:
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 com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStates;
import com.google.android.gms.location.LocationSettingsStatusCodes;
Don't forget to declare these permissions in Manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
I am using Google Play api to get device location and send it to server periodically (every 10 mins or on location change whichever arises first) via IntentService.
I am using LocationRequest.PRIORITY_HIGH_ACCURACY while building LocationRequest and the device GPS is also ON.
The api sometimes returns the location with high accuracy (<=100) but almost (>1000) other times.
How can the location accuracy attained ?
My Source :
package com.salesorder.locationmanager;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.gson.Gson;
import com.salesorder.constant.AppConstants;
import com.salesorder.entity.gson.LocationPostObject;
import com.salesorder.entity.gson.LogsGPS;
import com.salesorder.network.Connectivity;
import com.salesorder.network.WSClient;
import com.salesorder.storage.AppPreferences;
import com.salesorder.storage.dao.LogsGPSDAO;
import com.salesorder.util.CommonUtils;
public class SyncUserLocationService extends IntentService implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener {
private static final String TAG = "SyncUserLocationService";
private static final long ONE_MIN = 1000 * 60;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final long POLLING_FREQ = 1000 * 30;
private static final long FASTEST_UPDATE_FREQ = 1000 * 5;
private static final float MAX_ACCURACY = 150.0f;
private static final float MIN_LAST_READ_ACCURACY = 100.0f;
String username;
Context mContext;
private LocationRequest mLocationRequest;
private Location mBestReading;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
public SyncUserLocationService() {
super("SyncUserLocationService");
}
#Override
protected void onHandleIntent(Intent intent) {
mContext = this;
Log.v(TAG,"On Handle intent of SyncUserLocationService");
AppPreferences appPreferences = new AppPreferences(this);
username = appPreferences.getString(AppConstants.PREF_KEY_USERNAME, null);
if(username != null && username.length() != 0){
if (checkPlayServices()) {
Log.v(TAG,"Play service available");
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(POLLING_FREQ);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_FREQ);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
Log.e(TAG,"User recoverable error");
} else {
Log.e(TAG,"This device is not supported.");
}
return false;
}
return true;
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnected(Bundle connectionHint) {
// TODO Auto-generated method stub
if (checkPlayServices()) {
// Get best last location measurement meeting criteria
mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
if (null == mBestReading
|| mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
|| mBestReading.getTime() < System.currentTimeMillis()) {
Log.v(TAG,"INSIDE CONNECTED IF CONDITION");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
if (mBestReading.getAccuracy() < MAX_ACCURACY) {
sendGPSLocation();
}
// Schedule a runnable to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
#Override
public void run() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, SyncUserLocationService.this);
}
}, ONE_MIN, TimeUnit.MILLISECONDS);
}
}
}
#Override
public void onConnectionSuspended(int cause) {
}
private Location bestLastKnownLocation(float minAccuracy, long minTime) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;
// Get the best most recent location currently available
Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null) {
float accuracy = mCurrentLocation.getAccuracy();
long time = mCurrentLocation.getTime();
if (accuracy < bestAccuracy) {
bestResult = mCurrentLocation;
bestAccuracy = accuracy;
bestTime = time;
}
}
// Return best reading or null
if (bestAccuracy > minAccuracy || bestTime < minTime) {
return null;
}
else {
return bestResult;
}
}
public void sendGPSLocation(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
if (mBestReading != null) {
double latitude = mBestReading.getLatitude();
double longitude = mBestReading.getLongitude();
if(Connectivity.isConnected(SyncUserLocationService.this))
{
LocationPostObject locationPostObject = new LocationPostObject();
locationPostObject.setUser_id(username);
locationPostObject.setGeo_lat(latitude);
locationPostObject.setGeo_long(longitude);
locationPostObject.setGeo_accuracy((int)mBestReading.getAccuracy());
String response = null;
try {
final Gson gson = new Gson();
String jsonString = gson.toJson(locationPostObject);
Log.d(TAG, "Request " +jsonString.toString());
WSClient wsClient = new WSClient(mContext, true, true); //
response = wsClient.postTransactionDataSync(AppConstants.API_GPS_INSERT, jsonString);
Log.d(TAG, "response " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
LogsGPS logsGPS = new LogsGPS();
logsGPS.setGuid(CommonUtils.getUniqueID(SyncUserLocationService.this));
logsGPS.setUser_id(username);
logsGPS.setGeo_lat(latitude);
logsGPS.setGeo_long(longitude);
logsGPS.setGeo_accuracy((int)mBestReading.getAccuracy());
logsGPS.setTime_stamp(CommonUtils.getTimestamp());
logsGPS.setIssync(0);
LogsGPSDAO logsGPSDAO = new LogsGPSDAO(SyncUserLocationService.this);
long insert_result = logsGPSDAO.save(logsGPS);
Log.i(TAG,"saved location - " + insert_result);
}
} else {
Log.e(TAG,"(Couldn't get the location. Make sure location is enabled on the device)");
}
}
});
thread.start();
}
#Override
public void onLocationChanged(Location location) {
if (null == mBestReading || location.getAccuracy() <= mBestReading.getAccuracy()) {
mBestReading = location;
if (mBestReading.getAccuracy() < MAX_ACCURACY) {
sendGPSLocation();
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
}
I have implemented a background service to receive location updates:
public class TestActivity extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static String TAG = TestActivity_backup.class.getName();
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient=null;
#Override
public void onCreate() {
super.onCreate();
if (!isGooglePlayServicesAvailable()) {
stopSelf();
}
setContentView(R.layout.activity_test);
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10000).setFastestInterval(5000).setSmallestDisplacement(20);
this.buildGoogleApiClient();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.destination = intent.getStringExtra("DESTINATION");
LatLng latLng = intent.getParcelableExtra("LOCATION");
this.location = new Location("");
this.location.setLatitude(latLng.latitude);
this.location.setLongitude(latLng.longitude);
return START_NOT_STICKY;
}
#Override
public void onLocationChanged(Location location){
Toast.makeText(TestActivity.this, "User location changed", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnected(Bundle bundle) {
Toast.makeText(TestActivity.this, "Location service connected", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Location services suspended. Please reconnect.");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
//TODO
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
//GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
}
I have implemented all relevant methods.onCreate and onStartCommand are called but onConnec
ted and onLocationChanged are never ever called.If I implement an activity for location updates then its working fine.
What am I missing here?
Don't forget to add permission ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION depending upon Accuracy
And use this Code
public class LocationService extends Service {
private LocationListener locationListener;
#Override
public IBinder onBind(final Intent intent) {
return null;
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
super.onStartCommand(intent, flags, startId);
return Service.START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
this.locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, this.locationListener);
}
private static class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(final Location location) {
}
#Override
public void onProviderDisabled(final String provider) {
}
#Override
public void onProviderEnabled(final String provider) {
}
#Override
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
}
}
}
Here is my code that worked for me!
Don't forget to add mgoogleApiClient.connect() in onCreate()
and then take a look at the onConnected Method of googleapiClient - here I've created the the LocationRequest with
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, this);
and then for testing I used
LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
for the initial Request.
If you are using emulator don't forget to telnet localhost 5543 (to your emulator) and then use the command geo fix to set the initial location.
You can test it with geofixing to another location then the onLocationChanged Methode should be called ...
package com.pekam.androidservice;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.pekam.myandroidtheme.*;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.location.*;
import com.google.android.gms.location.LocationListener;
public class MyService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,LocationListener {
private NotificationManager nm;
private Timer timer = new Timer();
private int counter = 0;
private int incrementby = 1;
private static boolean isRunning = false;
private GoogleApiClient googleApiClient;
private LocationRequest mLocationRequest = new LocationRequest();
private String strLOG="LOG";
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients.
int mValue = 0; // Holds last value set by a client.
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_INT_VALUE = 3;
static final int MSG_SET_STRING_VALUE = 4;
static final int MSG_SET_STRING_LOG =5;
final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler.
// LocationRequest
#Override
public void onLocationChanged(Location location) {
Location mCurrentLocation = location;
sendLogMessageToUI("Last Known Loc" + mCurrentLocation.getLongitude() + mCurrentLocation.getLatitude());
}
//GoogleApiClient
#Override
public void onConnectionFailed(ConnectionResult bundle) {
}
#Override
public void onConnected(Bundle bundle) {
Log.i("onConnected", "GoogleApiClient" );
try {
Toast.makeText(this, "Location service connected", Toast.LENGTH_SHORT).show();
createLocationRequest();
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, mLocationRequest, this);
LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
} catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
Log.e("Google APi Connected", "Google APi Connected Failed.", t);
}
}
#Override
public void onConnectionSuspended(int i) {
}
//Service
#Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "Service Started.");
showNotification();
timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 1900L);
isRunning = true;
try {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
return START_STICKY; // run until explicitly stopped.
}
#Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
public static boolean isRunning()
{
return isRunning;
}
private void onTimerTick() {
Log.i("TimerTick", "Timer doing work." + counter);
try {
counter += incrementby;
sendMessageToUI(counter);
// LocationServices.FusedLocationApi.setMockMode(googleApiClient, true);
// double latitude = LocationServices.FusedLocationApi.getLastLocation(googleApiClient).getLatitude();
} catch (Throwable t) { //you should always ultimately catch all exceptions in timer tasks.
Log.e("TimerTick", "Timer Tick Failed.", t);
}
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
//GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
private void showNotification() {
nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TabBarActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
nm.notify(R.string.service_started, notification);
}
protected void createLocationRequest() {
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void sendMessageToUI(int intvaluetosend) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0));
//Send data as a String
Bundle b = new Bundle();
b.putString("str1", "ab" + intvaluetosend + "cd");
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
private void sendLogMessageToUI(String strLOG) {
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain());
//Send data as a String
Bundle b = new Bundle();
b.putString("strLOG", strLOG);
Message msg = Message.obtain(null, MSG_SET_STRING_LOG);
msg.setData(b);
mClients.get(i).send(msg);
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
class IncomingHandler extends Handler { // Handler of incoming messages from clients.
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_INT_VALUE:
incrementby = msg.arg1;
break;
default:
super.handleMessage(msg);
}
}
}
}
Hi Can anybody tell me how can i calculate Total Miles Travel from the Curent location to another location? e.g. like i start walking from point A and reached at point B. how can i find the total distance travel from point A to B. Please help me!!!
Criteria c=new Criteria()
c.setAccuracy(Criteria.ACCURACY_FINE);
String providerName=locMgr.getBestProvider(c,true);
Location startLocation = new Location(providerName);
startLocation.setLatitude(PrevLatitude);
startLocation.setLongitude(PrevLongitude);
startLocation.set(startLocation);
Location _myLoc = new Location(providerName);
_myLoc.setLatitude(Double.valueOf(nf.format(location.getLatitude())));
_myLoc.setLongitude(Double.valueOf(nf.format(location.getLongitude())));
_myLoc.set(_myLoc);
double meters = _myLoc.distanceTo(startLocation);
double miles = (meters*0.000621371192237334);
Assume, you have Location start_location and finish_location.
So you can use start_location.distanceTo(finish_location)
Please See , Location in Android
I have solved this exact problem in my open source Gps Tracker. The full working android project is here:
https://github.com/nickfox/GpsTracker/tree/master/phoneClients/android
and the class that does the tracking is below. You want to take a look at the variable called totalDistanceInMeters.
package com.websmithing.gpstracker;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
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;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class LocationService extends Service implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = "LocationService";
// use the websmithing defaultUploadWebsite for testing and then check your
// location with your browser here: https://www.websmithing.com/gpstracker/displaymap.php
private String defaultUploadWebsite;
private boolean currentlyProcessingLocation = false;
private LocationRequest locationRequest;
private LocationClient locationClient;
#Override
public void onCreate() {
super.onCreate();
defaultUploadWebsite = getString(R.string.default_upload_website);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// if we are currently trying to get a location and the alarm manager has called this again,
// no need to start processing a new location.
if (!currentlyProcessingLocation) {
currentlyProcessingLocation = true;
startTracking();
}
return START_NOT_STICKY;
}
private void startTracking() {
Log.d(TAG, "startTracking");
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
locationClient = new LocationClient(this,this,this);
if (!locationClient.isConnected() || !locationClient.isConnecting()) {
locationClient.connect();
}
} else {
Log.e(TAG, "unable to connect to google play services.");
}
}
protected void sendLocationDataToWebsite(Location location) {
// formatted for mysql datetime format
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getDefault());
Date date = new Date(location.getTime());
SharedPreferences sharedPreferences = this.getSharedPreferences("com.websmithing.gpstracker.prefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
float totalDistanceInMeters = sharedPreferences.getFloat("totalDistanceInMeters", 0f);
boolean firstTimeGettingPosition = sharedPreferences.getBoolean("firstTimeGettingPosition", true);
if (firstTimeGettingPosition) {
editor.putBoolean("firstTimeGettingPosition", false);
} else {
Location previousLocation = new Location("");
previousLocation.setLatitude(sharedPreferences.getFloat("previousLatitude", 0f));
previousLocation.setLongitude(sharedPreferences.getFloat("previousLongitude", 0f));
float distance = location.distanceTo(previousLocation);
totalDistanceInMeters += distance;
editor.putFloat("totalDistanceInMeters", totalDistanceInMeters);
}
editor.putFloat("previousLatitude", (float)location.getLatitude());
editor.putFloat("previousLongitude", (float)location.getLongitude());
editor.apply();
final RequestParams requestParams = new RequestParams();
requestParams.put("latitude", Double.toString(location.getLatitude()));
requestParams.put("longitude", Double.toString(location.getLongitude()));
Double speedInMilesPerHour = location.getSpeed()* 2.2369;
requestParams.put("speed", Integer.toString(speedInMilesPerHour.intValue()));
try {
requestParams.put("date", URLEncoder.encode(dateFormat.format(date), "UTF-8"));
} catch (UnsupportedEncodingException e) {}
requestParams.put("locationmethod", location.getProvider());
if (totalDistanceInMeters > 0) {
requestParams.put("distance", String.format("%.1f", totalDistanceInMeters / 1609)); // in miles,
} else {
requestParams.put("distance", "0.0"); // in miles
}
requestParams.put("username", sharedPreferences.getString("userName", ""));
requestParams.put("phonenumber", sharedPreferences.getString("appID", "")); // uuid
requestParams.put("sessionid", sharedPreferences.getString("sessionID", "")); // uuid
Double accuracyInFeet = location.getAccuracy()* 3.28;
requestParams.put("accuracy", Integer.toString(accuracyInFeet.intValue()));
Double altitudeInFeet = location.getAltitude() * 3.28;
requestParams.put("extrainfo", Integer.toString(altitudeInFeet.intValue()));
requestParams.put("eventtype", "android");
Float direction = location.getBearing();
requestParams.put("direction", Integer.toString(direction.intValue()));
final String uploadWebsite = sharedPreferences.getString("defaultUploadWebsite", defaultUploadWebsite);
LoopjHttpClient.get(uploadWebsite, requestParams, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] responseBody) {
LoopjHttpClient.debugLoopJ(TAG, "sendLocationDataToWebsite - success", uploadWebsite, requestParams, responseBody, headers, statusCode, null);
stopSelf();
}
#Override
public void onFailure(int statusCode, org.apache.http.Header[] headers, byte[] errorResponse, Throwable e) {
LoopjHttpClient.debugLoopJ(TAG, "sendLocationDataToWebsite - failure", uploadWebsite, requestParams, errorResponse, headers, statusCode, e);
stopSelf();
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e(TAG, "position: " + location.getLatitude() + ", " + location.getLongitude() + " accuracy: " + location.getAccuracy());
// we have our desired accuracy of 500 meters so lets quit this service,
// onDestroy will be called and stop our location uodates
if (location.getAccuracy() < 500.0f) {
stopLocationUpdates();
sendLocationDataToWebsite(location);
}
}
}
private void stopLocationUpdates() {
if (locationClient != null && locationClient.isConnected()) {
locationClient.removeLocationUpdates(this);
locationClient.disconnect();
}
}
/**
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000); // milliseconds
locationRequest.setFastestInterval(1000); // the fastest rate in milliseconds at which your app can handle location updates
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationClient.requestLocationUpdates(locationRequest, this);
}
/**
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
Log.e(TAG, "onDisconnected");
stopLocationUpdates();
stopSelf();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed");
stopLocationUpdates();
stopSelf();
}
}