Android调用Positionstack API返回HTTP 400语法错误求助
解决Positionstack API在Android模拟器中返回400 Bad Request的问题
你的代码存在多个明确问题,直接导致了400错误及JSON语法错误提示,以下是问题分析和修复方案:
问题根源
- 语法不完整:代码中
con.set语句未写完,属于无效语法,会导致请求构造逻辑异常。 - 请求头与请求体不匹配:你设置了
Content-Type: application/json,但注释的参数传递代码是用form格式键值对(access_key=xxx),服务器尝试按JSON解析时自然会报语法错误。 - 缺少必填参数:注释掉了参数写入代码,未向API传递
access_key和query这两个核心参数,服务器无法处理空请求。 - 请求方法选择不当:Positionstack的逆地理编码API默认支持GET请求,用GET传递参数更简洁,也不容易出错。
修复方案
方案1:使用GET请求(推荐)
GET请求直接将参数拼接在URL后,无需处理请求体,代码更简洁可靠:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; public class NetTest { public static String sendRequest(String baseUrl, String coordinate, String accessKey){ HttpURLConnection con = null; BufferedReader buffer = null; StringBuffer resultBuffer = null; InputStream is; try{ // 对坐标参数进行URL编码,避免特殊字符问题 String encodedCoordinate = URLEncoder.encode(coordinate, StandardCharsets.UTF_8.name()); // 拼接完整请求URL String fullUrl = String.format("%s?access_key=%s&query=%s", baseUrl, accessKey, encodedCoordinate); URL url = new URL(fullUrl); con = (HttpURLConnection) url.openConnection(); con.setConnectTimeout(5000); con.setReadTimeout(5000); con.setRequestMethod("GET"); // 接收响应 int responseCode = con.getResponseCode(); System.out.println(responseCode); is = responseCode == 200 ? con.getInputStream() : con.getErrorStream(); resultBuffer = new StringBuffer(); String line; buffer = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8.name())); while ((line = buffer.readLine()) != null){ resultBuffer.append(line); } return resultBuffer.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源,避免内存泄漏 if (buffer != null) { try { buffer.close(); } catch (IOException e) { e.printStackTrace(); } } if (con != null) { con.disconnect(); } } return ""; } public static void main(String[] args) { String coordinate = "-33.7,127"; String url = "http://api.positionstack.com/v1/reverse"; String accessKey = "你的实际access_key"; // 替换为你的API密钥 System.out.println(sendRequest(url, coordinate, accessKey)); } }
方案2:修复POST请求(若坚持使用)
如果一定要用POST,需保证请求头与请求体格式一致,以下是两种可行方式:
方式A:Form格式POST请求
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; public class NetTest { public static String sendRequest(String urlParam, String coordinate, String accessKey){ HttpURLConnection con = null; BufferedReader buffer = null; StringBuffer resultBuffer = null; InputStream is; try{ URL url = new URL(urlParam); con = (HttpURLConnection) url.openConnection(); con.setConnectTimeout(5000); con.setReadTimeout(5000); con.setRequestMethod("POST"); // 设置正确的Form格式请求头 con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); con.setDoOutput(true); // 构造Form参数 String postData = String.format("access_key=%s&query=%s", accessKey, coordinate); byte[] postDataBytes = postData.getBytes(StandardCharsets.UTF_8); // 写入请求体 try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { wr.write(postDataBytes); wr.flush(); } // 接收响应 int responseCode = con.getResponseCode(); System.out.println(responseCode); is = responseCode == 200 ? con.getInputStream() : con.getErrorStream(); resultBuffer = new StringBuffer(); String line; buffer = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8.name())); while ((line = buffer.readLine()) != null){ resultBuffer.append(line); } return resultBuffer.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (buffer != null) { try { buffer.close(); } catch (IOException e) { e.printStackTrace(); } } if (con != null) { con.disconnect(); } } return ""; } public static void main(String[] args) { String coordinate = "-33.7,127"; String url = "http://api.positionstack.com/v1/reverse"; String accessKey = "你的实际access_key"; // 替换为你的API密钥 System.out.println(sendRequest(url, coordinate, accessKey)); } }
方式B:JSON格式POST请求
若要使用JSON格式,需构造合法的JSON请求体:
// 仅替换请求头和请求体部分代码 con.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); con.setDoOutput(true); // 构造合法的JSON字符串 String jsonBody = String.format("{\"access_key\":\"%s\",\"query\":\"%s\"}", accessKey, coordinate); byte[] jsonBytes = jsonBody.getBytes(StandardCharsets.UTF_8); try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { wr.write(jsonBytes); wr.flush(); }
额外注意事项
在Android中,网络请求不能在主线程执行,需要用Coroutine、AsyncTask或第三方网络库(如OkHttp)处理异步请求,否则会抛出NetworkOnMainThreadException。
内容的提问来源于stack exchange,提问作者user130355
相关产品推荐
相关产品推荐

