使用GoogleApiClient挂起应用

时间:2017-08-21 10:34:34

标签: android android-fragments memory-management google-api-client android-googleapiclient

在我的应用程序中,我有4到5个片段,所有片段都需要GoogleApiCLient对象来获取当前位置并执行其他相关操作。

所以,我只是使用GoogleApiClient,如下所示:

首先我实施

implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener

声明

private GoogleApiClient mGoogleApiClient;

在片段的onCreate()

 if (!Constant.checkPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)) {
                Constant.requestPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, 101);
            } else {
                if (Constant.isOnline(mContext)) {
                    buildGoogleApiClient();
                    locationUpdate();
                } else {
                    Constant.displayToast(mContext, getResources().getString(R.string.msg_internet));
                }
            }

如下所示

private synchronized void buildGoogleApiClient() {
    if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
        mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addApi(LocationServices.API)
                .addApi(Places.GEO_DATA_API)
                .addApi(Places.PLACE_DETECTION_API)
                .enableAutoManage(getActivity(), MapFragment.this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }
}

onConnected 方法:

@Override
public void onConnected(@Nullable Bundle bundle) {
    try {
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

getLocation()方法:

  private void getLocation() {
    try {
        if (ActivityCompat.checkSelfPermission((Activity) mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission((Activity) mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        } else {
            mLocationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);
            // getting GPS status
            boolean isGPSEnabled = mLocationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);
            // getting network status
            boolean isNetworkEnabled = mLocationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                if (Prefrences.checkPref(mContext, ZIPCODE)) {
                    getLatLongFromZipCode();
                } else {
                    if (isNetworkEnabled) {
                        if (!Prefrences.checkPref(mContext, NEAR_ME_SEARCH)) {
                            mLocationManager.requestLocationUpdates(
                                    LocationManager.NETWORK_PROVIDER,
                                    0,
                                    0, this);
                            if (mLocationManager != null) {
                                mLocation = mLocationManager
                                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                                if (mLocation != null) {
                                    mCurrentLatitude = mLocation.getLatitude();
                                    mCurrentLongitude = mLocation.getLongitude();
                                } else if (mLastLocation != null) {
                                    mCurrentLatitude = mLastLocation.getLatitude();
                                    mCurrentLongitude = mLastLocation.getLongitude();
                                } else {
                                    Constant.displayToast(mContext, "Location not fetched. Try again.");
                                }
                            }
                        }
                    } else if (isGPSEnabled) {
                        if (!Prefrences.checkPref(mContext, NEAR_ME_SEARCH)) {
                            if (mLocation == null) {
                                mLocationManager.requestLocationUpdates(
                                        LocationManager.GPS_PROVIDER,
                                        0,
                                        0, this);
                                if (mLocationManager != null) {
                                    mLocation = mLocationManager
                                            .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                                    if (mLocation != null) {
                                        mCurrentLatitude = mLocation.getLatitude();
                                        mCurrentLongitude = mLocation.getLongitude();
                                    } else if (mLastLocation != null) {
                                        mCurrentLatitude = mLastLocation.getLatitude();
                                        mCurrentLongitude = mLastLocation.getLongitude();
                                    } else {
                                        Constant.displayToast(mContext, "Location not fetched. Try again.");
                                    }
                                }
                            }
                        }
                    }
                    loadServiceData();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

locationUpdate()方法,其中getLocation()方法正在调用:

private void locationUpdate() {
    try {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(5 * 1000);
        mLocationRequest.setFastestInterval(1 * 1000);
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);
        // **************************
        builder.setAlwaysShow(true); // this is the key ingredient
        // **************************
        if (mGoogleApiClient != null) {
            PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi
                    .checkLocationSettings(mGoogleApiClient, builder.build());
            result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
                @Override
                public void onResult(LocationSettingsResult result) {
                    final Status status = result.getStatus();
                    final LocationSettingsStates state = result
                            .getLocationSettingsStates();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            // All location settings are satisfied. The client can
                            // initialize location
                            // requests here.
                            try {
                                if (Constant.isOnline(mContext)) {
                                    getLocation();
                                } else
                                    Constant.displayToast(mContext, mContext.getResources().getString(R.string.msg_internet));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            // Location settings are not satisfied. But could be
                            // fixed by showing the user
                            // a dialog.
                            try {
                                status.startResolutionForResult((Activity) mContext, LOCATION_GET_CODE);
                            } catch (IntentSender.SendIntentException e) {
                                e.printStackTrace();
                            }

                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            // Location settings are not satisfied. However, we have
                            // no way to fix the
                            // settings so we won't show the dialog.
                            Constant.displayToast(mContext, "Location change issue.");
                            break;
                    }
                }
            });
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

onActivityResult()也如下所示:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == LOCATION_GET_CODE) {
        switch (resultCode) {
            case Activity.RESULT_OK:
                try {
                    getLocation();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                break;

            case Activity.RESULT_CANCELED:
                // The user was asked to change settings, but chose not to
                Toast.makeText(mContext, "Please, turn on GPS and try again", Toast.LENGTH_LONG).show();
                break;

            default:
                break;

        }
    }
    Runtime.getRuntime().gc();
}

onStop()方法:

@Override
public void onStop() {
    try {
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            mGoogleApiClient.stopAutoManage(getActivity());
            mGoogleApiClient.disconnect();
        }
        super.onStop();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

onStart()方法:

 @Override
public void onStart() {
    try {
        super.onStart();
        if (mGoogleApiClient != null) {
            mGoogleApiClient.connect();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

onDestroy()方法:

@Override
public void onDestroy() {
    try {
        super.onDestroy();

        if (mGoogleApiClient != null) {
            mGoogleApiClient.stopAutoManage(getActivity());
            mGoogleApiClient.disconnect();
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

现在,问题是当我从一个片段导航到另一个片段时,我的应用程序卡住或挂起2到3秒。

可能是什么问题? 感谢。

1 个答案:

答案 0 :(得分:0)

这种情况正在发生因为在每个片段中你一次又一次地做同样的事情。您正在onStart()中连接并在onStop()中断开连接。第二个片段的onStart()在第一个片段的onStop()之前调用。

不是在每个片段中使用 GoogleApiClient ,而是将其移至单个班级,并与活动进行连接和断开连接。

我已经为我自己的目的实现了LocationUpdater。看看代码,如果你觉得它很好就可以使用它。

<强> LocationFinder.class

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.maps.model.LatLng;

/**
 * Created by Bhuvanesh on 8/21/2017.
 */

@SuppressWarnings("MissingPermission")
public class LocationFinder implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    public static final String TAG = "LocationFinder";
    private static final String BROADCAST_GPS_REQ = "LocationFinder.GPS_REQ";
    private static final String KEY_GPS_REQ = "key.gps.req";
    private static final int GPS_REQUEST = 2301;
    private FragmentActivity activity;
    private FinderType finderType;
    private GoogleApiClient googleApiClient;
    private LocationRequest locationRequest;
    private long updateInterval;
    private long fastestInterval;
    private GpsRequestListener gpsRequestListener;
    private LocationUpdateListener locationUpdateListener;

public LocationFinder(FragmentActivity activity, FinderType finderType) {
    this.activity = activity;
    this.finderType = finderType;
}

private void connectGoogleApiClient() {
    googleApiClient = new GoogleApiClient.Builder(activity)
            .addApi(LocationServices.API).addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this).build();
    googleApiClient.connect();
}

private void createLocationRequest() {
    locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(updateInterval);
    locationRequest.setFastestInterval(fastestInterval);
}

private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        int intExtra = intent.getIntExtra(KEY_GPS_REQ, 0);
        switch (intExtra) {
            case Activity.RESULT_OK:
                LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, LocationFinder.this);
                gpsRequestListener.gpsTurnedOn();
                break;
            case Activity.RESULT_CANCELED:
                gpsRequestListener.gpsNotTurnedOn();
        }
    }
};

public void gpsRequestCallback(GpsRequestListener gpsRequestListener) {
    this.gpsRequestListener = gpsRequestListener;
    LocalBroadcastManager.getInstance(activity).registerReceiver(receiver, new IntentFilter(BROADCAST_GPS_REQ));
}

public void find(LocationUpdateListener listener) {
    this.locationUpdateListener = listener;
    createLocationRequest();
    connectGoogleApiClient();
}

private void find() {
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest);
    builder.setAlwaysShow(true);

    PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
            Status status = locationSettingsResult.getStatus();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, LocationFinder.this);
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        status.startResolutionForResult(activity, GPS_REQUEST);
                    } catch (IntentSender.SendIntentException e) {
                        e.printStackTrace();
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    Log.d(TAG, "No GPS Hardware");
                    break;
            }
        }
    });
}

public void stopFinder() {
    LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
    activity.unregisterReceiver(receiver);
    googleApiClient.disconnect();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    Log.d(TAG, "GoogleApiClient: Connected");
    find();
}

@Override
public void onConnectionSuspended(int i) {
    Log.d(TAG, "GoogleApiClient: onConnectionSuspended")
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.d(TAG, "GoogleApiClient: onConnectionFailed")
}

@Override
public void onLocationChanged(Location location) {
    if (finderType != FinderType.TRACK)
        stopFinder();
    locationUpdateListener.onLocationUpdate(new LatLng(location.getLatitude(), location.getLongitude()));
}

public void setGpsRequestListener(GpsRequestListener gpsRequestListener) {
    this.gpsRequestListener = gpsRequestListener;
}

public static void onRequestResult(Activity activity, int requestCode, int resultCode) {
    if (requestCode == GPS_REQUEST) {
        Intent intent = new Intent(BROADCAST_GPS_REQ);
        intent.putExtra(KEY_GPS_REQ, resultCode);
        LocalBroadcastManager.getInstance(activity).sendBroadcast(intent);
    }
}

public enum FinderType {
    // It will update the current GPS location once.
    GPS,
    //It will update the user location continuously.
    TRACK
}

interface LocationUpdateListener {
    void onLocationUpdate(LatLng latLng);
}

interface GpsRequestListener {
    void gpsTurnedOn();

    void gpsNotTurnedOn();
}
}

活动

LocationFinder finder = new LocationFinder((FragmentActivity) getActivity(), LocationFinder.FinderType.TRACK);
finder.config(5000, 5000);
finder.find(this);

您应该在片段中实现LocationFinder.LocationUpdateListener。您将在回调方法中获得位置更新。

void onLocationUpdate(LatLng latLng);

如果你想要打开Gps 并在完成这个过程之后得到一个回调。

finder.gpsRequestCallback(new GpsRequestListener() {
            @Override
            public void gpsTurnedOn() {

            }

            @Override
            public void gpsNotTurnedOn() {

            }
        });

在您的活动 onActivityResult()应该是这样的。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        LocationFinder.onRequestResult(this, requestCode, resultCode);
    }

注意:在使用此功能之前,您必须获得位置权限