如何通过位置设置对话框获取位置更新及代码问题排查
排查Google Maps风格位置功能的Fragment代码问题
我帮你梳理下代码里的问题,以及需要补充的逻辑,让按钮点击和权限请求正常工作:
核心问题分析
你的代码已经能触发位置设置对话框,但点击按钮无响应、权限请求后没动作,主要是这几个地方没处理到位:
onActivityResult里只留了RESULT_OK和RESULT_CANCELED的空分支,没有对用户取消对话框的情况做Toast提示- 权限申请成功后,没有编写获取当前位置的逻辑
onRequestPermissionsResult里的权限处理逻辑太简略,拒绝权限时没有反馈,授权成功也没触发位置获取
具体错误点&修正方案
1. 补全onActivityResult的取消逻辑
当用户点击“不了,谢谢”(对应RESULT_CANCELED)时,需要弹出Toast说明位置权限的必要性:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode){ case REQUEST_RESOLVE_ERROR: switch(resultCode){ case Activity.RESULT_OK: // 用户同意开启位置,触发权限检查和位置获取 checkPermissionAndGetLocation(); break; case Activity.RESULT_CANCELED: // 用户取消操作,显示提示 Toast.makeText(getActivity(), "启用位置服务才能使用地图相关功能哦", Toast.LENGTH_SHORT).show(); break; } break; } }
2. 完善权限请求后的处理逻辑
在onRequestPermissionsResult里,要区分权限通过、拒绝的情况,通过后立即获取当前位置:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode){ case ACCESS_FINE_LOCATION_CODE: if(grantResults.length > 0){ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限获取成功,开始获取当前位置 getCurrentLocation(); } else if (grantResults[0] == PackageManager.PERMISSION_DENIED) { // 权限被拒绝,提示用户 Toast.makeText(getActivity(), "需要位置权限才能获取当前位置", Toast.LENGTH_SHORT).show(); } } break; } }
3. 补充获取当前位置的方法
添加一个专门获取当前位置的方法,在权限通过后调用:
private void getCurrentLocation() { if (mGoogleApiClient.isConnected()) { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (location != null) { // 这里拿到了当前位置,可以做后续处理,比如显示经纬度 double latitude = location.getLatitude(); double longitude = location.getLongitude(); Toast.makeText(getActivity(), "当前位置:" + latitude + ", " + longitude, Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), "暂时无法获取位置,请稍后重试", Toast.LENGTH_SHORT).show(); } } } }
4. 优化权限检查的逻辑
把原来分散的权限检查逻辑抽成单独方法,方便复用:
private void checkPermissionAndGetLocation() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_CODE); } else { // 已经有权限,直接获取位置 getCurrentLocation(); } } else { // 低于Android 6.0,直接获取位置 getCurrentLocation(); } }
然后把onConnected里的逻辑改成调用这个方法:
@Override public void onConnected(@Nullable Bundle bundle) { // 先检查位置设置是否开启 settingsRequest(); }
修正后的完整代码片段
public class Home extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { GoogleApiClient mGoogleApiClient; LocationRequest locationRequest; private static final int ACCESS_FINE_LOCATION_CODE = 3310; private static final int REQUEST_RESOLVE_ERROR = 555; public Home() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_home, container, false); mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); mGoogleApiClient.connect(); return view; } @Override public void onStart() { super.onStart(); if (mGoogleApiClient != null && !mGoogleApiClient.isConnected()) { mGoogleApiClient.connect(); } } @Override public void onStop() { super.onStop(); if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { mGoogleApiClient.disconnect(); } } @Override public void onConnected(@Nullable Bundle bundle) { settingsRequest(); } @Override public void onConnectionSuspended(int i) { Toast.makeText(getActivity(), "位置服务连接暂停", Toast.LENGTH_SHORT).show(); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Toast.makeText(getActivity(), "位置服务连接失败", Toast.LENGTH_SHORT).show(); } private void settingsRequest() { LocationRequest locationRequest = LocationRequest.create(); locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); locationRequest.setInterval(30 * 1000); locationRequest.setFastestInterval(5 * 1000); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder() .addLocationRequest(locationRequest); builder.setAlwaysShow(true); final PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build()); result.setResultCallback(new ResultCallback<LocationSettingsResult>() { @Override public void onResult(@NonNull LocationSettingsResult result) { Status status = result.getStatus(); switch (status.getStatusCode()) { case LocationSettingsStatusCodes.SUCCESS: checkPermissionAndGetLocation(); break; case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: try { status.startResolutionForResult(getActivity(), REQUEST_RESOLVE_ERROR); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); } break; } } }); } private void checkPermissionAndGetLocation() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ACCESS_FINE_LOCATION_CODE); } else { getCurrentLocation(); } } else { getCurrentLocation(); } } private void getCurrentLocation() { if (mGoogleApiClient.isConnected()) { if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (location != null) { double latitude = location.getLatitude(); double longitude = location.getLongitude(); Toast.makeText(getActivity(), "当前位置:" + latitude + ", " + longitude, Toast.LENGTH_LONG).show(); // 这里可以把位置传递给地图控件或做其他业务处理 } else { Toast.makeText(getActivity(), "暂时无法获取位置,请稍后重试", Toast.LENGTH_SHORT).show(); } } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case ACCESS_FINE_LOCATION_CODE: if (grantResults.length > 0) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } else { Toast.makeText(getActivity(), "需要位置权限才能获取当前位置", Toast.LENGTH_SHORT).show(); } } break; } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_RESOLVE_ERROR: switch (resultCode) { case Activity.RESULT_OK: checkPermissionAndGetLocation(); break; case Activity.RESULT_CANCELED: Toast.makeText(getActivity(), "启用位置服务才能使用地图相关功能哦", Toast.LENGTH_SHORT).show(); break; } break; } } }
额外注意事项
- 确保在
AndroidManifest.xml中添加了位置权限声明:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- 如果需要持续获取位置更新,可以在
getCurrentLocation之后添加位置监听逻辑,使用LocationServices.FusedLocationApi.requestLocationUpdates
内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur
相关产品推荐
相关产品推荐

