我有这个应用程序,我需要在开始显示任何内容之前尽快获得一个粗略位置(我只请求android.permission.ACCESS_COARSE_LOCATION
)(除了启动屏幕)给用户。
由于某些原因,我的代码在某些需要请求位置更新的用例中无效(如果它无法找到最后知道的位置)。
老实说,我很难描述通常需要花费大量时间来修复位置的用例。我已经尝试了很多东西,在前台/后台打开/关闭应用程序时不断禁用/启用位置服务。很多事情,它只是不能持续发挥作用。
鉴于我的应用程序的性质,我真的需要尽快获得一个位置修复。由于我不需要一个精确的位置(一个非常粗略的估计是好的),我不明白为什么需要这么长的时间......
很抱歉这篇长篇文章,这是我目前的代码:
// BaseActivityLifecycleCallbacks extends Application.ActivityLifecycleCallbacks with default blank methods
public class MyLocation extends BaseActivityLifecycleCallbacks implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final int LOCATION_REQUEST_INTERVAL = 1000; // 1 second
private static final int LOCATION_REQUEST_FASTEST_INTERVAL = 250; // 250 milliseconds
private static final int LOCATION_REQUEST_UPDATE_TIMEOUT = 15000; // 15 seconds
private final Handler mMainHandler;
private final Runnable mExpiredRunnable;
private final GoogleApiClient mGoogleApiClient;
private final LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
@DebugLog
public MyLocation(Context context) {
mMainHandler = new Handler(Looper.getMainLooper());
mExpiredRunnable = new Runnable() {
@DebugLog
@Override
public void run() {
handleNewOrEmptyLocation(null);
}
};
MyApplication.getInstance().registerActivityLifecycleCallbacks(this);
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setInterval(LOCATION_REQUEST_INTERVAL)
.setFastestInterval(LOCATION_REQUEST_FASTEST_INTERVAL);
}
public void requestFusedLocation(@NonNull LocationCallback callback) {
mLocationCallback = callback;
mGoogleApiClient.connect();
}
@DebugLog
@Override
public void onActivityResumed(Activity activity) {
super.onActivityResumed(activity);
if (activity instanceof MainActivity) {
if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting() && mLocationCallback != null) {
mGoogleApiClient.connect();
}
}
}
@DebugLog
@Override
public void onActivityPaused(Activity activity) {
super.onActivityPaused(activity);
if (activity instanceof MainActivity) {
if (mGoogleApiClient.isConnected()) {
mMainHandler.removeCallbacks(mExpiredRunnable);
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
}
@DebugLog
@Override
// I'm handling permission request some place else...
@SuppressWarnings("MissingPermission")
public void onConnected(@Nullable Bundle bundle) {
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (lastLocation != null) {
handleNewOrEmptyLocation(lastLocation);
return;
}
// I've disabled this for testing purposes. Sometimes the current 15s timeout is not enough to get a location fix...
//mMainHandler.postDelayed(mExpiredRunnable, LOCATION_REQUEST_UPDATE_TIMEOUT);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@DebugLog
@Override
public void onLocationChanged(Location location) {
mMainHandler.removeCallbacks(mExpiredRunnable);
handleNewOrEmptyLocation(location);
}
@DebugLog
@Override
public void onConnectionSuspended(int i) {
// TODO: Is there something that needs to be done here?
Timber.e("onConnectionSuspended");
}
@DebugLog
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
// TODO: Is there something that needs to be done here?
Timber.e("onConnectionFailed");
}
@DebugLog
private void handleNewOrEmptyLocation(Location location) {
MyApplication.getInstance().unregisterActivityLifecycleCallbacks(this);
mGoogleApiClient.disconnect();
if (location != null) {
mLocationCallback.onLocationReceived(location);
} else {
mLocationCallback.onEmptyLocation();
}
}
public interface LocationCallback {
void onLocationReceived(Location location);
void onEmptyLocation();
}
}
这就是它目前的使用方式:
public class MAinActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyLocation myLocation = new MyLocation(this);
myLocation.requestFusedLocation(new MyLocation.LocationCallback() {
@DebugLog
@Override
public void onLocationReceived(Location location) {
Toast.makeText(MainActivity.this, String.valueOf(location), Toast.LENGTH_SHORT).show();
}
@DebugLog
@Override
public void onEmptyLocation() {
Toast.makeText(MainActivity.this, "HUSTON, WE HAVE A PROBLEM!", Toast.LENGTH_SHORT).show();
finish();
}
});
}
}
完成并作为奖励问题...... onConnectionSuspended
和onConnectionFailed
在什么情况下被召唤?我应该以某种方式处理这些回调吗?