diff --git a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java index 2514494d..7cf138ff 100644 --- a/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java +++ b/android/src/main/java/vn/hunghd/flutterdownloader/DownloadWorker.java @@ -15,6 +15,7 @@ import android.os.Build; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; @@ -48,6 +49,11 @@ import androidx.work.Worker; import androidx.work.WorkerParameters; +import io.flutter.FlutterInjector; +import io.flutter.embedding.android.FlutterView; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.embedding.engine.dart.DartExecutor; +import io.flutter.embedding.engine.loader.FlutterLoader; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.PluginRegistry; @@ -75,7 +81,7 @@ public class DownloadWorker extends Worker implements MethodChannel.MethodCallHa private static final AtomicBoolean isolateStarted = new AtomicBoolean(false); private static final ArrayDeque isolateQueue = new ArrayDeque<>(); - private static FlutterNativeView backgroundFlutterView; + private static FlutterView backgroundFlutterView; private final Pattern charsetPattern = Pattern.compile("(?i)\\bcharset=\\s*\"?([^\\s;\"]*)"); private final Pattern filenameStarPattern = Pattern.compile("(?i)\\bfilename\\*=([^']+)'([^']*)'\"?([^\"]+)\"?"); @@ -92,6 +98,9 @@ public class DownloadWorker extends Worker implements MethodChannel.MethodCallHa private String msgStarted, msgInProgress, msgCanceled, msgFailed, msgPaused, msgComplete; private long lastCallUpdateNotification = 0; + @Nullable + private static FlutterEngine engine; + public DownloadWorker(@NonNull final Context context, @NonNull WorkerParameters params) { super(context, params); @@ -104,41 +113,36 @@ public void run() { }); } - private void startBackgroundIsolate(Context context) { - synchronized (isolateStarted) { - if (backgroundFlutterView == null) { - SharedPreferences pref = context.getSharedPreferences(FlutterDownloaderPlugin.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE); - long callbackHandle = pref.getLong(FlutterDownloaderPlugin.CALLBACK_DISPATCHER_HANDLE_KEY, 0); - - FlutterMain.startInitialization(context); // Starts initialization of the native system, if already initialized this does nothing - FlutterMain.ensureInitializationComplete(context, null); + private void startEngine(Context context) { + SharedPreferences pref = context.getSharedPreferences(FlutterDownloaderPlugin.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE); + long callbackHandle = pref.getLong(FlutterDownloaderPlugin.CALLBACK_DISPATCHER_HANDLE_KEY, -1L); - FlutterCallbackInformation callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(callbackHandle); - if (callbackInfo == null) { - Log.e(TAG, "Fatal: failed to find callback"); - return; - } + Log.d(TAG, "callbackHandle: " + callbackHandle); - backgroundFlutterView = new FlutterNativeView(getApplicationContext(), true); + if (callbackHandle != -1L && engine == null) { + engine = new FlutterEngine(context); + FlutterLoader flutterLoader = FlutterInjector.instance().flutterLoader(); + flutterLoader.ensureInitializationComplete(context, null); - /// backward compatibility with V1 embedding - if (getApplicationContext() instanceof PluginRegistrantCallback) { - PluginRegistrantCallback pluginRegistrantCallback = (PluginRegistrantCallback) getApplicationContext(); - PluginRegistry registry = backgroundFlutterView.getPluginRegistry(); - pluginRegistrantCallback.registerWith(registry); - } + FlutterCallbackInformation callbackInfo = + FlutterCallbackInformation.lookupCallbackInformation(callbackHandle); + String dartBundlePath = flutterLoader.findAppBundlePath(); - FlutterRunArguments args = new FlutterRunArguments(); - args.bundlePath = FlutterMain.findAppBundlePath(); - args.entrypoint = callbackInfo.callbackName; - args.libraryPath = callbackInfo.callbackLibraryPath; - backgroundFlutterView.runFromBundle(args); - } + backgroundChannel = new MethodChannel(engine.getDartExecutor().getBinaryMessenger(), "vn.hunghd/downloader_background"); + backgroundChannel.setMethodCallHandler(this); + engine + .getDartExecutor() + .executeDartCallback( + new DartExecutor.DartCallback(context.getAssets(), dartBundlePath, callbackInfo)); } + } - backgroundChannel = new MethodChannel(backgroundFlutterView, "vn.hunghd/downloader_background"); - backgroundChannel.setMethodCallHandler(this); + private void startBackgroundIsolate(Context context) { + synchronized (isolateStarted) { + if(!isolateStarted.get()) + startEngine(context); + } } @Override @@ -196,7 +200,7 @@ public Result doWork() { File partialFile = new File(saveFilePath); if (partialFile.exists()) { isResume = true; - log("exists file for "+ filename + "automatic resuming..."); + log("exists file for " + filename + "automatic resuming..."); } try { diff --git a/ios/Classes/FlutterDownloaderPlugin.m b/ios/Classes/FlutterDownloaderPlugin.m index 8da1b116..e567a23f 100644 --- a/ios/Classes/FlutterDownloaderPlugin.m +++ b/ios/Classes/FlutterDownloaderPlugin.m @@ -155,7 +155,7 @@ - (NSURLSession *)wifiSession { return _wifiSession; } -- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url fileName:(NSString *)fileName andSavedDir:(NSString *)savedDir andHeaders:(NSString *)headers wifiOnly:(bool)wifiOnly { +- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url fileName:(NSString *)fileName andSavedDir:(NSString *)savedDir andHeaders:(NSString *)headers allowCellular:(bool)allowCellular { NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; if (headers != nil && [headers length] > 0) { NSError *jsonError; @@ -171,10 +171,10 @@ - (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url fileName:(NSStrin } } NSURLSessionDownloadTask *task; - if (wifiOnly) { - task = [[self wifiSession] downloadTaskWithRequest:request]; - } else { + if (allowCellular) { task = [[self currentSession] downloadTaskWithRequest:request]; + } else { + task = [[self wifiSession] downloadTaskWithRequest:request]; } [task resume]; @@ -594,7 +594,7 @@ - (void)enqueueMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result NSNumber *openFileFromNotification = call.arguments[KEY_OPEN_FILE_FROM_NOTIFICATION]; bool allowCellular = [call.arguments[KEY_ALLOW_CELLULAR] boolValue]; - NSURLSessionDownloadTask *task = [self downloadTaskWithURL:[NSURL URLWithString:urlString] fileName:fileName andSavedDir:savedDir andHeaders:headers wifiOnly:allowCellular]; + NSURLSessionDownloadTask *task = [self downloadTaskWithURL:[NSURL URLWithString:urlString] fileName:fileName andSavedDir:savedDir andHeaders:headers allowCellular:allowCellular]; NSString *taskId = allowCellular ? [self identifierForTask:task ofSession:self.currentSession] : [self identifierForTask:task ofSession:self.wifiSession]; @@ -714,7 +714,7 @@ - (void)retryMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { NSString *headers = taskDict[KEY_HEADERS]; bool allowCellular = (bool) taskDict[KEY_ALLOW_CELLULAR]; - NSURLSessionDownloadTask *newTask = [self downloadTaskWithURL:[NSURL URLWithString:urlString] fileName:fileName andSavedDir:savedDir andHeaders:headers wifiOnly: allowCellular]; + NSURLSessionDownloadTask *newTask = [self downloadTaskWithURL:[NSURL URLWithString:urlString] fileName:fileName andSavedDir:savedDir andHeaders:headers allowCellular:allowCellular]; NSString *newTaskId = [self identifierForTask:newTask ofSession: (allowCellular ? self.currentSession : self.wifiSession)]; // update memory-cache