Skip to content

Commit

Permalink
Merge branch 'spoonconsulting:master' into update-demo
Browse files Browse the repository at this point in the history
  • Loading branch information
MaximBelov authored Dec 9, 2024
2 parents 3124323 + 774e330 commit 350f5b2
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 29 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
## [4.1.1](https://github.com/spoonconsulting/cordova-plugin-background-upload/compare/4.1.0....4.1.1) (2024-09-23)
## [4.1.2](https://github.com/spoonconsulting/cordova-plugin-background-upload/compare/4.1.1...4.1.2) (2024-11-05)
* **android:** Return upload start and end time in upload response
* **iOS:** Return upload start and end time in upload response

## [4.1.1](https://github.com/spoonconsulting/cordova-plugin-background-upload/compare/4.1.0...4.1.1) (2024-09-23)
* **android:** Update cordova plugin file version to 8.1.0
* **iOS:** Update cordova plugin file version to 8.1.0

## [4.1.0](https://github.com/spoonconsulting/cordova-plugin-background-upload/compare/4.0.10....4.1.0) (2024-04-30)
## [4.1.0](https://github.com/spoonconsulting/cordova-plugin-background-upload/compare/4.0.10...4.1.0) (2024-04-30)
* **android:** REVERTED Add Workers based on the number of parallelUploadsLimit and use a database to continue taking pending uploads in the Workers
* **iOS:** Removed framework tag for pods

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@spoonconsulting/cordova-plugin-background-upload",
"version": "4.1.1",
"version": "4.1.2",
"description": "Cordova plugin for uploading file in the background",
"cordova": {
"id": "@spoonconsulting/cordova-plugin-background-upload",
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="@spoonconsulting/cordova-plugin-background-upload" version="4.1.1">
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="@spoonconsulting/cordova-plugin-background-upload" version="4.1.2">
<name>Cordova Background Upload Plugin</name>
<description>Background Upload plugin for Cordova</description>
<license>ISC</license>
Expand Down
37 changes: 24 additions & 13 deletions src/android/FileTransferBackground.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -81,7 +82,13 @@ private void sendProgress(final String id, int progressPercent) {
}
}

private void sendSuccess(final String id, final String response, int statusCode) {
private void sendSuccess(HashMap<String, Object> uploadData) {
String id = (String) uploadData.get("outputId");
String response = (String) uploadData.get("response");
int statusCode = (int) uploadData.get("statusCode");
long uploadDuration = (long) uploadData.get("uploadDuration");
long finishUploadTime = (long) uploadData.get("finishUploadTime");

if (response != null && !response.isEmpty()) {
logMessage("eventLabel='Uploader onSuccess' uploadId='" + id + "' response='" + response.substring(0, Math.min(2000, response.length() - 1)) + "'");
} else {
Expand All @@ -95,6 +102,8 @@ private void sendSuccess(final String id, final String response, int statusCode)
.put("state", "UPLOADED")
.put("serverResponse", response)
.put("statusCode", statusCode)
.put("uploadDuration", uploadDuration)
.put("finishUploadTime", finishUploadTime)
);
} catch (JSONException e) {
// Can't really happen but just in case
Expand Down Expand Up @@ -401,26 +410,28 @@ private void acknowledgeEvent(String eventId, CallbackContext context) {
* Handle ACK data and send it to the JS.
*/
private void handleAck(final Data ackData) {
// If upload was successful
if (!ackData.getBoolean(UploadTask.KEY_OUTPUT_IS_ERROR, false)) {
// Read response from file if present
String response = null;
if (ackData.getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE) != null) {
response = readFileToStringNoThrow(ackData.getString(UploadTask.KEY_OUTPUT_RESPONSE_FILE));
}

sendSuccess(
ackData.getString(UploadTask.KEY_OUTPUT_ID),
response,
ackData.getInt(UploadTask.KEY_OUTPUT_STATUS_CODE, -1 /* If this is sent, something is really wrong */)
);

long startUploadTime = ackData.getLong(UploadTask.KEY_OUTPUT_UPLOAD_START_TIME, 0);
long finishUploadTime = ackData.getLong(UploadTask.KEY_OUTPUT_UPLOAD_FINISH_TIME, 0);
long uploadDuration = finishUploadTime - startUploadTime;

HashMap<String, Object> uploadData = new HashMap<>();
uploadData.put("outputId", ackData.getString(UploadTask.KEY_OUTPUT_ID));
uploadData.put("response", response);
uploadData.put("statusCode", ackData.getInt(UploadTask.KEY_OUTPUT_STATUS_CODE, -1));
uploadData.put("uploadDuration", uploadDuration);
uploadData.put("finishUploadTime", finishUploadTime);
sendSuccess(uploadData);
} else {
// The upload was a failure
sendError(
ackData.getString(UploadTask.KEY_OUTPUT_ID),
ackData.getString(UploadTask.KEY_OUTPUT_FAILURE_REASON),
ackData.getBoolean(UploadTask.KEY_OUTPUT_FAILURE_CANCELED, false)
ackData.getString(UploadTask.KEY_OUTPUT_ID),
ackData.getString(UploadTask.KEY_OUTPUT_FAILURE_REASON),
ackData.getBoolean(UploadTask.KEY_OUTPUT_FAILURE_CANCELED, false)
);
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/android/UploadTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public final class UploadTask extends Worker {
public static final String KEY_OUTPUT_STATUS_CODE = "output_status_code";
public static final String KEY_OUTPUT_FAILURE_REASON = "output_failure_reason";
public static final String KEY_OUTPUT_FAILURE_CANCELED = "output_failure_canceled";
public static final String KEY_OUTPUT_UPLOAD_START_TIME = "output_upload_start_time";
public static final String KEY_OUTPUT_UPLOAD_FINISH_TIME = "output_upload_finish_time";
// </editor-fold>

private static UploadNotification uploadNotification = null;
Expand All @@ -96,6 +98,8 @@ public void release() { }
private static int concurrency = 1;
private static Semaphore concurrentUploads = new Semaphore(concurrency, true);
private static Mutex concurrencyLock = new Mutex();
long startTime = 0;
long endTime = 0;

public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerParams) {

Expand Down Expand Up @@ -189,6 +193,7 @@ public Result doWork() {
return Result.retry();
}

startTime = System.currentTimeMillis();
// Register me
uploadForegroundNotification.progress(getId(), 0f);
handleNotification();
Expand Down Expand Up @@ -246,6 +251,7 @@ public Result doWork() {
return Result.retry();
}
} finally {
endTime = System.currentTimeMillis();
// Always remove ourselves from the notification
uploadForegroundNotification.done(getId());
}
Expand All @@ -254,7 +260,9 @@ public Result doWork() {
final Data.Builder outputData = new Data.Builder()
.putString(KEY_OUTPUT_ID, id)
.putBoolean(KEY_OUTPUT_IS_ERROR, false)
.putInt(KEY_OUTPUT_STATUS_CODE, (!DEBUG_SKIP_UPLOAD) ? response.code() : 200);
.putInt(KEY_OUTPUT_STATUS_CODE, (!DEBUG_SKIP_UPLOAD) ? response.code() : 200)
.putLong(KEY_OUTPUT_UPLOAD_START_TIME, startTime)
.putLong(KEY_OUTPUT_UPLOAD_FINISH_TIME, endTime);

// Try read the response body, if any
try {
Expand Down
1 change: 1 addition & 0 deletions src/ios/FileUploader.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import "UploadEvent.h"
#import <AFNetworking/AFNetworking.h>
#import <math.h>
NS_ASSUME_NONNULL_BEGIN
@protocol FileUploaderDelegate <NSObject>
@optional
Expand Down
36 changes: 27 additions & 9 deletions src/ios/FileUploader.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "FileUploader.h"
@interface FileUploader()
@property (nonatomic, strong) NSMutableDictionary* responsesData;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSDate *> *uploadStartTimes;
@property (nonatomic, strong) NSMutableDictionary *responsesData;
@property (nonatomic, strong) AFURLSessionManager *manager;
@end

Expand All @@ -20,30 +21,44 @@ -(id)init{
return nil;
[UploadEvent setupStorage];
self.responsesData = [[NSMutableDictionary alloc] init];
self.uploadStartTimes = [[NSMutableDictionary alloc] init];
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[[NSBundle mainBundle] bundleIdentifier]];
configuration.HTTPMaximumConnectionsPerHost = FileUploader.parallelUploadsLimit;
configuration.sessionSendsLaunchEvents = NO;
self.manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
__weak FileUploader *weakSelf = self;
[self.manager setTaskDidCompleteBlock:^(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSError * _Nullable error) {
NSString* uploadId = [NSURLProtocol propertyForKey:kUploadUUIDStrPropertyKey inRequest:task.originalRequest];
NSDate *startTime = weakSelf.uploadStartTimes[uploadId];
NSDate *endUploadTime = [NSDate date];
NSTimeInterval timeInterval = [endUploadTime timeIntervalSince1970];
long long endUploadTimeInMS = (long long)(timeInterval * 1000);
NSTimeInterval duration = [endUploadTime timeIntervalSinceDate:startTime];
NSLog(@"[BackgroundUpload] Task %@ completed with error %@", uploadId, error);
if (!error){
NSData* serverData = weakSelf.responsesData[@(task.taskIdentifier)];
NSString* serverResponse = serverData ? [[NSString alloc] initWithData:serverData encoding:NSUTF8StringEncoding] : @"";
[weakSelf.responsesData removeObjectForKey:@(task.taskIdentifier)];
[weakSelf saveAndSendEvent:@{
@"id" : uploadId,
@"state" : @"UPLOADED",
@"statusCode" : @(((NSHTTPURLResponse *)task.response).statusCode),
@"serverResponse" : serverResponse
}];
NSMutableDictionary *event = [@{
@"id" : uploadId,
@"state" : @"UPLOADED",
@"statusCode" : @(((NSHTTPURLResponse *)task.response).statusCode),
@"serverResponse" : serverResponse
} mutableCopy];

if (!isnan(duration)) {
event[@"uploadDuration"] = @(duration * 1000);
event[@"finishUploadTime"] = @(endUploadTimeInMS);
}

[weakSelf saveAndSendEvent:event];
} else {
[weakSelf.responsesData removeObjectForKey:@(task.taskIdentifier)];
[weakSelf saveAndSendEvent:@{
@"id" : uploadId,
@"state" : @"FAILED",
@"error" : error.localizedDescription,
@"errorCode" : @(error.code)
@"errorCode" : @(error.code),
}];
}
}];
Expand All @@ -60,7 +75,7 @@ -(id)init{
}

-(void)saveAndSendEvent:(NSDictionary*)data{
UploadEvent*event = [UploadEvent create:data];
UploadEvent* event = [UploadEvent create:data];
[self sendEvent:[event dataRepresentation]];
}

Expand Down Expand Up @@ -89,6 +104,9 @@ -(void)addUpload:(NSDictionary *)payload completionHandler:(void (^)(NSError* er
completionHandler:^(NSError *error, NSMutableURLRequest *request) {
if (error)
return handler(error);

weakSelf.uploadStartTimes[payload[@"id"]] = [NSDate date];

__block double lastProgressTimeStamp = 0;

[[weakSelf.manager uploadTaskWithRequest:request
Expand Down

0 comments on commit 350f5b2

Please sign in to comment.