记录使用request.downloadFile实现下载过程中的坑
今天开发过程中要实现一个点击下载的功能,很自然地就想到使用@kit.BasicServicesKit组件包提供的request.downloadFile功能,根据官方文档配置好下载参数,示例代码如下:
request.downloadFile(AppContextInstance.context, { url: downloadUrl, filePath: downloadPath, // 0(NET_MOBILE/仅限蜂窝网络)| 1(NET_WIFI/仅限Wi-Fi)| 2(NET_ALL/任何网络(默认值)) networkType: 1, // 核心作用:设置下载任务在系统通知栏中显示的标题 // 用户感知:用户通过系统通知中心看到的下载任务名称 // 系统集成:该标题也会出现在下载管理器的任务列表中 title: '下载到沙箱', // false:明确禁止计量网络下载(蜂窝网络下自动暂停下载)| true:强制允许计量网络下载(即使用户开启"省流量模式"也强制下载) enableMetered: false, // true:强制允许漫游下载(即使设备检测到处于国际漫游状态,下载任务仍继续执行) // false:禁止漫游下载(默认/检测到漫游时自动暂停下载) enableRoaming: false, // 是否后台下载:true=应用切后台或锁屏后下载继续执行/false=应用进入后台时自动暂停下载(默认值) background: true }, (err, downloadTask) => { if (err) { console.error('Download failed: ' + JSON.stringify(err)); return; } // 监听下载进度 downloadTask.on('progress', (receivedSize, totalSize) => { console.debug(`Download Progress: ${receivedSize}/${totalSize} bytes`); }); // 下载完成 downloadTask.on('complete', () => { console.debug('Download saved to: ' + downloadPath); }); });
然后在页面视图点击事件中调用封装的下载方法,按期望来讲就是一个很简单的下载功能,要下载的资源文件检查了确实存在,点一下应该就能下载到指定位置。然后当我部署到真机上进行测试,却发现沙箱目录创建了待下载的文件,但却是0KB,而且下载任务的监听事件都没有触发,也没有报错出来。只能去Log面板查找跟下载相关的日志,发现了如下一些日志记录:
E StepResultSet[GetValue]: ret is 27394061 E AbsResultSet[GetRow]: Get(0, task_id)->ret 27394061 E StepResultSet[GetValue]: ret is 27394061 E AbsResultSet[GetRow]: Get(0, group_id)->ret 27394061 E RdbStoreImpl[AfterOpen]: GetRdbService failed, err: 27394049, storeName: download_sqlite.db. E [download_task_manager.cpp(148)]RemoveTask abort, task is not exist, taskId E GetAdditionalInfo com.android.providers.downloads error E GetAppProvisionInfoSync fail -n com.android.providers.downloads -u 100 ret:17700001 E GetAdditionalInfo com.android.providers.downloads.ui error E GetSpecifiedDistributionType failed -n com.android.providers.downloads.ui ret:17700001 E [UpdateBeanHelper]:com.android.providers.downloads.ui getSpecifiedDistributionType error:{"code":17700001}
经过与AI交流才知道原来鸿蒙系统会将下载任务存到本地数据库中,如果因为没有网络等原因导致下载未能完成,会等到网络条件具备时再次执行这些下载任务。至于我前面在点击事件里下载未能成功下载,恰恰是因为关闭了手机WIFI但是却没有发觉。6月的天气下午已经是很热了,排查了半天下载异常没找到原因后面就去休息了。等休息好了才发现是因为关闭了WIFI没有网络的原因。为了杜绝以后再次因为网络连接原因导致浪费测试时间及影响心情,我决定封装一个检测网络连接状态的方法。首先就是要注册网络监听事件,代码如下:
// 创建网络管理器 const netManager = connection.createNetConnection() // GET_NETWORK_INFO netManager.register((error: BusinessError) => { showDebugV2(error) }); // 订阅网络可用事件 netManager.on('netAvailable', (res: connection.NetHandle) => { AppStorageUtil.updateKeyVal('isNetworkAvailable', true) }); // 订阅网络丢失事件 netManager.on('netLost', (res: connection.NetHandle) => { AppStorageUtil.updateKeyVal('isNetworkAvailable', false) }); netManager.on('netUnavailable', () => { AppStorageUtil.updateKeyVal('isNetworkAvailable', false) });
还可以即时检测网络是否可连接,示例代码如下:
// 检查是否可连接网络 public static checkIsNetworkAvailable() { const boolResult: boolean = connection.hasDefaultNetSync() return boolResult; }
如果要检测某个具体的接口域名是否可用,还可以基于@kit.NetworkKit包下的http模块封装一个ping方法。总之完善了检测网络是否可连接的逻辑之后,打开WIFI连接,之前几次重复部署产生的几个下载任务竟然重新执行下载了,因为我发现沙箱目录之前产生的0KB文件都下载到正常文件大小了。