2

我正在使用 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);
            }
        }
    }

}
4

0 回答 0