diff --git a/plugin.xml b/plugin.xml
index 69290c1d..340a7941 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -35,6 +35,8 @@
+
+
diff --git a/src/android/UploadNotification.java b/src/android/UploadNotification.java
index 092ce707..c970a751 100644
--- a/src/android/UploadNotification.java
+++ b/src/android/UploadNotification.java
@@ -14,8 +14,10 @@
import androidx.annotation.IntegerRes;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
+import androidx.work.ForegroundInfo;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
+import android.content.pm.ServiceInfo;
import java.util.Collections;
import java.util.List;
@@ -82,7 +84,7 @@ public static Notification createNotification(NotificationCompat.Builder notific
Notification notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
- return notification;
+ return notification;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@@ -103,7 +105,9 @@ private static NotificationCompat.Builder getUploadNotification(final Context co
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, pendingIntentFlag);
// TODO: click intent open app
- @SuppressLint("ResourceType") NotificationCompat.Builder uploadNotificationBuilder = new NotificationCompat.Builder(context, UploadTask.NOTIFICATION_CHANNEL_ID)
+ @SuppressLint("ResourceType")
+ NotificationCompat.Builder uploadNotificationBuilder = new NotificationCompat.Builder(context,
+ UploadTask.NOTIFICATION_CHANNEL_ID)
.setContentTitle(notificationTitle)
.setTicker(notificationTitle)
.setSmallIcon(notificationIconRes)
@@ -117,4 +121,13 @@ private static NotificationCompat.Builder getUploadNotification(final Context co
return uploadNotificationBuilder;
}
+
+ public ForegroundInfo getForegroundInfo() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ return new ForegroundInfo(notificationId, notificationBuilder.build(),
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
+ }
+
+ return new ForegroundInfo(notificationId, notificationBuilder.build());
+ }
}
diff --git a/src/android/UploadTask.java b/src/android/UploadTask.java
index 9fd1c5c0..f2361fb9 100644
--- a/src/android/UploadTask.java
+++ b/src/android/UploadTask.java
@@ -7,6 +7,7 @@
import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
+import androidx.work.ForegroundInfo;
import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
@@ -155,7 +156,7 @@ public UploadTask(@NonNull Context context, @NonNull WorkerParameters workerPara
@NonNull
@Override
public Result doWork() {
- if(!hasNetworkConnection()) {
+ if (!hasNetworkConnection()) {
return Result.retry();
}
@@ -194,9 +195,16 @@ public Result doWork() {
}
startTime = System.currentTimeMillis();
- // Register me
- uploadForegroundNotification.progress(getId(), 0f);
- handleNotification();
+ // Register me and start foreground service IMMEDIATELY
+ // This must be done before any blocking operations to ensure uploads continue when app is killed
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ uploadForegroundNotification.progress(getId(), 0f);
+ setForegroundAsync(uploadForegroundNotification.getForegroundInfo(getApplicationContext()));
+ } else {
+ // Android 12+: Still need to start foreground service for WorkManager to continue after app kill
+ uploadNotification.updateProgress();
+ setForegroundAsync(uploadNotification.getForegroundInfo());
+ }
// Start call
currentCall = httpClient.newCall(request);
@@ -305,7 +313,10 @@ private void handleProgress(long bytesWritten, long totalBytes) {
}
float percent = (float) bytesWritten / (float) totalBytes;
- UploadForegroundNotification.progress(getId(), percent);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ UploadForegroundNotification.progress(getId(), percent);
+ }
+ // On Android 12+, progress is tracked via WorkManager progress data
Log.i(TAG, "handleProgress: " + getId() + " Progress: " + (int) (percent * 100f));
@@ -395,12 +406,22 @@ private void handleNotification() {
Log.d(TAG, "Upload Notification");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
setForegroundAsync(uploadForegroundNotification.getForegroundInfo(getApplicationContext()));
- } else {
+ } else {
uploadNotification.updateProgress();
}
Log.d(TAG, "Upload Notification Exit");
}
+ @NonNull
+ @Override
+ public ForegroundInfo getForegroundInfo() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ return uploadForegroundNotification.getForegroundInfo(getApplicationContext());
+ }
+
+ return uploadNotification.getForegroundInfo();
+ }
+
private synchronized boolean hasNetworkConnection() {
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if((connectivityManager == null) || (connectivityManager.getActiveNetworkInfo() == null) || (connectivityManager.getActiveNetworkInfo().isConnectedOrConnecting() == false)) {