使用融合位置提供程序获取用户当前位置
Posted
技术标签:
【中文标题】使用融合位置提供程序获取用户当前位置【英文标题】:Getting user current location using fused location provider 【发布时间】:2019-07-28 04:13:31 【问题描述】:我正在使用 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();
【问题讨论】:
【参考方案1】:大多数情况下,当用户在建筑物内时,GPS 提供商会花费大量时间来获取位置。在这种情况下,您必须从网络提供商处获取位置以获得更快的结果。 GPS 在建筑物外工作得很好,但很难从建筑物内获取位置。请允许从网络和 GPS 提供商获取位置以获得更好的结果。
【讨论】:
【参考方案2】:android 实现和创建这个 fusedlocationprovider 库的方式是它需要两种类型的位置更新: 1 -> 基于网络 2 -> 全球定位系统
当用户尝试从室内或 GPS 没有太多空间从卫星获取位置的任何地方获取位置时,它使用网络。
因此,当您在室内工作时,您会发现获取位置很麻烦。但正如你所说,有时需要更少的时间,有时需要很多时间。
可能的情况是,每当您请求位置时,如果其他应用程序已经获取了位置,它就会去尝试查找位置,并且如果有位置,您就会得到它。否则它会尝试自己找到位置,下次你搜索它时它会直接给你。
并且您已经使用了 GPS 提供商,也使用了网络提供商。
如果有帮助,请告诉我。谢谢
【讨论】:
以上是关于使用融合位置提供程序获取用户当前位置的主要内容,如果未能解决你的问题,请参考以下文章
使用融合的 Location Provider 获取当前位置