HarmonyNote.TOP鸿蒙开发笔记

记录使用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文件都下载到正常文件大小了。