Android Studio点击Find按钮无响应问题求助(附代码与日志)
问题:点击「Find」按钮地图无反应,AsyncTask抛出空指针异常
我开发了一款用于查找附近医院、银行等场所的Android应用,但每次点击「Find」按钮时地图都没有任何反应。我是Android Studio新手,不知道怎么修正代码实现预期功能。以下是我的MainActivity代码和Logcat报错信息:
MainActivity代码
Spinner spType; Button btnFind; SupportMapFragment supportMapFragment; GoogleMap map; FusedLocationProviderClient fusedLocationProviderClient; double currentLat = 0, currentLong = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); spType = findViewById(R.id.sp_type); btnFind = findViewById(R.id.bt_find); supportMapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.google_map); String[] placeTypeListe = {"atm", "bank", "hospital", "movie_theater", "restaurant"}; String[] placeNameList = {"ATM", "Bank", "Hospital", "Movie Theatre", "Restaurant"}; spType.setAdapter(new ArrayAdapter<>(MainActivity.this , android.R.layout.simple_spinner_dropdown_item, placeNameList)); fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); if (ActivityCompat.checkSelfPermission(MainActivity.this , Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } else { ActivityCompat.requestPermissions(MainActivity.this , new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 44); } btnFind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int i = spType.getSelectedItemPosition(); String url = "https://maps.googleapis.com/maps/api/..." + "?location=" + currentLat + "," + currentLong + "&radius=5000" + "&type=" + placeTypeListe[i] + "&sensor=true" + "&key=" + getResources().getString(R.string.google_map_key); new PlaceTask().execute(url); } }); } private void getCurrentLocation() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } Task<Location> task = fusedLocationProviderClient.getLastLocation(); task.addOnSuccessListener(new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { if (location != null){ currentLat = location.getLatitude(); currentLong = location.getLongitude(); supportMapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(@NonNull GoogleMap googleMap) { map = googleMap; map.animateCamera(CameraUpdateFactory.newLatLngZoom( new LatLng(currentLat,currentLong),10 )); } }); } } }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 44) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } } } private class PlaceTask extends AsyncTask<String,Integer,String> { @Override protected String doInBackground(String... strings) { String data = null; try { data = downloadUrl(strings[0]); } catch (IOException e) { e.printStackTrace(); } return data; } @Override protected void onPostExecute(String s) { new ParserTask().execute(s); } } private String downloadUrl(String string) throws IOException { URL url = new URL(string); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); InputStream stream = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder builder = new StringBuilder(); String line = ""; while ((line = reader.readLine()) != null){ builder.append(line); } String data = builder.toString(); reader.close(); return data; } private class ParserTask extends AsyncTask<String,Integer, List<HashMap<String,String>>> { @Override protected List<HashMap<String, String>> doInBackground(String... strings) { JsonParser jsonParser = new JsonParser(); List<HashMap<String,String>> mapList = null; JSONObject object = null; try { object = new JSONObject(strings[0]); mapList = jsonParser.parseResult(object); } catch (JSONException e) { e.printStackTrace(); } return mapList; } @Override protected void onPostExecute(List<HashMap<String, String>> hashMaps) { map.clear(); for (int i=0;i<hashMaps.size();i++){ HashMap<String,String> hashMapList = hashMaps.get(i); double lat = Double.parseDouble(hashMapList.get("lat")); double lng = Double.parseDouble(hashMapList.get("lng")); String name = hashMapList.get("name"); LatLng latLng = new LatLng(lat,lng); MarkerOptions options = new MarkerOptions(); options.position(latLng); options.title(name); map.addMarker(options); } } }
Logcat报错信息
FATAL EXCEPTION: AsyncTask #1 Process: com.example.add, PID: 13706 java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$4.done(AsyncTask.java:415) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383) at java.util.concurrent.FutureTask.setException(FutureTask.java:252) at java.util.concurrent.FutureTask.run(FutureTask.java:271) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:121) at org.json.JSONTokener.nextValue(JSONTokener.java:98) at org.json.JSONObject.<init>(JSONObject.java:168) at org.json.JSONObject.<init>(JSONObject.java:185) at com.example.add.MainActivity$ParserTask.doInBackground(MainActivity.java:174) at com.example.add.MainActivity$ParserTask.doInBackground(MainActivity.java:166) at android.os.AsyncTask$3.call(AsyncTask.java:394) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920)
解决方案
1. 修正Places API请求URL
代码中使用的URL不完整,正确的Nearby Search API地址需替换为:
String url = "https://maps.googleapis.com/maps/api/place/nearbysearch/json" + "?location=" + currentLat + "," + currentLong + "&radius=5000" + "&type=" + placeTypeListe[i] + "&key=" + getResources().getString(R.string.google_map_key);
注:sensor=true参数已废弃,无需添加
2. 完善网络请求错误处理
在downloadUrl方法中添加响应码检查,避免请求失败时返回null:
private String downloadUrl(String string) throws IOException { URL url = new URL(string); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); // 检查HTTP响应状态 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new IOException("请求失败,响应码:" + connection.getResponseCode()); } InputStream stream = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder builder = new StringBuilder(); String line = ""; while ((line = reader.readLine()) != null){ builder.append(line); } String data = builder.toString(); reader.close(); connection.disconnect(); // 主动断开连接 return data; }
3. 添加空值检查,防止崩溃
- 在
PlaceTask.onPostExecute中检查下载的数据是否有效:
@Override protected void onPostExecute(String s) { if (s != null && !s.isEmpty()) { new ParserTask().execute(s); } else { Log.e("PlaceTask", "下载的数据为空或无效"); // 可在此处给用户弹出网络错误提示 } }
- 在
ParserTask.doInBackground中检查传入的JSON字符串:
@Override protected List<HashMap<String, String>> doInBackground(String... strings) { if (strings[0] == null || strings[0].isEmpty()) { Log.e("ParserTask", "传入的JSON数据为空"); return null; } JsonParser jsonParser = new JsonParser(); List<HashMap<String,String>> mapList = null; JSONObject object = null; try { object = new JSONObject(strings[0]); mapList = jsonParser.parseResult(object); } catch (JSONException e) { e.printStackTrace(); } return mapList; }
- 在
ParserTask.onPostExecute中检查地图和查询结果是否有效:
@Override protected void onPostExecute(List<HashMap<String, String>> hashMaps) { if (map == null) { Log.e("ParserTask", "地图未初始化"); return; } map.clear(); if (hashMaps == null || hashMaps.isEmpty()) { Log.e("ParserTask", "未找到附近的场所"); return; } for (int i=0;i<hashMaps.size();i++){ HashMap<String,String> hashMapList = hashMaps.get(i); double lat = Double.parseDouble(hashMapList.get("lat")); double lng = Double.parseDouble(hashMapList.get("lng")); String name = hashMapList.get("name"); LatLng latLng = new LatLng(lat,lng); MarkerOptions options = new MarkerOptions(); options.position(latLng); options.title(name); map.addMarker(options); } }
4. 验证API密钥与权限
- 确保
google_map_key对应的API密钥已启用Places API和Maps SDK for Android,且应用包名限制设置正确。 - 确认
AndroidManifest.xml中已添加必要权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
内容的提问来源于stack exchange,提问作者youna kim
相关产品推荐
相关产品推荐

