我正在使用Google Play API获取设备位置,并通过IntentService定期将其发送到服务器(每10分钟或根据位置发生变化)。
我在构建LocationRequest.PRIORITY_HIGH_ACCURACY
时使用LocationRequest
,设备GPS也已开启。
api有时会以高精度(< = 100)返回该位置,但其他时间几乎(> 1000)。
如何获得定位精度?
我的来源:
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);
}
}
}
}