You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中Java获取用户当前位置时变量null致崩溃问题

Android Google Maps 显示当前位置时变量始终为null的问题修复

你的代码里有几个关键问题导致here变量始终为null,同时还有逻辑错误导致位置无法正确获取,下面逐一说明并给出修复方案:

问题分析

  1. 局部变量覆盖全局变量:在onMapReady方法里,你重新定义了LatLng here局部变量,完全覆盖了全局的here变量,导致全局变量始终没被使用。
  2. 异步执行顺序问题:getLastLocation()是异步回调方法,而onMapReady可能先执行,这时候全局here还没被赋值,自然是null。
  3. 经纬度赋值颠倒:你把location.getLatitude()赋值给了longo,location.getLongitude()赋值给了lato,最后创建LatLng时顺序搞反了,即使获取到位置也会显示错误坐标。
  4. 权限处理缺失:当权限未授予时,你只弹出了Toast,但没有调用askPermission()让用户授权,导致无法获取位置权限。
  5. getLastLocation()的局限性:该方法依赖设备缓存的最后位置,如果设备刚启动或很久没获取位置,会返回null,应该使用getCurrentLocation()主动请求实时位置。

修复后的完整代码

package com.example.mobileproject;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.widget.Toast;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.CancellationTokenSource;

public class activity_hospitals extends FragmentActivity implements OnMapReadyCallback {
    private GoogleMap Gmap;
    private FusedLocationProviderClient flsc;
    private LatLng here;
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 100;

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

        // 初始化Toolbar
        androidx.appcompat.widget.Toolbar mytoolbar = findViewById(R.id.hospitalToolbar);
        mytoolbar.setTitle("Hospitals Near You");

        // 初始化位置客户端
        flsc = LocationServices.getFusedLocationProviderClient(this);

        // 初始化地图
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        Gmap = googleMap;
        // 先添加固定的医院标记
        addHospitalMarkers();
        // 检查权限并获取位置
        checkLocationPermissionAndGetLocation();
    }

    private void addHospitalMarkers() {
        LatLng placeholder1 = new LatLng(33.66535378588594, 35.420147180348465);
        Gmap.addMarker(new MarkerOptions().position(placeholder1).title("Dr. Monzer al Haj Hospital"));

        LatLng placeholder2 = new LatLng(33.76696201016636, 35.48301133270906);
        Gmap.addMarker(new MarkerOptions().position(placeholder2).title("SSH"));
    }

    private void checkLocationPermissionAndGetLocation() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            getCurrentLocation();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
        }
    }

    private void getCurrentLocation() {
        // 创建位置请求,主动获取实时位置
        LocationRequest locationRequest = LocationRequest.create()
                .setPriority(Priority.PRIORITY_HIGH_ACCURACY)
                .setInterval(10000)
                .setFastestInterval(5000);

        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        flsc.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, cancellationTokenSource.getToken())
                .addOnSuccessListener(this, location -> {
                    if (location != null) {
                        // 正确赋值经纬度:纬度在前,经度在后
                        here = new LatLng(location.getLatitude(), location.getLongitude());
                        // 添加当前位置标记并移动相机
                        updateMapWithCurrentLocation();
                    } else {
                        Toast.makeText(this, "无法获取当前位置", Toast.LENGTH_SHORT).show();
                        // 位置获取失败时使用默认坐标
                        useDefaultLocation();
                    }
                })
                .addOnFailureListener(this, e -> {
                    Toast.makeText(this, "位置获取失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
                    useDefaultLocation();
                });
    }

    private void updateMapWithCurrentLocation() {
        if (Gmap != null && here != null) {
            Gmap.addMarker(new MarkerOptions().position(here).title("Your Location"));
            float zoomLevel = 11.0f;
            Gmap.moveCamera(CameraUpdateFactory.newLatLngZoom(here, zoomLevel));
        }
    }

    private void useDefaultLocation() {
        // 使用默认坐标作为 fallback
        here = new LatLng(33.71456158807447, 35.48425016137045);
        updateMapWithCurrentLocation();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getCurrentLocation();
            } else {
                Toast.makeText(this, "需要位置权限才能显示当前位置", Toast.LENGTH_SHORT).show();
                useDefaultLocation();
            }
        }
    }
}

关键修复点说明

  • 调整执行顺序:把获取位置的逻辑放到onMapReady之后,确保地图初始化完成后再处理位置更新。
  • 移除局部变量覆盖:删除onMapReady里的局部here变量,直接使用全局变量。
  • 修正经纬度顺序:创建LatLng时严格遵循纬度, 经度的顺序。
  • 替换为getCurrentLocation():主动请求实时位置,避免依赖可能为null的缓存位置。
  • 完善权限处理:权限未授予时主动发起请求,拒绝权限后提供默认坐标作为备选方案。
  • 拆分逻辑:把添加医院标记、更新地图等逻辑拆分为独立方法,提高代码可读性。

额外注意事项

  1. 确保在AndroidManifest.xml中添加位置权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
  1. 测试时请在真机上测试,模拟器需要手动设置模拟位置。
  2. 针对Android 12及以上版本,还需要申请ACCESS_COARSE_LOCATION权限作为备选。

内容的提问来源于stack exchange,提问作者sammy medawar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:40:31