简体   繁体   中英

How to get location fast and only once using fused location provider client in 2021

I am developing a app which has to get the location information (latitude and longitude) of the device only once but as fast as possible. My code is taking too much time. It is taking around 2-3 minutes to fetch location. Especially for those devices if location button is initially off. I happened to see a relatable question Link below but that is almost 6 year old and I would think the answers are apt in 2021. My situation is also same, I also need to collect longitude and latitude information (for one time only) so I can find the distance between 2 devices. Please find the code that I have used for latitude and longitude information and kindly tell me is there is any better way to do my task. Using this code I will display current location in a text view (BuyerArea in code), once location is displayed correctly I will save latitude and longitude information in firebase database

` public class BuyerAreaFinderActivity extends AppCompatActivity {

String currentGroupName, BuyerLatitude,BuyerLongitude;
Button BuyerAreaFetchBtn, continueBtn;
TextView BuyerArea; // to display location
private FirebaseUser User;
private Task<Void> UserTask;
private FirebaseAuth mAuth;
private DatabaseReference RootRef;
private String currentUserId;
FusedLocationProviderClient fusedLocationProviderClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_buyer_area_finder);

    BuyerAreaFetchBtn= findViewById(R.id.buyAfBtn);
    continueBtn=findViewById(R.id.continueBtn);

    BuyerArea=findViewById(R.id.tv_address);
    mAuth=FirebaseAuth.getInstance();
    currentUserId=mAuth.getCurrentUser().getUid();

    RootRef= FirebaseDatabase.getInstance().getReference();


    fusedLocationProviderClient= LocationServices.getFusedLocationProviderClient(
            BuyerAreaFinderActivity.this);

    BuyerAreaFetchBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!isConnected(this)) { // checking internet connection

                Toast.makeText(getApplicationContext(), " Please connect to internet", Toast.LENGTH_SHORT).show();

            }else {


                LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE
                );
                if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                        || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {

                    if (ActivityCompat.checkSelfPermission(BuyerAreaFinderActivity.this
                            , Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                            && ActivityCompat.checkSelfPermission(BuyerAreaFinderActivity.this
                            , Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){

                        getCurrentLocation();

                    }else {
                        //when permission is not granted
                        //Request permission
                        ActivityCompat.requestPermissions(BuyerAreaFinderActivity.this
                                , new String[]{Manifest.permission.ACCESS_FINE_LOCATION
                                        , Manifest.permission.ACCESS_COARSE_LOCATION}
                                , 100);
                    }

                }else {
                    Toast.makeText(getApplicationContext(), "Please switch on location , We will be sending enquiry to bet shops in your location ", Toast.LENGTH_LONG).show();
                    startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
                }

            }
        }
    });

    BuyerArea.addTextChangedListener(new TextWatcher() { //Here I am displaying location, Once displayed correctly I will save latitude and longitude in my database
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) { Here I am displaying location, Once displayed correctly I will save latitude and longitude in my database


            HashMap<String, Object>buyerLocationMap = new HashMap<>();
            buyerLocationMap.put("buyerLatitude", BuyerLatitude);
            buyerLocationMap.put("buyerLongitude", BuyerLongitude);

            RootRef.child("Users").child(currentUserId).updateChildren(buyerLocationMap)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                   if(task.isSuccessful()){

                       continueBtn.setVisibility(View.VISIBLE);
                       continueBtn.setEnabled(true);

                   }else {
                       String ErrorMessage = task.getException().toString(); // get the error ocuured  from net/firebase
                       Toast.makeText(BuyerAreaFinderActivity.this, "Error : " + ErrorMessage, Toast.LENGTH_SHORT).show();

                   }


                }
            });




        }
    });

    continueBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SendToNextActivity(); // next activity 
            finish();

        }
    });
}



@SuppressLint("MissingSuperCall")
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    //This methood check whether permmission is granted or not after requesting permission using the request code

    //here suppress error by right clicking.
    if(requestCode ==100 && grantResults.length>0&&(grantResults[0]+grantResults[1]
            ==PackageManager.PERMISSION_GRANTED)){
        //when permission granted
        // Call method
        getCurrentLocation();


    }else {
        //when permissions are denied

        if (!ActivityCompat.shouldShowRequestPermissionRationale(BuyerAreaFinderActivity.this, Manifest.permission.ACCESS_FINE_LOCATION )
                && !ActivityCompat.shouldShowRequestPermissionRationale(BuyerAreaFinderActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
            //This block here means PERMANENTLY DENIED PERMISSION
            new AlertDialog.Builder(BuyerAreaFinderActivity.this)
                    .setMessage("You have permanently denied this permission, go to settings to enable this permission")
                    .setPositiveButton("Go to settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            gotoApplicationSettings();
                        }
                    })
                    .setNegativeButton("Cancel", null)
                    .setCancelable(false)
                    .show();
        }else{
            Toast.makeText(getApplicationContext(),"Location permission denied, Please click again to allow location permission.",Toast.LENGTH_LONG).show();
        }
    }
}

@SuppressLint("MissingPermission")

private void getCurrentLocation() {

    fusedLocationProviderClient.flushLocations();// used by me for refreshing don't know correct or not


    fusedLocationProviderClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
        @Override
        public void onComplete(@NonNull Task<Location> task) {

            Location location=task.getResult();
            //Check condition
            if(location !=null){

                BuyerLatitude=String.valueOf(location.getLatitude());
                BuyerLongitude=String.valueOf(location.getLongitude());

/ ----------------- Geocoder is used to find the address if we dont want address to be displayed don't use this part -----------------

                Geocoder geocoder = new Geocoder(BuyerAreaFinderActivity.this, Locale.getDefault());
                try {
                    List<Address> addresses = geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
                    String address = addresses.get(0).getAddressLine(0);
                    BuyerArea.setText(address);
                    BuyerAreaFetchBtn.setVisibility(View.INVISIBLE);

                } catch (IOException e) {
                    e.printStackTrace();
                }
                //------------------up to here for Geocoder-------------------------------------------------------------------------------


            }
            else {
                //Location update.. when location result is null , Initialize location update part
                // LocationRequest locationRequest = new LocationRequest() //deprecated so changed by me

                LocationRequest locationRequest = LocationRequest.create()
                        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                        .setInterval(10000)
                        .setFastestInterval(1000)
                        .setNumUpdates(1);

                //Initialize location call back

                LocationCallback locationCallback=new LocationCallback(){
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        Location location1=locationResult.getLastLocation();

                        BuyerLatitude=String.valueOf(location1.getLatitude());
                        BuyerLongitude=String.valueOf(location1.getLongitude());
                    }
                };
                // Request location updates, Actually I dont want location updates but removal caused further delay in fetching location.
                
                fusedLocationProviderClient.requestLocationUpdates(locationRequest,locationCallback, Looper.myLooper());
                Toast.makeText(getApplicationContext(),"We are collecting your location details. Please wait for few seconds and press the button again",Toast.LENGTH_LONG).show();

                fusedLocationProviderClient.removeLocationUpdates(locationCallback);


            }

        }
    });


}

private void gotoApplicationSettings() { // if location is off, this will allow us to open the settings

    Intent intent = new Intent();
    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", this.getPackageName(), null);
    intent.setData(uri);
    startActivity(intent);

}

private boolean isConnected(View.OnClickListener onClickListener) {

    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo wifiConn = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    NetworkInfo mobileConn = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    return (wifiConn != null && wifiConn.isConnected()) || (mobileConn != null && mobileConn.isConnected());
}

private void SendToNextActivity() {


    Intent nextIntent = new Intent(Current.this, Next.class); // Take to next activity
          startActivity(nextIntent);
          finish();
}

}`

     private void getUserLastLocation(FusedLocationProviderClient fusedLocationProviderClient) {
    
            if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(getContext(), 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.
                Toast.makeText(getContext(), "permission deny before", Toast.LENGTH_SHORT).show();
                checkSelfLoctionPermission();
            }
    
     //this logic you can write seprate to check user is enable the gps or not 
     //make sure before calling the location user has enabled the gps ..this 
     //if... else condition to help to check user has enabled gps or not
    
     if (isLocationEnabled())//if 2
                            {

        //u can write your logic here
}else
{
  Toast.makeText(getContext(), "Please turn on" + " your location...", Toast.LENGTH_LONG).show();
                                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                startActivity(intent);
 
}

    
                 //this if condition only run once.. when first time user want to take location
                //this method will get fresh location (means current location)
            if (!Constant.FETCHINGLOCTIONFIRSTTIEME) {
                CancellationTokenSource tokenSource = new CancellationTokenSource();
                CancellationToken token = tokenSource.getToken();
                mFusedLocationProviderClient.
                        getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, token)
                        .addOnSuccessListener(new OnSuccessListener<Location>() {
                            @Override
                            public void onSuccess(@NonNull Location location) {
    
                                if (location != null) {
                                 
                                     double lat=location.getLatitude();
                                     double longt=location.getLongitude();
    
    
                                } else {
                                   //don't be confused with AlertDialoBox because 
            //this our alerbox written by me you can write own alerbox to show the //message 
                                    Common.AlertDialogBox(getContext(), "Fetching location ",
                                            getString(R.string.fetchingerror));
    
    
                                }
    
    
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
    
                        String message = e.getMessage();
                        String title = "locatuion fetching exception";
                        Common.AlertDialogBox(getContext(), title, message);
    
                    }
                });
            } else {
    
                fusedLocationProviderClient.getLastLocation()
                        .addOnSuccessListener(new OnSuccessListener<Location>() {
                            @Override
                            public void onSuccess(@NonNull Location location) {
                                if (location != null) {
                                    double lat=location.getLatitude();
                                double longt=location.getLongitude();
                                } else {
                                    Toast.makeText(getContext(), "Fetching location error", Toast.LENGTH_SHORT).show();
                                    Log.d("test", "onViewCreated" + "fetching location error");
    
    
                                }
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        String message = e.getMessage();
                        String title = "locatuion fetching exception";
                     
                    }
                });
            }//else closed
        }

  //to check user gps is o or not
    private boolean isLocationEnabled() {
        LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM