【问题标题】:How to get user's current location in Android如何在Android中获取用户的当前位置
【发布时间】:2017-01-12 15:22:36
【问题描述】:

我想在点击按钮时获取用户当前的纬度。我知道您可以使用 FusedLocationApi 获取最后一个已知位置。但我无法理解的是,需要为此打开 gps 或位置服务吗?如果是,如何检查用户是否打开了位置并获取当前位置。此外,如何在获取位置时包括棉花糖权限检查。

我已经提到过: 1)googlesamples/android-play-location 2)googlesamples/android-XYZTouristAttractions 和许多其他链接,但无法制作完整的流程。

代码

public class AccessLocationFragment extends BaseFragment implements View.OnClickListener, LocationListener,
    GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, GeneralDialogFragment.GeneralDialogClickListener {

private static final int MY_PERMISSIONS_REQUEST_LOCATION = 101;
private static final String TAG = AccessLocationFragment.class.getSimpleName();
private static final int REQUEST_CHECK_SETTINGS = 102;
private Button mAccessLocation;
private EditText mZipCode;
private Dialog progressDialog;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;

public static AccessLocationFragment newInstance() {
    return new AccessLocationFragment();
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_access_location, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    RecycleApplication.getEventBus().register(this);
    mAccessLocation = (Button) view.findViewById(R.id.access_location);
    mZipCode = (EditText) view.findViewById(R.id.zip_code);
    mAccessLocation.setOnClickListener(this);

    mZipCode.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                String zipCode = mZipCode.getText().toString().trim();
                if (TextUtils.isEmpty(zipCode)) {
                    Toast.makeText(mActivity, "Please enter zip code", Toast.LENGTH_SHORT).show();
                } else {
                    Call<Address> response = mRecycleService.getAddress(zipCode);
                    response.enqueue(new GetLocationCallback(AccessLocationFragment.this));
                }
            }
            return false;
        }
    });
    // Create an instance of GoogleAPIClient.
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }
    if (!LocationUtils.checkFineLocationPermission(mActivity)) {
        // See if user has denied permission in the past
        if (shouldShowRequestPermissionRationale(android.Manifest.permission.ACCESS_FINE_LOCATION)) {
            // Show a simple snackbar explaining the request instead
            showPermissionSnackbar();
        } else {
            requestFineLocationPermission();
        }
    } else {
        displayLocationSettingsRequest();
    }
}

private void startHomeActivity(Address address) {
    RecyclePreferences.getInstance().setCity(address.getCity());
    RecyclePreferences.getInstance().setState(address.getState());
    RecyclePreferences.getInstance().setLatitude(address.getLatitude());
    RecyclePreferences.getInstance().setLongitude(address.getLongitude());
    RecyclePreferences.getInstance().setZipCode(address.getZipCode());
    startActivity(new Intent(mActivity, HomeActivity.class));
    mActivity.finish();
}

@Override
public void onSuccess(Call<Address> call, Response<Address> response) {
    mActivity.hideProgressDialog(progressDialog);
    if (response.isSuccessful()) {
        Address address = response.body();
        startHomeActivity(address);
    }
}

@Override
public void onFailure(Call<Address> call, Throwable t) {
    mActivity.hideProgressDialog(progressDialog);
}

@Override
public void onClick(View view) {
    if (view.getId() == R.id.access_location) {
        fetchAddress(mLastLocation);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_LOCATION: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               displayLocationSettingsRequest();
            }
        }
    }
}

private void fetchAddress(Location location) {
    mRecycleService = new RecycleRetrofitBuilder(mActivity).getService();
    Call<Address> response = mRecycleService.getAddress(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
    progressDialog = mActivity.showProgressDialog(mActivity);
    response.enqueue(new GetLocationCallback(AccessLocationFragment.this));
}

private void requestFineLocationPermission() {
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
}

private void showPermissionSnackbar() {
    GeneralDialogFragment generalDialogFragment = GeneralDialogFragment.
            newInstance("Permissions", "Allow Recycle the World to use your location.", "Allow", "Go Back", this);
    mActivity.showDialogFragment(generalDialogFragment);
    displayLocationSettingsRequest();
}

private void displayLocationSettingsRequest() {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(10000 / 2);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
    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:
                    getLocation();
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ");
                    try {
                        status.startResolutionForResult(mActivity, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                        Log.i(TAG, "PendingIntent unable to execute request.");
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
                    break;
            }
        }
    });
}

private void getLocation() {
    if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CHECK_SETTINGS) {
        getLocation();
    }
}

@Override
public void onStart() {
    mGoogleApiClient.connect();
    super.onStart();
}

@Override
public void onStop() {
    mGoogleApiClient.disconnect();
    super.onStop();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    getLocation();
}

@Override
public void onDestroy() {
    super.onDestroy();
    RecycleApplication.getEventBus().unregister(this);
}


@Override
public void onConnectionSuspended(int i) {

}

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

}

@Override
public void onOk(DialogFragment dialogFragment) {
    dialogFragment.dismiss();
    requestFineLocationPermission();
}

@Override
public void onCancel(DialogFragment dialogFragment) {
    dialogFragment.dismiss();

}

}

【问题讨论】:

  • 您说您参考了许多相关资源 - 所以请包含您自己的代码,让我们看看您已经完成了多远,您遇到了什么错误(如果有),我们可以提供帮助。
  • 请看上面的代码。

标签: android location google-play-services


【解决方案1】:

抱歉,我没有查看您的代码,我只是在编写您在问题中要求的功能。 首先,您需要建立与 google api 客户端的连接,例如:

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

根据我的经验,在此之后,您几乎总是会被调用 onConnected() 函数,您可以在 API 级别 23 之后请求位置权限:

public void checkLocationPermission(){
    if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
        // You don't have the permission you need to request it 
        ActivityCompat.requestPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION), REQ_CODE);
    }else{
        // You have the permission.
        requestLocationAccess();
    }
}

如果您请求权限,您的onRequestPermissionsResult() 函数将使用REQ_CODE 调用。如果您需要更多信息来实现事件,请检查 original documentation 以获取运行时权限,这非常有用。
当您拥有权限时,您可以检查该位置是否已启用,例如:

public void requestLocationAccess(){
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval((long) (LocationHelper.UPDATE_INTERVAL_IN_MILLISECONDS*1.1));
    mLocationRequest.setFastestInterval(LocationHelper.UPDATE_INTERVAL_IN_MILLISECONDS);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    final LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
    builder.setAlwaysShow(true); //this is the key ingredient
    com.google.android.gms.common.api.PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>(){
        @Override
        public void onResult(@NonNull LocationSettingsResult result){
            if(requester != null){
                final Status resultStatus = result.getStatus();
                switch(resultStatus.getStatusCode()){
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. You can ask for the user's location HERE



                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the user a dialog.
                        try{
                            resultStatus.startResolutionForResult(this, REQUEST_LOCATION);
                            break;
                        }catch(IntentSender.SendIntentException ignored){}
                    }
                }
            }
        }
    });  
}

如果需要向用户显示启用位置对话框,您将在onActivityResult() 函数中获得回调,请求代码为REQUEST_LOCATION)

完成所有这些过程后,您就可以致电locationManager.getLastKnownLocation() 或开始位置请求或任何您想要的。

PS.:我已经从我的大班中删除了这段代码,所以如果您发现任何错误,请随时提出。我只指定了一切顺利的情况,因为它包含了本质,我希望你可以自己处理异常。

【讨论】:

    【解决方案2】:

    试试这个代码:

    public void showMap() {
    
        mapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
        if (map == null) {
            map = mapFragment.getMap();
        }
    
    
        // Enable Zoom
        map.getUiSettings().setZoomGesturesEnabled(true);
    
        //set Map TYPE
        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    
        //enable Current location Button
        map.setMyLocationEnabled(true);
    
        LocationManager locationManager = (LocationManager)getActivity().getSystemService(getActivity().LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        String bestProvider = locationManager.getBestProvider(criteria, true);
        if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = locationManager.getLastKnownLocation(bestProvider);
        if (location != null) {
            onLocationChanged(location);
        }
        locationManager.requestLocationUpdates(bestProvider, 2000, 0, this);
    }
    
    @Override
    public void onLocationChanged(Location location) {
    
        latitude= location.getLatitude();
        longitude=location.getLongitude();
    
        LatLng loc = new LatLng(latitude, longitude);
    
         if (marker!=null){
             marker.remove();
         }
    
        marker=  map.addMarker(new MarkerOptions().position(loc).title("Sparx IT Solutions"));
        map.moveCamera(CameraUpdateFactory.newLatLng(loc));
        map.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16.0f));
    
    }
    
    @Override
    public void onProviderDisabled(String provider) {
    
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(intent);
        Toast.makeText(getActivity().getBaseContext(), "Gps is turned off!!",
                Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onProviderEnabled(String provider) {
    
        Toast.makeText(getActivity().getBaseContext(), "Gps is turned on!! ",
                Toast.LENGTH_SHORT).show();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      • 1970-01-01
      • 2017-04-01
      相关资源
      最近更新 更多