调用Google Geolocation API时持续触发FileNotFoundException求助
问题
调用Google Geolocation API时触发FileNotFoundException,确认已使用POST请求方式,先后尝试两种实现代码仍未解决:
初始实现代码
Activity代码
String url = "https://www.googleapis.com/geolocation/v1/geolocate?key=API_KEY"; LocationAsyncTask task = new LocationAsyncTask(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); else task.execute(url);
AsyncTask代码
protected Void doInBackground(String... param) { HttpsConnectionHelper conn = new HttpsConnectionHelper(weakContext.get()); String response = conn.httpPost(param[0]); Log.d(MainActivity.LOG_TAG, "LocationAsyncTask = " + response); return null; }
HttpsConnectionHelper代码
String httpPost(String requestURL) { Log.d(MainActivity.LOG_TAG, "HttpsConnectionHelper# requestURL = " + requestURL); URL url; HttpsURLConnection conn = null; try { //Create connection url = new URL(requestURL); conn = (HttpsURLConnection) url.openConnection(); Log.d(MainActivity.LOG_TAG, "HttpsConnectionHelper# url.openConnection()"); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Accept", "application/json"); conn.connect(); Log.d(MainActivity.LOG_TAG, "HttpsConnectionHelper# conn.connect()"); //Get Response InputStream is = conn.getInputStream(); Log.d(MainActivity.LOG_TAG, "HttpsConnectionHelper# is.available() = "+is.available()); BufferedReader rd = new BufferedReader(new InputStreamReader(is)); String line; StringBuilder response = new StringBuilder(); while ((line = rd.readLine()) != null) { response.append(line); } rd.close(); return response.toString(); } catch (Exception e) { e.printStackTrace(); Log.d(MainActivity.LOG_TAG, "HttpsConnectionHelper#Exception# e.getMessage() = "+e.getMessage()); } finally { if (conn != null) { conn.disconnect(); } } return ""; }
编辑补充:参考官方curl重写代码
官方curl示例:
curl -X POST "https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d \ '{ "homeMobileCountryCode":310, "homeMobileNetworkCode":410, "radioType":"gsm", "carrier":"Vodafone", "considerIp":true }'
重写后的Android代码:
public class GeolocationTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { String apiUrl = "https://www.googleapis.com/geolocation/v1/geolocate?key=API_KEY"; Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground() apiUrl = " + apiUrl); String requestBody = "{ " + "\"homeMobileCountryCode\":310, " + "\"homeMobileNetworkCode\":410, " + "\"radioType\":\"gsm\", " + "\"carrier\":\"Vodafone\", " + "\"considerIp\":true " + "}"; try { URL url = new URL(apiUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // Set up the connection connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/json"); connection.setDoOutput(true); Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground() before write"); // Write the request body try (OutputStream os = connection.getOutputStream()) { byte[] input = requestBody.getBytes("utf-8"); os.write(input, 0, input.length); } Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground() after write"); // Read the response try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) { StringBuilder response = new StringBuilder(); String responseLine = null; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground() response.toString() = "+response.toString()); return response.toString(); } } catch (IOException e) { e.printStackTrace(); Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground()# Excep = "+e.getMessage()); } return null; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // Handle the result, e.g., parse the JSON response if (result != null) { // Parse and handle the JSON response here Log.d(MainActivity.LOG_TAG, "LocationAsyncTask(new) = " + result); } } }
两次实现均触发FileNotFoundException,需解决该问题。
解决思路与方案
FileNotFoundException在这里并非真的找不到文件,而是HTTP请求返回4xx/5xx错误码,Android的HttpURLConnection会将这类错误响应判定为"文件不存在"抛出异常。以下是具体排查和修复步骤:
1. 捕获错误响应流,获取真实错误信息
在代码的异常块中添加错误流读取逻辑,直接拿到Google API返回的具体错误原因:
catch (IOException e) { e.printStackTrace(); // 读取API错误响应 if (connection != null) { try { InputStream errorStream = connection.getErrorStream(); if (errorStream != null) { BufferedReader br = new BufferedReader(new InputStreamReader(errorStream, "utf-8")); StringBuilder errorResponse = new StringBuilder(); String line; while ((line = br.readLine()) != null) { errorResponse.append(line.trim()); } Log.d(MainActivity.LOG_TAG, "API错误响应: " + errorResponse.toString()); } } catch (IOException ex) { ex.printStackTrace(); } } Log.d(MainActivity.LOG_TAG, "GeolocationTask# doInBackground()# Excep = "+e.getMessage()); }
日志中的错误响应会直接指出问题,常见原因包括:API_KEY无效、API未启用、请求参数错误、配额耗尽等。
2. 检查API配置核心问题
- 确认API_KEY有效且启用Geolocation API:登录Google Cloud控制台,验证API_KEY正确性,同时在"API和服务"中确认已启用"Geolocation API"。
- 检查API_KEY限制:确保API_KEY没有设置过严的应用/IP限制(比如仅允许特定Android包名,而当前应用包名未添加)。
- 验证请求参数合法性:如果使用模拟参数(如示例中的310/410 MCC/MNC),需确保参数符合目标区域运营商规范,或直接用
considerIp: true仅基于IP定位做测试。
3. 代码层面优化
- 添加Content-Length请求头(可选,避免服务器解析异常):在写入请求体前添加:
connection.setRequestProperty("Content-Length", String.valueOf(requestBody.getBytes("utf-8").length)); - 切换为HttpsURLConnection:Google API仅支持HTTPS,将原代码中的
HttpURLConnection改为HttpsURLConnection:HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - 确保流关闭顺序:现有代码的try-with-resources已正确处理流关闭,无需额外修改,但要避免在流关闭前调用
disconnect()。
4. 先通过外部工具验证API可用性
用Postman或curl直接调用API,确认API_KEY和参数能正常返回结果后,再迁移到Android代码,避免代码与API配置问题混淆。
内容的提问来源于stack exchange,提问作者Amit Yadav
相关产品推荐
相关产品推荐

