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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:20:53