首页 > 解决方案 > 使用融合位置提供程序获取用户当前位置

问题描述

我正在使用 google play service location api(融合位置提供程序)来获取用户当前位置。在某些情况下,返回结果需要太多时间,有时返回同一设备的结果需要的时间要少得多。在这两种情况下,用户都在室内。我无法理解这是这种情况背后的原因。

public class SelfAttendanceFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
    OnMapReadyCallback, GoogleMap.OnMapClickListener {


protected static final int REQUEST_CHECK_SETTINGS = 0x1;
private static final int MY_PERMISSIONS_REQUEST = 1;
private static Double LATITUDE_DHAKA;
private static Double LONGITUDE_DHAKA;

LoadingDialog mLoadingDialog;
double latitude = 0;
double longitude = 0;
Handler mHandler;
CountDownTimer countDownTimer;
FusedLocationProviderClient mFusedLocationClient;
GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
LocationCallback mLocationCallback;
LocationManager locationManager;
SupportMapFragment mapFragment;
Location location;
private GoogleMap mMap;
private String address;
private String remarks = "";

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View view = inflater.inflate(R.layout.fragment_self_attendance, container, false);
    ButterKnife.bind(this, view);
    return view;

}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    /*if (!checkPermissionGranted()) {
        askForPermission();
    }*/

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED

                && getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED ) {

            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION},
                    MY_PERMISSIONS_REQUEST);
        } else {
               startAction();
        }
    } else {
        startAction();
    }


}

private void startAction(){
    mLoadingDialog = new LoadingDialog(getContext(), getString(R.string.fetching_location));

    mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext());
    locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);

    doCheckPermissionForGps();

    mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);
            List<Location> locationList = locationResult.getLocations();
            for (Location loc : locationList) {
                if (loc.getLatitude() != 0 && loc.getLongitude() != 0) {
                    location = loc;
                    checkLocationandAddToMap();
                     break;
                }
            }

        }
    };
}


private void doCheckPermissionForGps() {

    Boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

    if (isGpsEnabled && mGoogleApiClient != null) {
        requestLocationUpdates();
    } else if (mGoogleApiClient == null) {
        buildGoogleApiClient();
    } else if (!isGpsEnabled) {
        displayLocationSettingsRequest(getContext());
    }

}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(getContext())
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    mGoogleApiClient.connect();

    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(10);
    mLocationRequest.setFastestInterval(10 / 2);
}

private String getAddressByLattitudeAndLongitude() {
    String address;
    try {
        Geocoder geocoder;
        List<Address> addresses;
        geocoder = new Geocoder(getContext(), Locale.getDefault());

        addresses = geocoder.getFromLocation(latitude, longitude, 5); // Here 1 represent max location result to returned, by documents it recommended 1 to 5

        address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
        if (address.isEmpty()) {
            address = addresses.get(0).getLocality();
        }
    } catch (Exception ex) {
        address = "";
    }
    return address;
}

private void displayLocationSettingsRequest(Context context) {
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
    builder.setAlwaysShow(true);

    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();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        status.startResolutionForResult(getActivity(), REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    break;
            }
        }
    });

}



 @SuppressLint("MissingPermission")
private void requestLocationUpdates() {
    if(isAdded() && getActivity() != null){
        mLoadingDialog.showDialogWithText("Fetching location using GPS...");
    }

    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode,resultCode,data);
    switch (resultCode) {
        case -1:
            requestLocationUpdates();

            break;
        case 0:
            displayLocationSettingsRequest(getContext());
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }


}

@Override
public void onConnected(@Nullable Bundle bundle) {
    if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        displayLocationSettingsRequest(getContext());
    } else {
        requestLocationUpdates();
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

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

@SuppressLint("MissingPermission")
@Override
public void onMapReady(GoogleMap googleMap) {

    try{
        mMap = googleMap;
        mMap.clear();

        LATITUDE_DHAKA = 23.777176;
        LONGITUDE_DHAKA = 90.399452;
        try {

            boolean success = mMap.setMapStyle(
                    MapStyleOptions.loadRawResourceStyle(
                            getContext(), R.raw.style_map));


        } catch (Resources.NotFoundException e) {
            e.printStackTrace();
        }

        CameraPosition camPosition = new CameraPosition.Builder()
                .target(new LatLng(LATITUDE_DHAKA, LONGITUDE_DHAKA)).zoom(10)                   // Sets the zoom
                // Sets the orientation of the camera to east
                .build();

        if (mMap != null)
            mMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(camPosition));

        mMap.setMyLocationEnabled(true);
        mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
            @Override
            public boolean onMyLocationButtonClick() {
                doCheckPermissionForGps();
                return false;
            }
        });


        View locationButton = ((View) mapFragment.getView().findViewById(Integer.parseInt("1")).getParent()).findViewById(Integer.parseInt("2"));
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
                locationButton.getLayoutParams();
        // position on right bottom
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        layoutParams.setMargins(0, 0, 0, 100);
    } catch (Exception ex){

    }



}

private void checkLocationandAddToMap() {

    //MarkerOptions are used to create a new Marker.You can specify location, title etc with MarkerOptions
    if (location != null) {

        CameraPosition camPosition = new CameraPosition.Builder()
                .target(new LatLng(location.getLatitude(), location.getLongitude())).zoom(17)                   // Sets the zoom
                // Sets the orientation of the camera to east
                .build();

        if (mMap != null)
            mMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(camPosition));

    }
}

@Override
public void onMapClick(LatLng latLng) {

}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    if (requestCode == MY_PERMISSIONS_REQUEST
            && grantResults[0] == PackageManager.PERMISSION_GRANTED

            && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
        startAction();
    } else {
        CustomSnackbarError.showMessageFromFragment(getContext(),"Permission is necessary" +
                " to enable this feature");
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION},
                MY_PERMISSIONS_REQUEST);
    }
}

/*@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED
                   *//* && grantResults[2] == PackageManager.PERMISSION_GRANTED
                    && grantResults[3] == PackageManager.PERMISSION_GRANTED
                    && grantResults[4] == PackageManager.PERMISSION_GRANTED
                    && grantResults[5] == PackageManager.PERMISSION_GRANTED
                    && grantResults[6] == PackageManager.PERMISSION_GRANTED
                    && grantResults[7] == PackageManager.PERMISSION_GRANTED*//*
                    ) {

                //checkForUpdate();
                startAction();

            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}*/

private boolean checkPermissionGranted() {

  /*  if (ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.ACCESS_NETWORK_STATE)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }

    if (ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.INTERNET)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }*/

   /* if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.CALL_PHONE)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }

    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }*/
    if (ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }

    if (ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        return false;
    }
    return true;
}

private void askForPermission() {

    ActivityCompat.requestPermissions((Activity) getContext(),
            new String[]{
                    /*Manifest.permission.ACCESS_NETWORK_STATE,
                    Manifest.permission.INTERNET,
                    Manifest.permission.CALL_PHONE,
                    Manifest.permission.CAMERA,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,*/
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
            },
            MY_PERMISSIONS_REQUEST);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    dismisLoadingDialog();
}
private void dismisLoadingDialog(){
    if(mLoadingDialog != null && mLoadingDialog.isShowing()){
        mLoadingDialog.dismiss();
    }
}

}

标签: androidlocationandroid-fusedlocation

解决方案


android 实现和创建这个 fusedlocationprovider 库的方式是它需要两种类型的位置更新:1 -> 基于网络 2 -> GPS

当用户尝试从室内或 GPS 没有太多空间从卫星获取位置的任何地方获取位置时,它使用网络。

所以,当你在室内工作时,你会发现它在获取位置时很麻烦。但正如你所说,有时需要更少的时间,有时需要很多时间。

可能的情况是,每当您请求位置时,如果其他应用程序已经获取了位置,它就会去尝试查找位置,如果有位置,您将得到它。否则它会尝试自己找到位置,下次你搜索它时,它会直接给你。

而且您已经使用了 GPS 提供商,也使用了网络提供商。

让我知道它是否有帮助。谢谢


推荐阅读