【问题标题】:How to get location fast and only once using fused location provider client in 2021如何在 2021 年使用融合的位置提供程序客户端快速且仅一次获取位置
【发布时间】:2021-11-07 16:30:21
【问题描述】:

我正在开发一个应用程序,它必须尽可能快地获取设备的位置信息(纬度和经度)一次。我的代码花费了太多时间。获取位置大约需要 2-3 分钟。特别是对于那些设备,如果位置按钮最初是关闭的。我碰巧看到一个相关的问题Link below ,但那已经快 6 岁了,我认为答案在 2021 年很合适。我的情况也一样,我还需要收集经度和纬度信息(仅限一次)所以我可以找到两个设备之间的距离。请找到我用于纬度和经度信息的代码,并请告诉我是否有更好的方法来完成我的任务。使用此代码,我将在文本视图中显示当前位置(代码中的 BuyerArea),一旦位置正确显示,我将在 firebase 数据库中保存纬度和经度信息

` 公共类 BuyerAreaFinderActivity 扩展 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 用于查找地址 如果我们不想显示地址,请不要使用这部分 -------- ---------

                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();
}

}`

【问题讨论】:

  • 这段代码中到底有什么不符合您的预期?告诉我们共享代码有什么问题。你有什么错误吗?
  • @AlexMamo.. 获取位置有延迟,大约 2、3 分钟,

标签: android firebase android-studio location


【解决方案1】:

因为你调用 getLastlocation() 调用 getcurrentLocation() 在 getLastLocation() 的情况下,如果用户禁用 GPS 位置,它会尝试从缓存中获取用户 lastLocation。在这种情况下,位置将从缓存中清除。在您启用 GPS 后,它正在等待任何应用调用当前位置并存储到缓存中.当任何应用程序获取位置时,它会自动将值存储到缓存中(如 googlemap 等)..之后您的应用程序将获得用户的最后一个位置。摆脱这种想法调用 getCurrentLocation() bcoz 当前位置总是调用新条目获取用户确切位置的位置。如果您的应用程序调用 getCurrentLocation(),则位置会自动保存到缓存中,然后您可以调用 getLastLocation()。 如果你需要代码注释它..我会在这里更新代码

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-28
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 2013-09-01
    • 2014-09-05
    • 2014-11-29
    • 2015-12-22
    相关资源
    最近更新 更多