Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit fbf02ac

Browse files
committed
[path_provider] started supporting background platform channels
1 parent c85fa03 commit fbf02ac

File tree

3 files changed

+147
-45
lines changed

3 files changed

+147
-45
lines changed

packages/path_provider/path_provider/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.0.6
2+
3+
* Added support for Background Platform Channels on Android when it is
4+
available.
5+
16
## 2.0.5
27

38
* Update minimum Flutter SDK to 2.5 and iOS deployment target to 9.0.

packages/path_provider/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java

Lines changed: 141 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,172 @@
99
import android.os.Build.VERSION_CODES;
1010
import android.os.Handler;
1111
import android.os.Looper;
12+
import android.util.Log;
1213
import androidx.annotation.NonNull;
1314
import com.google.common.util.concurrent.FutureCallback;
1415
import com.google.common.util.concurrent.Futures;
1516
import com.google.common.util.concurrent.SettableFuture;
1617
import com.google.common.util.concurrent.ThreadFactoryBuilder;
1718
import io.flutter.embedding.engine.plugins.FlutterPlugin;
19+
import io.flutter.plugin.common.BinaryMessenger;
1820
import io.flutter.plugin.common.MethodCall;
1921
import io.flutter.plugin.common.MethodChannel;
2022
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
2123
import io.flutter.plugin.common.MethodChannel.Result;
24+
import io.flutter.plugin.common.MethodCodec;
25+
import io.flutter.plugin.common.StandardMethodCodec;
2226
import io.flutter.util.PathUtils;
2327
import java.io.File;
28+
import java.lang.reflect.Constructor;
29+
import java.lang.reflect.Method;
2430
import java.util.ArrayList;
2531
import java.util.List;
2632
import java.util.concurrent.Callable;
2733
import java.util.concurrent.Executor;
2834
import java.util.concurrent.Executors;
2935

3036
public class PathProviderPlugin implements FlutterPlugin, MethodCallHandler {
31-
37+
static final String TAG = "PathProviderPlugin";
3238
private Context context;
3339
private MethodChannel channel;
34-
private final Executor uiThreadExecutor = new UiThreadExecutor();
35-
private final Executor executor =
36-
Executors.newSingleThreadExecutor(
37-
new ThreadFactoryBuilder()
38-
.setNameFormat("path-provider-background-%d")
39-
.setPriority(Thread.NORM_PRIORITY)
40-
.build());
40+
private PathProviderImpl impl;
41+
42+
private interface PathProviderImpl {
43+
void getTemporaryDirectory(@NonNull Result result);
44+
45+
void getApplicationDocumentsDirectory(@NonNull Result result);
46+
47+
void getStorageDirectory(@NonNull Result result);
48+
49+
void getExternalCacheDirectories(@NonNull Result result);
50+
51+
void getExternalStorageDirectories(@NonNull String directoryName, @NonNull Result result);
52+
53+
void getApplicationSupportDirectory(@NonNull Result result);
54+
}
55+
56+
private class PathProviderPlatformThread implements PathProviderImpl {
57+
private final Executor uiThreadExecutor = new UiThreadExecutor();
58+
private final Executor executor =
59+
Executors.newSingleThreadExecutor(
60+
new ThreadFactoryBuilder()
61+
.setNameFormat("path-provider-background-%d")
62+
.setPriority(Thread.NORM_PRIORITY)
63+
.build());
64+
65+
public void getTemporaryDirectory(@NonNull Result result) {
66+
executeInBackground(() -> getPathProviderTemporaryDirectory(), result);
67+
}
68+
69+
public void getApplicationDocumentsDirectory(@NonNull Result result) {
70+
executeInBackground(() -> getPathProviderApplicationDocumentsDirectory(), result);
71+
}
72+
73+
public void getStorageDirectory(@NonNull Result result) {
74+
executeInBackground(() -> getPathProviderStorageDirectory(), result);
75+
}
76+
77+
public void getExternalCacheDirectories(@NonNull Result result) {
78+
executeInBackground(() -> getPathProviderExternalCacheDirectories(), result);
79+
}
80+
81+
public void getExternalStorageDirectories(
82+
@NonNull String directoryName, @NonNull Result result) {
83+
executeInBackground(() -> getPathProviderExternalStorageDirectories(directoryName), result);
84+
}
85+
86+
public void getApplicationSupportDirectory(@NonNull Result result) {
87+
executeInBackground(() -> PathProviderPlugin.this.getApplicationSupportDirectory(), result);
88+
}
89+
90+
private <T> void executeInBackground(Callable<T> task, Result result) {
91+
final SettableFuture<T> future = SettableFuture.create();
92+
Futures.addCallback(
93+
future,
94+
new FutureCallback<T>() {
95+
public void onSuccess(T answer) {
96+
result.success(answer);
97+
}
98+
99+
public void onFailure(Throwable t) {
100+
result.error(t.getClass().getName(), t.getMessage(), null);
101+
}
102+
},
103+
uiThreadExecutor);
104+
executor.execute(
105+
() -> {
106+
try {
107+
future.set(task.call());
108+
} catch (Throwable t) {
109+
future.setException(t);
110+
}
111+
});
112+
}
113+
}
114+
115+
private class PathProviderBackgroundThread implements PathProviderImpl {
116+
public void getTemporaryDirectory(@NonNull Result result) {
117+
result.success(getPathProviderTemporaryDirectory());
118+
}
119+
120+
public void getApplicationDocumentsDirectory(@NonNull Result result) {
121+
result.success(getPathProviderApplicationDocumentsDirectory());
122+
}
123+
124+
public void getStorageDirectory(@NonNull Result result) {
125+
result.success(getPathProviderStorageDirectory());
126+
}
127+
128+
public void getExternalCacheDirectories(@NonNull Result result) {
129+
result.success(getPathProviderExternalCacheDirectories());
130+
}
131+
132+
public void getExternalStorageDirectories(
133+
@NonNull String directoryName, @NonNull Result result) {
134+
result.success(getPathProviderExternalStorageDirectories(directoryName));
135+
}
136+
137+
public void getApplicationSupportDirectory(@NonNull Result result) {
138+
result.success(PathProviderPlugin.this.getApplicationSupportDirectory());
139+
}
140+
}
41141

42142
public PathProviderPlugin() {}
43143

144+
private void setup(BinaryMessenger messenger, Context context) {
145+
String channelName = "plugins.flutter.io/path_provider";
146+
// TODO(gaaclarke): Remove reflection guard when https://github.com/flutter/engine/pull/29147
147+
// becomes available on the stable branch.
148+
try {
149+
Class methodChannelClass = Class.forName("io.flutter.plugin.common.MethodChannel");
150+
Class taskQueueClass = Class.forName("io.flutter.plugin.common.BinaryMessenger$TaskQueue");
151+
Method makeBackgroundTaskQueue = messenger.getClass().getMethod("makeBackgroundTaskQueue");
152+
Object taskQueue = makeBackgroundTaskQueue.invoke(messenger);
153+
Constructor<MethodChannel> constructor =
154+
methodChannelClass.getConstructor(
155+
BinaryMessenger.class, String.class, MethodCodec.class, taskQueueClass);
156+
channel =
157+
constructor.newInstance(messenger, channelName, StandardMethodCodec.INSTANCE, taskQueue);
158+
impl = new PathProviderBackgroundThread();
159+
Log.d(TAG, "Use TaskQueues.");
160+
} catch (Exception ex) {
161+
channel = new MethodChannel(messenger, channelName);
162+
impl = new PathProviderPlatformThread();
163+
Log.d(TAG, "Don't use TaskQueues.");
164+
}
165+
this.context = context;
166+
channel.setMethodCallHandler(this);
167+
}
168+
44169
@SuppressWarnings("deprecation")
45170
public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) {
46171
PathProviderPlugin instance = new PathProviderPlugin();
47-
instance.channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/path_provider");
48-
instance.context = registrar.context();
49-
instance.channel.setMethodCallHandler(instance);
172+
instance.setup(registrar.messenger(), registrar.context());
50173
}
51174

52175
@Override
53176
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
54-
channel = new MethodChannel(binding.getBinaryMessenger(), "plugins.flutter.io/path_provider");
55-
context = binding.getApplicationContext();
56-
channel.setMethodCallHandler(this);
177+
setup(binding.getBinaryMessenger(), binding.getApplicationContext());
57178
}
58179

59180
@Override
@@ -62,52 +183,28 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
62183
channel = null;
63184
}
64185

65-
private <T> void executeInBackground(Callable<T> task, Result result) {
66-
final SettableFuture<T> future = SettableFuture.create();
67-
Futures.addCallback(
68-
future,
69-
new FutureCallback<T>() {
70-
public void onSuccess(T answer) {
71-
result.success(answer);
72-
}
73-
74-
public void onFailure(Throwable t) {
75-
result.error(t.getClass().getName(), t.getMessage(), null);
76-
}
77-
},
78-
uiThreadExecutor);
79-
executor.execute(
80-
() -> {
81-
try {
82-
future.set(task.call());
83-
} catch (Throwable t) {
84-
future.setException(t);
85-
}
86-
});
87-
}
88-
89186
@Override
90187
public void onMethodCall(MethodCall call, @NonNull Result result) {
91188
switch (call.method) {
92189
case "getTemporaryDirectory":
93-
executeInBackground(() -> getPathProviderTemporaryDirectory(), result);
190+
impl.getTemporaryDirectory(result);
94191
break;
95192
case "getApplicationDocumentsDirectory":
96-
executeInBackground(() -> getPathProviderApplicationDocumentsDirectory(), result);
193+
impl.getApplicationDocumentsDirectory(result);
97194
break;
98195
case "getStorageDirectory":
99-
executeInBackground(() -> getPathProviderStorageDirectory(), result);
196+
impl.getStorageDirectory(result);
100197
break;
101198
case "getExternalCacheDirectories":
102-
executeInBackground(() -> getPathProviderExternalCacheDirectories(), result);
199+
impl.getExternalCacheDirectories(result);
103200
break;
104201
case "getExternalStorageDirectories":
105202
final Integer type = call.argument("type");
106203
final String directoryName = StorageDirectoryMapper.androidType(type);
107-
executeInBackground(() -> getPathProviderExternalStorageDirectories(directoryName), result);
204+
impl.getExternalStorageDirectories(directoryName, result);
108205
break;
109206
case "getApplicationSupportDirectory":
110-
executeInBackground(() -> getApplicationSupportDirectory(), result);
207+
impl.getApplicationSupportDirectory(result);
111208
break;
112209
default:
113210
result.notImplemented();

packages/path_provider/path_provider/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: path_provider
22
description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories.
33
repository: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
5-
version: 2.0.5
5+
version: 2.0.6
66

77
environment:
88
sdk: ">=2.14.0 <3.0.0"

0 commit comments

Comments
 (0)