Issue
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();
}
}`
Solution
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);
}
Answered By - Aakash Kumar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.