startDownload method

Future<void> startDownload()

开始或继续下载

Implementation

Future<void> startDownload() async {
  if (!Platform.isAndroid) assert(false, 'Only Android is supported');

  if (_updateInfo == null || _updateInfo!.latestVersion == null) {
    _log('错误: 更新信息或下载链接为空。');
    statusNotifier.value = DownloadStatus.error;
    return;
  }

  if (statusNotifier.value == DownloadStatus.downloading) {
    _log('下载已在进行中。');
    return;
  }

  statusNotifier.value = DownloadStatus.downloading;
  _cancelToken = CancelToken();

  final latestVersion = _updateInfo!.latestVersion!;

  try {
    final tempDir = await getTemporaryDirectory();
    _savePath = '${tempDir.path}/app-v${latestVersion.version}.apk';

    _log('本地路径: $_savePath');
    _log('下载链接: ${latestVersion.downloadUrl}');

    int existingLength = 0;
    final file = File(_savePath!);
    if (await file.exists()) {
      existingLength = await file.length();
      _log('文件已存在,大小: $existingLength bytes. 尝试断点续传。');
    }

    // 检查已下载部分是否等于总大小
    if (latestVersion.apkSize == existingLength) {
      _log('文件已完整下载,直接进入完成状态。');
      await _onDownloadCompleted();
      return;
    }

    await _dio.download(
      latestVersion.downloadUrl,
      _savePath,
      cancelToken: _cancelToken,
      fileAccessMode: FileAccessMode.append,
      onReceiveProgress: (received, total) {
        // 当前已下载的总字节数
        int currentTotal = existingLength + received;

        // 使用已知的文件大小
        int totalSize = latestVersion.apkSize;

        if (totalSize > 0) {
          progressNotifier.value = currentTotal / totalSize;
        }

        _log('下载进度: ${(progressNotifier.value * 100).toStringAsFixed(1)}%');
      },
      options: Options(headers: {'Range': 'bytes=$existingLength-'}),
      deleteOnError: false, // 重要:保留部分下载的文件
    );

    await _onDownloadCompleted();
  } on DioException catch (e) {
    if (CancelToken.isCancel(e)) {
      statusNotifier.value = DownloadStatus.paused;
      _log('下载已暂停。');
    } else {
      statusNotifier.value = DownloadStatus.error;
      _log('下载出错: $e');
      _errorHandler?.call(e);
    }
  } catch (e) {
    statusNotifier.value = DownloadStatus.error;
    _log('下载时发生未知错误: $e');
    _errorHandler?.call(e);
  }
}