fix: working downloads

This commit is contained in:
Fredrik Burmester
2025-10-03 07:07:28 +02:00
parent 8d59065c49
commit c88de0250f
11 changed files with 890 additions and 590 deletions

View File

@@ -3,6 +3,7 @@
"version": "1.0.0",
"platforms": ["ios"],
"ios": {
"modules": ["BackgroundDownloaderModule"],
"appDelegateSubscribers": ["BackgroundDownloaderAppDelegate"]
}
}

View File

@@ -1,4 +1,4 @@
import { EventEmitter, type Subscription } from "expo-modules-core";
import type { Subscription } from "expo-modules-core";
import type {
ActiveDownload,
DownloadCompleteEvent,
@@ -8,8 +8,6 @@ import type {
} from "./src/BackgroundDownloader.types";
import BackgroundDownloaderModule from "./src/BackgroundDownloaderModule";
const emitter = new EventEmitter(BackgroundDownloaderModule);
export interface BackgroundDownloader {
startDownload(url: string, destinationPath?: string): Promise<number>;
cancelDownload(taskId: number): void;
@@ -51,25 +49,34 @@ const BackgroundDownloader: BackgroundDownloader = {
addProgressListener(
listener: (event: DownloadProgressEvent) => void,
): Subscription {
return emitter.addListener("onDownloadProgress", listener);
return BackgroundDownloaderModule.addListener(
"onDownloadProgress",
listener,
);
},
addCompleteListener(
listener: (event: DownloadCompleteEvent) => void,
): Subscription {
return emitter.addListener("onDownloadComplete", listener);
return BackgroundDownloaderModule.addListener(
"onDownloadComplete",
listener,
);
},
addErrorListener(
listener: (event: DownloadErrorEvent) => void,
): Subscription {
return emitter.addListener("onDownloadError", listener);
return BackgroundDownloaderModule.addListener("onDownloadError", listener);
},
addStartedListener(
listener: (event: DownloadStartedEvent) => void,
): Subscription {
return emitter.addListener("onDownloadStarted", listener);
return BackgroundDownloaderModule.addListener(
"onDownloadStarted",
listener,
);
},
};

View File

@@ -28,6 +28,8 @@ class DownloadSessionDelegate: NSObject, URLSessionDownloadDelegate {
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64
) {
let progress = totalBytesExpectedToWrite > 0 ? Double(totalBytesWritten) / Double(totalBytesExpectedToWrite) : 0.0
print("[BackgroundDownloader] Progress callback: taskId=\(downloadTask.taskIdentifier), written=\(totalBytesWritten), total=\(totalBytesExpectedToWrite), progress=\(progress)")
module?.handleProgress(
taskId: downloadTask.taskIdentifier,
bytesWritten: totalBytesWritten,
@@ -40,6 +42,7 @@ class DownloadSessionDelegate: NSObject, URLSessionDownloadDelegate {
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL
) {
print("[BackgroundDownloader] Download finished callback: taskId=\(downloadTask.taskIdentifier)")
module?.handleDownloadComplete(
taskId: downloadTask.taskIdentifier,
location: location,
@@ -52,7 +55,15 @@ class DownloadSessionDelegate: NSObject, URLSessionDownloadDelegate {
task: URLSessionTask,
didCompleteWithError error: Error?
) {
print("[BackgroundDownloader] Task completed: taskId=\(task.taskIdentifier), error=\(String(describing: error))")
if let httpResponse = task.response as? HTTPURLResponse {
print("[BackgroundDownloader] HTTP Status: \(httpResponse.statusCode)")
print("[BackgroundDownloader] Content-Length: \(httpResponse.expectedContentLength)")
}
if let error = error {
print("[BackgroundDownloader] Task error: \(error.localizedDescription)")
module?.handleError(taskId: task.taskIdentifier, error: error)
}
}
@@ -100,9 +111,17 @@ public class BackgroundDownloaderModule: Module {
throw DownloadError.downloadFailed
}
let task = session.downloadTask(with: url)
// Create a URLRequest to ensure proper handling
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.timeoutInterval = 300
let task = session.downloadTask(with: request)
let taskId = task.taskIdentifier
print("[BackgroundDownloader] Starting download: taskId=\(taskId), url=\(urlString)")
print("[BackgroundDownloader] Destination: \(destinationPath ?? "default")")
self.downloadTasks[taskId] = DownloadTaskInfo(
url: urlString,
destinationPath: destinationPath
@@ -110,11 +129,27 @@ public class BackgroundDownloaderModule: Module {
task.resume()
print("[BackgroundDownloader] Task resumed with state: \(self.taskStateString(task.state))")
print("[BackgroundDownloader] Sending started event")
self.sendEvent("onDownloadStarted", [
"taskId": taskId,
"url": urlString
])
// Check task state after a brief delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
session.getAllTasks { tasks in
if let downloadTask = tasks.first(where: { $0.taskIdentifier == taskId }) {
print("[BackgroundDownloader] Task state after 0.5s: \(self.taskStateString(downloadTask.state))")
if let response = downloadTask.response as? HTTPURLResponse {
print("[BackgroundDownloader] Response status: \(response.statusCode)")
print("[BackgroundDownloader] Expected content length: \(response.expectedContentLength)")
}
}
}
}
return taskId
}
@@ -158,6 +193,8 @@ public class BackgroundDownloaderModule: Module {
}
private func initializeSession() {
print("[BackgroundDownloader] Initializing URLSession")
let config = URLSessionConfiguration.background(
withIdentifier: "com.fredrikburmester.streamyfin.backgrounddownloader"
)
@@ -171,6 +208,8 @@ public class BackgroundDownloaderModule: Module {
delegate: self.sessionDelegate,
delegateQueue: nil
)
print("[BackgroundDownloader] URLSession initialized with delegate: \(String(describing: self.sessionDelegate))")
}
private func taskStateString(_ state: URLSessionTask.State) -> String {
@@ -194,6 +233,8 @@ public class BackgroundDownloaderModule: Module {
? Double(bytesWritten) / Double(totalBytes)
: 0.0
print("[BackgroundDownloader] Sending progress event: taskId=\(taskId), progress=\(progress)")
self.sendEvent("onDownloadProgress", [
"taskId": taskId,
"bytesWritten": bytesWritten,