一、场景
某一天,项目组反馈问题,说文件下载的功能在某些机型上无法使用,下载文件失败。
二、问题分析
首先查看了问题表现,是一台鸿蒙系统的手机,当时手上还有其他事情,只是记了下来,后续分析。
等到实际分析此问题的时候,脑海中有个固有印象,会不会是鸿蒙系统的适配有问题,但是作为工程师,首先就需要排除错误路径,于是找了其他手机来 测试复现问题,发现并不是,自己的测试OPPO手机上也有此问题,无法下载,表现为在Download目录下是一个 临时文件,创建了,但是文件大小为 0 , 当时并没有引起重视,导致后面误入歧途。
随后自己怀疑是不是又还是因为安卓10版本以后的存储分区导致的问题,因为自己这台测试机器已经升级到android 12 版本了,于是找老版本机器,发现小米的老版本手机上确认可以正常下载,但是此时的调试文件已经转为自己的开发环境,而非项目组环境的https路径。
于是继续在存储分区这条路上面分析调试,怀疑代码,导出搜索是否有同类相关问题,
// 指定下载地址 DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); // 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库 request.allowScanningByMediaScanner(); // 设置通知的显示类型,下载进行时和完成后显示通知 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);// 允许在计费流量下下载 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { request.setAllowedOverMetered(true); } // 允许该记录在下载管理界面可见 request.setVisibleInDownloadsUi(true); // 允许漫游时下载 request.setAllowedOverRoaming(true); // 允许下载的网路类型 request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE ); if(TextUtils.isEmpty(fileName)){ ToastUtil.makeTextShowLong(context, "请设置下载文件名称"); return; } request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); final DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE); // 添加一个下载任务 long downloadId = downloadManager.enqueue(request);
就这么几行代码,琢磨来,琢磨去,一直就怀疑这个 Environment.DIRECTORY_DOWNLOADS 是否不能这么设置了,调试了很多遍,后来发现自己的http 环境没有问题, 自己的内网https 也没有问题,但是项目组的下载地址就是不能成功下载,百思不得其解。
最后终于还是怀疑项目组的环境问题,虽然早就知道其实https,但是从网上的资料来看,安卓系统自带的downloadManager 是适配了http和https的不需要额外设置,随后在抓取的一份系统日志中看到了如下信息:
于是找到了问题点了,看来还是https 证书认证的问题,居然忘记这个了,看到网上说的处理方式是忽略认证,例如:
Android网络请求忽略https证书验证 - 简书
但是我这个是调用的系统下载管理接口,非自己调用okhttp, 所以不方便处理,最后还是和项目组确认,其已经有证书,只是接口调用还是用的IP,将其改为域名方式就正常了。
这个坑又浪费了整整一天的时间,分析来,分析去,各种怀疑,其实还是刚开始的思路不对,明明Download 目录下都已经有大小为 0 的文件创建了,怎么可能还是存储分区导致的无法访问目录的问题呢,真的是脑子瓦塔了吧!!!