parseAndroid method

Future<void> parseAndroid(
  1. Socket socket,
  2. Uri uri,
  3. List<String> responseHeaders,
  4. int requestRangeStart,
  5. int requestRangeEnd,
  6. Map<String, String> headers,
)

Parses and responds to range requests on Android.

Handles segmented download and response for large files.

Implementation

Future<void> parseAndroid(
  Socket socket,
  Uri uri,
  List<String> responseHeaders,
  int requestRangeStart,
  int requestRangeEnd,
  Map<String, String> headers,
) async {
  DownloadTask task = DownloadTask(
    uri: uri,
    startRange: 0,
    endRange: 1,
    headers: headers,
  );
  Uint8List? data = await cache(task);
  int contentLength = 0;
  if (data != null) {
    contentLength = int.tryParse(Utf8Codec().decode(data)) ?? 0;
  }
  if (contentLength == 0) {
    contentLength = await head(uri, headers: headers);
    await _cacheContentLength(task, contentLength);
  }

  requestRangeEnd = contentLength - 1;
  responseHeaders.add('content-length: ${contentLength - requestRangeStart}');
  responseHeaders.add(
    'content-range: bytes '
    '$requestRangeStart-$requestRangeEnd/$contentLength',
  );
  await socket.append(responseHeaders.join('\r\n'));

  bool downloading = true;
  int startRange =
      requestRangeStart - (requestRangeStart % Config.segmentSize);
  int endRange = startRange + Config.segmentSize - 1;
  int retry = 3;
  while (downloading) {
    DownloadTask task = DownloadTask(
      uri: uri,
      startRange: startRange,
      endRange: endRange,
      headers: headers,
    );
    logD(
      'Start ${task.url} '
      'Request range:${task.startRange}-${task.endRange}',
    );

    Uint8List? data = await cache(task);
    // if the task has been added, wait for the download to complete
    bool exitUri = VideoProxy.downloadManager.isTaskExit(task);

    if (exitUri) {
      while (data == null) {
        await Future.delayed(const Duration(milliseconds: 100));
        data = await cache(task);
      }
    }
    if (data == null) {
      concurrent(task, headers);
      task.priority += 2;
      data = await download(task);
    }
    if (data == null) {
      retry--;
      if (retry == 0) {
        downloading = false;
        break;
      }
      continue;
    }

    int startIndex = 0;
    int? endIndex;
    if (startRange < requestRangeStart) {
      startIndex = requestRangeStart - startRange;
    }
    if (endRange > requestRangeEnd) {
      endIndex = requestRangeEnd - startRange + 1;
    }
    data = data.sublist(startIndex, endIndex);
    socket.done.then((value) {
      downloading = false;
    }).catchError((e) {
      downloading = false;
    });
    bool success = await socket.append(data);
    if (!success) downloading = false;
    startRange += Config.segmentSize;
    endRange = startRange + Config.segmentSize - 1;
    if (startRange > requestRangeEnd) {
      downloading = false;
    }
  }
}