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但从未赋值,需补充位置权限申请和位置获取逻辑:
- 添加权限到AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- 补充位置获取代码:
在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
相关产品推荐
相关产品推荐

