【问题标题】:FusedLocationProviderClient when and how to stop Looper?FusedLocationProviderClient 何时以及如何停止 Looper?
【发布时间】:2018-03-15 02:14:12
【问题描述】:

我曾经使用 FusedLocationApi,直到我得知它已被弃用(请参阅下面的参考资料)。实施起来很简单。正如文档所说,您需要将它与 GoogleApiClient 结合使用

LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,
                        locationRequest, this);

我最近更改为 FusedLocationProviderClient(请参阅下面的参考资料)按照教程,我能够成功地让 FusedLocationProviderClient 工作

教程:https://github.com/codepath/android_guides/wiki/Retrieving-Location-with-LocationServices-API

// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
      @Override
      public void onLocationResult(LocationResult locationResult) {
         // do work here
         onLocationChanged(locationResult.getLastLocation();
      }
    },
    Looper.myLooper());

我遇到的问题是 Looper 线程。即使应用程序在后台,Looper 线程也会继续运行。我想在应用程序处于后台时暂停位置更新,然后在应用程序处于前台时恢复位置更新。我怎样才能做到这一点?

参考资料:

  1. https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi
  2. https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient

【问题讨论】:

    标签: android multithreading geolocation android-looper


    【解决方案1】:

    您只需要在您的活动的onPause() 中调用mFusedLocationClient.removeLocationUpdates(mLocationCallback)。然而,它的意义远不止这些。

    在您的主要活动中使用 FusedLocationProviderClient 和 LocationRequest 的成员变量:

    import com.google.android.gms.location.FusedLocationProviderClient;
    import com.google.android.gms.location.LocationCallback;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationResult;
    
    public class MainActivity extends AppCompatActivity
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener {
    
        FusedLocationProviderClient mFusedLocationClient;
        LocationRequest mLocationRequest;
    
        //..........
    

    也为 LocationCallback 使用成员变量:

    LocationCallback mLocationCallback = new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {
            for (Location location : locationResult.getLocations()) {
                Log.i("MainActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
    
            }
        };
    
    };
    

    然后,在onCreate() 中分配mFusedLocationClient

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        requestLocationUpdates();
    
        //...............
    }
    

    那么在onResume()中,如果设置了FusedLocationProviderClient,则使用它。

    @Override
    public void onResume() {
        if (mFusedLocationClient != null) {
            requestLocationUpdates();
        }
    }
    
    public void requestLocationUpdates() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(120000); // two minute interval
        mLocationRequest.setFastestInterval(120000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        }
    }
    

    最后,在onPause() 中,致电removeLocationUpdates()

    @Override
    public void onPause() {
        super.onPause();
        if (mFusedLocationClient != null) {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
        }
    }
    

    【讨论】:

    【解决方案2】:

    获取位置后,只需删除他在上述答案中提到的mFusedLocationClient.removeLocationUpdates

    if (mFusedLocationClient != null) 
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
    

    Looper 将被称为requestLocationUpdates,直到您将其删除。

    在我的问题中,我按照上面提到的那样做了。下面是我的代码。

      mFusedLocationClient.getLastLocation()
                        .addOnSuccessListener(new OnSuccessListener<Location>() {
                            @Override
                            public void onSuccess(Location location) {
                                // GPS location can be null if GPS is switched off
                                if (location != null) {
    
                                    mLocation = location;
    
                                    if (mFusedLocationClient != null) {
                                        mFusedLocationClient.removeLocationUpdates(mLocationCallback);
                                    }
                              } else {
                                    startLocationUpdates();
                               }
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(HomeActivity.this, "Error trying to get last GPS location", Toast.LENGTH_SHORT).show();
                                e.printStackTrace();
                            }
                        });
    

    下面是我的requestLocationUpdates,所以在位置可用之前我会收到请求。

    private void startLocationUpdates() {
            mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
                    .addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
                        @Override
                        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                            Log.i(TAG, "All location settings are satisfied.");
    
                            getPackageManager().checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, getPackageName());
                            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                                    mLocationCallback, Looper.myLooper());
                            getLastLocationNewMethod();
                        }
                    })
                    .addOnFailureListener(this, new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            int statusCode = ((ApiException) e).getStatusCode();
                            switch (statusCode) {
                                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                    Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade " +
                                            "location settings ");
                                    try {
                                        ResolvableApiException rae = (ResolvableApiException) e;
                                        rae.startResolutionForResult(HomeActivity.this, 0x1);
                                    } catch (IntentSender.SendIntentException sie) {
                                        Log.i(TAG, "PendingIntent unable to execute request.");
                                    }
                                    break;
                                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                    String errorMessage = "Location settings are inadequate, and cannot be " +
                                            "fixed here. Fix in Settings.";
                                    Log.e(TAG, errorMessage);
                                    Toast.makeText(HomeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
                                    //  mRequestingLocationUpdates = false;
                            }
                            getLastLocationNewMethod();  // this method is where I can get location. It is calling above method. 
                        }
                    });
        }
    

    注意:这里是 GitHub Repo 的更多信息 LINK

    【讨论】:

    • 我们可以从前台服务调用 LocationSettingRequest 吗?因为我正在从前台服务请求位置更新
    • 据我了解,LocationSettingRequest 检查仅在请求位置更新之前完成一次??在开始请求位置更新后,如果用户禁用 gps 一段时间后,LocationSettinsRequest onFailureCallback() 会再次被调用吗?我认为这是在请求位置更新之前一次回调以检查 gps 是否打开。如果用户在一段时间后关闭 gps,我们能做什么?也许我们应该定期检查gps是否打开。
    • 只需对 LocationSettingRequest 使用服务。所以它会在你关闭 GPS 时检查。
    • 我们不能从服务中使用 LocationSettingsRequest 来提示用户对话框,因为这一行需要活动上下文 "rae.startResolutionForResult(HomeActivity.this, 0x1);"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多