我的所有 FusedLocation 请求的列表

Posted

技术标签:

【中文标题】我的所有 FusedLocation 请求的列表【英文标题】:List of all my FusedLocation requests 【发布时间】:2017-12-05 15:58:14 【问题描述】:

我正在使用下面的代码在一项活动中注册位置更新,但我如何检查我的应用程序之前是否已注册此请求(或查询我的活动位置请求)并且仍在等待对于位置响应,所以我不会提出重复请求?我可以关闭我的应用并再次运行它而不停止此请求:

this.locationRequest = new LocationRequest();
this.locationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
this.locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
this.locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(this.locationRequest);
this.locationSettingsRequest = builder.build();

this.locationCallback = new LocationCallback() 
    @Override
    public void onLocationResult(LocationResult locationResult) 
        super.onLocationResult(locationResult); // why? this. is. crazy. android.
        Location currentLocation = locationResult.getLastLocation();

        GPSPoint gpsPoint = new GPSPoint(currentLocation.getLatitude(),
                                         currentLocation.getLongitude());
        Log.i(TAG, "Location Callback results: " + gpsPoint);
        if (null != workable)
            workable.work(gpsPoint);
    
;

this.mFusedLocationClient =
        LocationServices.getFusedLocationProviderClient(MainApplication.getAppContext());
this.mFusedLocationClient.requestLocationUpdates(this.locationRequest,
                this.locationCallback, Looper.myLooper());

【问题讨论】:

【参考方案1】:

但是如何检查我的应用之前是否已注册此请求(或查询我的活动位置请求)并且仍在等待位置响应,因此我不会发出重复请求?

根据 [FusedLocationProvider API](https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener, android.os.Looper)) 的文档,

public abstract PendingResult<Status> requestLocationUpdates (GoogleApiClient client, LocationRequest request, LocationListener listener, Looper looper)

上面的代码可以:

为调用返回一个 PendingResult,检查isSuccess() 以确定是否 成功了。

也许你可以尝试isSuccess() 来检查请求是否已经注册并应用验证,如果它抛出true 那么它应该已经停止发出另一个请求。

【讨论】:

【参考方案2】:
public class BackgroundLocationService extends Service implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    GpsStatus.Listener,
    LocationListener 

// Constants here....

private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private LocationManager locationManager;
// Flag that indicates if a request is underway.
private boolean mInProgress;

private NotificationManagement myNotificationManager;
private Boolean servicesAvailable = false;

//And other variables here...

@Override
public void onCreate()

    super.onCreate();

    myNotificationManager = new NotificationManagement(getApplicationContext());
    myNotificationManager.displayMainNotification();

    mInProgress = false;
    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create();
    // Use high accuracy
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    // Set the update interval
    mLocationRequest.setInterval(PREFERRED_INTERVAL);
    // Set the fastest update interval
    mLocationRequest.setFastestInterval(FASTEST_INTERVAL);

    servicesAvailable = servicesConnected();

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationManager.addGpsStatusListener(this);

    setUpLocationClientIfNeeded();


/**
 * Create a new location client, using the enclosing class to
 * handle callbacks.
 */
protected synchronized void buildGoogleApiClient()

    this.mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();


private boolean servicesConnected()


    // Check that Google Play services is available
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

    // If Google Play services is available
    if (ConnectionResult.SUCCESS == resultCode)
    
        return true;
    
    else
    
        return false;
    


public int onStartCommand(Intent intent, int flags, int startId)

    super.onStartCommand(intent, flags, startId);

    if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
        return START_STICKY;

    setUpLocationClientIfNeeded();
    if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress)
    
        mInProgress = true;
        mGoogleApiClient.connect();
    
    return START_STICKY;



private void setUpLocationClientIfNeeded()

    if (mGoogleApiClient == null)
        buildGoogleApiClient();


public void onGpsStatusChanged(int event)




// Define the callback method that receives location updates
@Override
public void onLocationChanged(Location location)

    simpleGPSFilter(location);


// Other fancy and needed stuff here...

/**
 * "Stupid" filter that utilizes experience data to filter out location noise.
 * @param location Location object carrying all the needed information
 */
private void simpleGPSFilter(Location location)

    //Loading all the required variables
    int signalPower = 0;
    satellites = 0;
    // Getting the satellites
    mGpsStatus = locationManager.getGpsStatus(mGpsStatus);
    Iterable<GpsSatellite> sats = mGpsStatus.getSatellites();
    if (sats != null)
    
        for (GpsSatellite sat : sats)
        
            if (sat.usedInFix())
            
                satellites++;
                signalPower += sat.getSnr();
            
        
    
    if (satellites != 0)
        signalPower = signalPower/satellites;
    mySpeed = (location.getSpeed() * 3600) / 1000;
    myAccuracy = location.getAccuracy();
    myBearing = location.getBearing();
    latitude = location.getLatitude();
    longitude = location.getLongitude();
    Log.i("START OF CYCLE", "START OF CYCLE");
    Log.i("Sat Strength", Integer.toString(signalPower));
    Log.i("Locked Sats", Integer.toString(satellites));

    // Do the math for the coordinates distance
    /*
     * Earth's radius at given Latitude.
     * Formula: Radius = sqrt( ((equatorR^2 * cos(latitude))^2 + (poleR^2 * sin(latitude))^2 ) / ((equatorR * cos(latitude))^2 + (poleR * sin(latitude))^2)
     * IMPORTANT: Math lib uses radians for the trigonometry equations so do not forget to use toRadians()
     */
    Log.i("Lat for Radius", Double.toString(latitude));
    double earthRadius = Math.sqrt((Math.pow((EARTH_RADIUS_EQUATOR * EARTH_RADIUS_EQUATOR * Math.cos(Math.toRadians(latitude))), 2)
            + Math.pow((EARTH_RADIUS_POLES * EARTH_RADIUS_POLES * Math.cos(Math.toRadians(latitude))), 2))
            / (Math.pow((EARTH_RADIUS_EQUATOR * Math.cos(Math.toRadians(latitude))), 2)
            + Math.pow((EARTH_RADIUS_POLES * Math.cos(Math.toRadians(latitude))), 2)));
    Log.i("Earth Radius", Double.toString(earthRadius));

    /*
     * Calculating distance between 2 points on map using the Haversine formula (arctangent writing) with the following algorithm
     * latDifference = latitude - lastLatitude;
     * lngDifference = longitude - lastLongitude;
     * a = (sin(latDifference/2))^2 + cos(lastLatitude) * cos(latitude) * (sin(lngDifference/2))^2
     * c = 2 * atan2( sqrt(a), sqrt(1-a) )
     * distance = earthRadius * c
     */
    double latDifference = latitude - lastLatitude;
    double lngDifference = longitude - lastLongitude;
    double a = Math.pow((Math.sin(Math.toRadians(latDifference / 2))), 2) + (Math.cos(Math.toRadians(lastLatitude))
            * Math.cos(Math.toRadians(latitude))
            * Math.pow((Math.sin(Math.toRadians(lngDifference / 2))), 2));
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double distance = earthRadius * c;
    Log.i("New point distance", Double.toString(distance));

    // Filter logic
    // Make an initial location log
    if ((!isInit) && (myAccuracy < ACCEPTED_ACCURACY))
    
        isInit = true;
        lastLatitude = latitude;
        lastLongitude = longitude;
        logLocations(location);
    
    else
    
        // Satellite lock (use of GPS) on the higher level
        if (satellites == 0)
        
            // Accuracy filtering at the second level
            if (myAccuracy < ACCEPTED_ACCURACY)
            
                if ((distance > ACCEPTED_DISTANCE))
                
                    lastLatitude = latitude;
                    lastLongitude = longitude;
                    logLocations(location);
                    Log.i("Location Logged", "No Sats");
                    /*
                    // Calculate speed in correlation to perceived movement
                    double speed = distance / (PREFERRED_INTERVAL / 1000);  // TODO: Need to make actual time dynamic as the fused location does not have fixed timing
                    if (speed < ACCEPTED_SPEED)
                    
                        lastLatitude = latitude;
                        lastLongitude = longitude;
                        logLocations(location);
                     */
                
            
        
        else if ((satellites < 4) && (signalPower > ACCEPTED_SIGNAL))
        
            if (myAccuracy < (ACCEPTED_ACCURACY + 50))
            
                logLocations(location);
                Log.i("Location Logged", "With Sats");
            
        
        else
        
            if (myAccuracy < (ACCEPTED_ACCURACY + 100))
            
                lastSpeed = mySpeed;
                lastBearing = myBearing;
                lastLatitude = latitude;
                lastLongitude = longitude;
                logLocations(location);
                Log.i("Location Logged", "With Good Sats");
            
        
    
    Log.i("END OF CYCLE", "END OF CYCLE");


private void logLocations(Location location)

    String myprovider = "false";

    String temp = timestampFormat.format(location.getTime());
    mysqliteHelper dbHelper = new MySQLiteHelper(getApplicationContext());

    try
    
        dbHelper.createEntry(latitude, longitude, allschemes, temp, mySpeed, myAccuracy, myBearing, myprovider, satellites);
    
    catch (Exception e)
    
        e.printStackTrace();
    

    CheckAutoArrive(String.valueOf(latitude), String.valueOf(longitude));


这可能以基本方式起作用,但如果您需要对这些内容进行详细说明,请访问我即将发布的有关 JAVA 中的融合位置的视频中的 YouTube 频道 Techzology。

【讨论】:

发布 250 多行代码而没有任何解释并不完全是 Stack Overflow 对答案的定义。

以上是关于我的所有 FusedLocation 请求的列表的主要内容,如果未能解决你的问题,请参考以下文章

FusedLocation 不会触发 android api <= 21 的 locationcallback

fusedLocation API 间隔与关闭 GPS 无线电有何关系

FusedLocation GoogleApi - 侦听器不得为空 (Xamarin.Android)

使用 API 获取系统中所有服务请求的列表

FusedLocation Pending Intent 有时在没有位置的情况下调用

方案循环不会遍历列表中的所有元素