REST API在Java中正常运行但Android上报FileNotFound问题
我之前也碰到过类似的情况,这个异常在Android的HTTP请求里很容易误导人——它通常不是真的找不到API端点,而是API返回了非200的HTTP状态码(比如401未授权、404路径错误等),Android的HttpsURLConnection会把这类错误转换成FileNotFoundException抛出。下面是一步步的排查和解决方法:
1. 先捕获真实的HTTP响应码和错误信息
这是最关键的一步,能帮你定位到底是认证、路径还是其他问题。修改你的代码,先获取响应码,再处理输入/错误流:
// 发起API请求到MySportsFeeds以获取NFL赛事赛程 try { URL url = new URL("https://api.mysportsfeeds.com/v2.1/pull/nfl/current/games.json"); // 指定UTF-8字符集编码,避免Android与Java SE的编码差异 String encoding = java.util.Base64.getEncoder().encodeToString("[I_PUT_THE_CORRECT_API_KEY_HERE]:MYSPORTSFEEDS".getBytes(java.nio.charset.StandardCharsets.UTF_8)); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setDoOutput(true); connection.setRequestProperty("Authorization", "Basic " + encoding); // 先获取响应码,判断请求是否成功 int responseCode = connection.getResponseCode(); if (responseCode == HttpsURLConnection.HTTP_OK) { InputStream content = connection.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(content)); String line; while ((line = in.readLine()) != null) { System.out.println(line); } } else { // 读取错误流,获取API返回的具体错误信息 InputStream errorStream = connection.getErrorStream(); BufferedReader errorIn = new BufferedReader(new InputStreamReader(errorStream)); String errorLine; StringBuilder errorMsg = new StringBuilder(); while ((errorLine = errorIn.readLine()) != null) { errorMsg.append(errorLine); } // 用Log打印错误,方便在Logcat中查看 android.util.Log.e("MSF_API_ERROR", "Response Code: " + responseCode + ", Error Details: " + errorMsg.toString()); } } catch (Exception ex) { android.util.Log.e("MSF_API_EXCEPTION", "Exception: " + ex.toString()); }
运行后查看Logcat里的错误信息,比如如果是401 Unauthorized,说明认证有问题;如果是404 Not Found,可能是赛季参数错误。
2. 排查常见的坑点
(1)认证编码的字符集问题
确保Base64编码时使用UTF-8字符集,Android和Java SE的Base64实现可能在默认字符集上有差异,指定StandardCharsets.UTF_8能避免这个问题。另外可以打印出encoding的值,和Eclipse里运行的Java代码生成的编码字符串对比,看是否一致。
(2)Android 9+的网络限制
如果你的App的targetSdkVersion >= 28,默认会限制一些网络行为。虽然你调用的是HTTPS,但某些情况下(比如API证书有问题、使用了代理)也可能触发异常。可以在AndroidManifest.xml的<application>标签里添加:
android:usesCleartextTraffic="true"
先试试是否能解决问题,之后再根据实际情况调整。
(3)网络请求不能在主线程
Android从API 11开始,禁止在主线程执行网络请求,否则会抛出NetworkOnMainThreadException。虽然你当前的异常是FileNotFoundException,但如果你的代码是在Activity的onCreate或主线程其他方法里执行的,先把它移到后台线程:
- 可以用
AsyncTask(适合旧版本) - 或者用Kotlin Coroutines(推荐)
- 或者
Thread+Handler的方式
(4)API端点的赛季参数是否有效
你调用的是nfl/current/games.json,这里的current指的是当前活跃赛季。如果处于休赛期,current可能没有对应的赛季数据,API会返回404。可以换成具体的赛季ID,比如2024-2025试试,看是否能正常返回数据。
3. 验证API端点的正确性
可以先在Postman或浏览器里手动调用这个API(添加Basic Auth头,用户名是你的API key,密码是MYSPORTSFEEDS),确认API本身能返回正常数据。如果手动调用也失败,那问题就出在API密钥或端点上,和Android代码无关。
内容的提问来源于stack exchange,提问作者Adam Lee

