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

Android Studio中Google Maps的SearchView输入位置时崩溃求助

Google Maps SearchView 模拟器崩溃问题解决

问题描述

在Android Studio中使用Java开发Google Maps的SearchView功能时,输入位置后模拟器直接崩溃。先后尝试两种教程方法均无效,报错指向com.example.routeplanner.MainActivity$1.onQueryTextSubmit(MainActivity.java:77),实际崩溃日志显示空指针异常。

代码片段

MainActivity.java 代码

import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.widget.Toast;
import androidx.fragment.app.FragmentActivity;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.maps.CameraUpdate;
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.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import androidx.appcompat.widget.SearchView;
import java.io.IOException;
import java.util.List;
import java.util.Locale;

public class MainActivity extends FragmentActivity implements OnMapReadyCallback
{
    GoogleMap googleMap;
    SupportMapFragment mapFragment;
    SearchView searchView;
    Location currentLocation;
    FusedLocationProviderClient fusedClient;
    private static final int REQUEST_CODE = 101;
    FrameLayout frameLayout;
    Marker marker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        searchView = findViewById(R.id.search);
        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentMap);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                String location = searchView.getQuery().toString();
                if (location == null)
                {
                    Toast.makeText(MainActivity.this, "Location NOT FOUND", Toast.LENGTH_SHORT).show();

                    }else
                {
                    Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
                    try
                    {
                        List<Address> addressList = geocoder.getFromLocationName(location, 1);
                        if (addressList.size() > 0 )
                        {
                            LatLng latLng = new LatLng(addressList.get(0).getLatitude(),addressList.get(0).getLongitude());
                            if (marker != null)
                            {
                                marker.remove();
                            }
                            MarkerOptions markerOptions = new MarkerOptions().position(latLng).title(location);
                            markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
                            CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 5);
                            googleMap.animateCamera(cameraUpdate);
                            marker = googleMap.addMarker(markerOptions);
                        }
                    }catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }
                    return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        this.googleMap = googleMap;
    }
}

SearchView 布局代码

<androidx.appcompat.widget.SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#BFBFBF"
        android:elevation="5dp"
        app:iconifiedByDefault="false"
        app:queryHint="Search Location" />

崩溃日志(翻译后)

E/AndroidRuntime: 致命异常: main
    进程: com.example.routeplanner, PID: 3893
    java.lang.NullPointerException: 尝试调用空对象引用的虚拟方法 'double android.location.Location.getLatitude()'
        at com.example.routeplanner.MainActivity.onMapReady(MainActivity.java:115)
        at com.google.android.gms.maps.zzat.zzb(com.google.android.gms:play-services-maps@@18.1.0:1)
        at com.google.android.gms.maps.internal.zzar.zza(com.google.android.gms:play-services-maps@@18.1.0:6)
        at com.google.android.gms.internal.maps.zzb.onTransact(com.google.android.gms:play-services-maps@@18.1.0:3)
        at android.os.Binder.transact(Binder.java:499)
        at fj.c(:com.google.android.gms.dynamite_mapsdynamite@230514022@23.05.14 (040700-0):2)
        at com.google.maps.api.android.lib6.impl.bg.run(:com.google.android.gms.dynamite_mapsdynamite@230514022@23.05.14 (040700-0):1)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

问题分析与修复方案

核心问题1:GoogleMap 对象未就绪就被调用

当前代码中,若用户在地图加载完成前提交SearchView,googleMap对象会处于null状态,调用googleMap.animateCamera或googleMap.addMarker时直接触发崩溃。

修复代码:
在onQueryTextSubmit方法开头增加地图对象非空判断:

@Override
public boolean onQueryTextSubmit(String query) {
    String location = searchView.getQuery().toString();
    // 先判断地图是否加载完成
    if (googleMap == null) {
        Toast.makeText(MainActivity.this, "地图加载中,请稍后重试", Toast.LENGTH_SHORT).show();
        return false;
    }
    // 修正空判断逻辑:getQuery().toString()不会返回null,需判断空字符串
    if (location.isEmpty()) {
        Toast.makeText(MainActivity.this, "请输入位置", Toast.LENGTH_SHORT).show();
    } else {
        Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
        try {
            List<Address> addressList = geocoder.getFromLocationName(location, 1);
            // 增加地址列表非空判断
            if (addressList != null && addressList.size() > 0 ) {
                LatLng latLng = new LatLng(addressList.get(0).getLatitude(),addressList.get(0).getLongitude());
                if (marker != null) {
                    marker.remove();
                }
                MarkerOptions markerOptions = new MarkerOptions().position(latLng).title(location);
                markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
                // 调整缩放级别至更合理的15级
                CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
                googleMap.animateCamera(cameraUpdate);
                marker = googleMap.addMarker(markerOptions);
            } else {
                Toast.makeText(MainActivity.this, "未找到该位置", Toast.LENGTH_SHORT).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "位置解析失败", Toast.LENGTH_SHORT).show();
        }
    }
    return false;
}

核心问题2:Location 对象未初始化

崩溃日志显示尝试调用Location.getLatitude()但对象为null,你声明了currentLocation但从未赋值,需补充位置权限申请和位置获取逻辑:

  1. 添加权限到AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  1. 补充位置获取代码:
    在MainActivity中添加以下方法:
import android.Manifest;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.location.LocationServices;

// 在onCreate方法中初始化fusedClient并调用fetchLocation
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    searchView = findViewById(R.id.search);
    mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentMap);
    // 初始化位置客户端
    fusedClient = LocationServices.getFusedLocationProviderClient(this);
    // 获取当前位置
    fetchLocation();
    // ... 原有SearchView监听代码
    mapFragment.getMapAsync(this);
}

private void fetchLocation() {
    // 检查权限
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED 
        && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
        return;
    }
    // 获取最后已知位置
    Task<Location> task = fusedClient.getLastLocation();
    task.addOnSuccessListener(location -> {
        if (location != null) {
            currentLocation = location;
            // 地图就绪后定位到当前位置
            if (googleMap != null) {
                LatLng currentLatLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15));
            }
        }
    });
}

// 权限申请回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            fetchLocation();
        }
    }
}

额外注意事项

  • 确保build.gradle中引入正确的依赖:
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
  • Geocoder依赖网络和设备服务,需做好异常捕获和无结果的提示逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 15:50:17