FusedLocationProvider 始终返回 null Location 对象

Posted

技术标签:

【中文标题】FusedLocationProvider 始终返回 null Location 对象【英文标题】:FusedLocationProvider always returns null Location object 【发布时间】:2022-01-21 16:12:15 【问题描述】:

我已经尝试了无数的 FusedLocationProviderClient 实现,我在互联网上找到并使用文档,但每次我都无法获得位置和空对象。这是我在主要活动中使用 FusedLocationProviderClient 获取位置的最终代码。然后我在另一个片段中使用 Location 对象来显示用户的坐标。

这是活动代码

    ActivityMainBinding activityMainBinding;
    NavHostFragment navHostFragment;
    NavController navController;
    LocationRequest mLocationRequest;
    Location mLocation;
    FusedLocationProviderClient mFusedLocationClient;

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        startLocation();

        activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(activityMainBinding.getRoot());
        navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerMain);
        navController = navHostFragment.getNavController();

        activityMainBinding.bottomNavigation.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() 
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) 
                switch(item.getItemId()) 
                    case R.id.menuItemHome:
                        navController.navigate(R.id.homeFragment);
                        break;
                    case R.id.menuItemSearch:
                        navController.navigate(R.id.searchFragment);
                        break;
                    case R.id.menuItemProfile:
                        navController.navigate(R.id.profileFragment);
                        break;
                    case R.id.menuItemSettings:
                        navController.navigate(R.id.settingsFragment);
                        break;
                
                return true;
            
        );
    

    @Override
    public void onBackPressed() 
        navController.navigate(R.id.homeFragment);
        activityMainBinding.bottomNavigation.setSelectedItemId(R.id.menuItemHome);
    

    public void startLocation() 

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        if (    (ContextCompat.checkSelfPermission( this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED )
                || ( ContextCompat.checkSelfPermission( this,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ) 
            //Location Permission granted
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
            LocationServices.getFusedLocationProviderClient(this).getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() 
                @Override
                public void onSuccess(@NonNull Location location) 
                    mLocation = location;
                
            );
         else 
            //Request Location Permission
            checkLocationPermission();
        
    

    public void stopLocationUpdates() 
        if( mFusedLocationClient != null )
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
    

    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
    private void checkLocationPermission() 
        if (    (ContextCompat.checkSelfPermission( this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED )
                || ( ContextCompat.checkSelfPermission( this,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ) 

            if (    ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    || ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_COARSE_LOCATION) ) 

                //Request location message for user
                new AlertDialog.Builder(this)
                        .setTitle("Location Permission Needed")
                        .setMessage("This app needs the Location permission, please accept to use location functionality")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() 
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) 
                                //Prompt the user once explanation has been shown
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]Manifest.permission.ACCESS_COARSE_LOCATION,
                                        MY_PERMISSIONS_REQUEST_LOCATION );
                            
                        )
                        .create()
                        .show();
             else 
                //request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]Manifest.permission.ACCESS_COARSE_LOCATION,
                        MY_PERMISSIONS_REQUEST_LOCATION );
            
        
    

    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) 
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == MY_PERMISSIONS_REQUEST_LOCATION) 
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) 

                // permission was granted
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_COARSE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) 
                    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
                
            
        
    

    LocationCallback mLocationCallback = new LocationCallback() 
        @Override
        public void onLocationResult(LocationResult locationResult) 
            if (locationResult == null) 
                return;
            
            for (Location location : locationResult.getLocations()) 
                if (location != null) 
                    mLocation = location;
                    return;
                
            
        
    ;

这是片段类中我要显示坐标的代码

public class HomeFragment extends Fragment 
    private HomeFragmentBinding homeFragmentBinding;
    private NavController navController;
    private MainViewModel mainViewModel;
    private Location userLocation;
    private MainActivity mainActivity;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        mainViewModel = new ViewModelProvider(getActivity()).get(MainViewModel.class);
        mainActivity = (MainActivity) getActivity();
        userLocation = mainActivity.mLocation;

        homeFragmentBinding.textDist1.setText("Lat: " + userLocation.getLatitude() + " Long: " + userLocation.getLongitude());
    

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        homeFragmentBinding = HomeFragmentBinding.inflate(inflater, container, false);
        return homeFragmentBinding.getRoot();
    

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) 
        super.onViewCreated(view, savedInstanceState);
        navController = Navigation.findNavController(view);

        homeFragmentBinding.textDist1.setText("Lat: " + userLocation.getLatitude() + " Long: " + userLocation.getLongitude());

    

我还在清单中添加了 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 的权限,并且

implementation 'com.google.android.gms:play-services-location:19.0.0' 在 gradle 构建中。

每次运行应用程序时,我都会收到空 Location 对象的空指针异常。用户也没有获得提供位置访问权限的弹出窗口。 我从我的 android 虚拟设备的设置中手动打开了位置访问,但没有任何改变。在 android 文档和旧的 *** 页面上经过无数小时后,我找不到问题。 感谢您的帮助。

【问题讨论】:

在获得该位置之前,您需要避免尝试使用该位置。现在,onViewCreated() 中的片段尝试使用该位置,而不考虑您何时实际获得该位置。将所有位置逻辑移动到片段(或 Jetpack ViewModel)中,并在 onLocationResult() 获取位置时更新您的 UI。 我按照你说的做了,把我所有的位置逻辑都移到了片段类中,并在 onSuccessListener 的 onSuccess 方法中为 textView 调用了 setText。我还添加了一条 toast 消息以确认实际调用了 onSuccess 方法。然后我在 onCreate 和 onViewCreated 上调用了我的 startLocation 方法(只是为了确定),但我看到 textFields 没有变化,也没有收到 toast 消息。有什么问题? 【参考方案1】:

首先,创建一个 Fused Location Provider Client 的实例。

mFusedLocationClient= LocationServices.getFusedLocationProviderClient(this)

然后执行位置请求。

mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());

我想官方文档很清楚。参考-https://developer.android.com/training/location/

【讨论】:

以上是关于FusedLocationProvider 始终返回 null Location 对象的主要内容,如果未能解决你的问题,请参考以下文章

FusedLocationProvider - 如果位置模式为“仅设备”,任何获取位置的方法?

FusedLocationProvider 有时会给出错误的位置

FusedLocationProvider 位置更新的单独类或服务?

无法使用 FusedLocationProvider 将 Gps 设置升级到高精度在某些设备中

Android:FusedLocationProvider,每隔几秒获取一次位置

使用 fusedLocationProvider.removeLocationUpdates (locationCallback) Android Studio 时出错