Android Studio中出现java.io.FileNotFoundException,浏览器访问却正常
嘿,我之前也踩过类似的坑,给你几个实用的排查方向,一步步来应该能找到问题:
核对请求方法与头部信息
浏览器默认发的是GET请求,而且会自动带上一堆请求头(比如User-Agent、Accept),但你的App代码里可能用了错误的请求方法(比如POST),或者没设置必要的请求头,导致服务器识别不了请求,返回404状态码——而Android的HttpURLConnection会把4xx/5xx这类错误状态码包装成FileNotFoundException,并不是真的文件不存在。
建议:用Chrome开发者工具(F12打开Network面板)查看浏览器请求的头信息,然后在代码里完全复刻这些头,比如:HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 7 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"); connection.setRequestProperty("Accept", "application/json");检查HTTPS兼容性(如果是HTTPS链接)
Nexus 7的系统版本大多比较老(比如Android 6.0甚至更早),而很多现代服务器用的SSL证书加密算法(比如TLS 1.3)是老系统不支持的,这会导致请求失败,同样会抛出FileNotFoundException。
临时测试方法:如果服务器允许,把链接换成HTTP试试能不能正常请求;如果必须用HTTPS,需要在App里配置兼容老系统的SSL套接字工厂(注意生产环境要做好安全校验)。确认网络权限与明文流量设置
如果你用的是HTTP链接,Android 9(API 28)及以上默认禁止明文网络流量,要是你的Nexus 7系统版本在9以上,没配置的话请求会直接失败。
解决:在AndroidManifest.xml的<application>标签里添加android:usesCleartextTraffic="true",同时确保已经声明了网络权限:<uses-permission android:name="android.permission.INTERNET" />排查URL编码问题
你的URL里如果包含特殊字符(比如空格、中文、&符号),浏览器会自动帮你编码,但代码里如果直接拼接这些字符,会导致实际请求的URL和浏览器里的不一样,服务器自然找不到资源。
正确做法:用Uri.Builder来构建URL,自动处理编码:Uri.Builder urlBuilder = new Uri.Builder() .scheme("https") .authority("your-server-domain.com") .appendPath("api") .appendPath("data") .appendQueryParameter("key", "包含特殊字符的参数"); String finalUrl = urlBuilder.build().toString();验证服务器是否限制非浏览器请求
有些服务器会拦截非浏览器的User-Agent,直接返回404,这就刚好符合“浏览器能访问,App不行”的情况。
解决:就像第一点说的,把App的User-Agent改成和浏览器完全一致的,再跑一遍测试。打印实际请求的URL
最后,一定要在代码里把最终发送请求的URL打印出来(用Log.d("Debug", "Request URL: " + finalUrl)),然后复制这个URL到浏览器里访问,看是不是真的返回404。如果浏览器也返回404,那就是你代码里拼接URL的问题;如果浏览器能正常显示,那就是请求方法、头信息或者系统兼容性的问题。
内容的提问来源于stack exchange,提问作者mtdavem

