9
9
import android .os .Build .VERSION_CODES ;
10
10
import android .os .Handler ;
11
11
import android .os .Looper ;
12
+ import android .util .Log ;
12
13
import androidx .annotation .NonNull ;
13
14
import com .google .common .util .concurrent .FutureCallback ;
14
15
import com .google .common .util .concurrent .Futures ;
15
16
import com .google .common .util .concurrent .SettableFuture ;
16
17
import com .google .common .util .concurrent .ThreadFactoryBuilder ;
17
18
import io .flutter .embedding .engine .plugins .FlutterPlugin ;
19
+ import io .flutter .plugin .common .BinaryMessenger ;
18
20
import io .flutter .plugin .common .MethodCall ;
19
21
import io .flutter .plugin .common .MethodChannel ;
20
22
import io .flutter .plugin .common .MethodChannel .MethodCallHandler ;
21
23
import io .flutter .plugin .common .MethodChannel .Result ;
24
+ import io .flutter .plugin .common .MethodCodec ;
25
+ import io .flutter .plugin .common .StandardMethodCodec ;
22
26
import io .flutter .util .PathUtils ;
23
27
import java .io .File ;
28
+ import java .lang .reflect .Constructor ;
29
+ import java .lang .reflect .Method ;
24
30
import java .util .ArrayList ;
25
31
import java .util .List ;
26
32
import java .util .concurrent .Callable ;
27
33
import java .util .concurrent .Executor ;
28
34
import java .util .concurrent .Executors ;
29
35
30
36
public class PathProviderPlugin implements FlutterPlugin , MethodCallHandler {
31
-
37
+ static final String TAG = "PathProviderPlugin" ;
32
38
private Context context ;
33
39
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
+ }
41
141
42
142
public PathProviderPlugin () {}
43
143
144
+ private void setup (BinaryMessenger messenger , Context context ) {
145
+ String channelName = "plugins.flutter.io/path_provider" ;
146
+ try {
147
+ Class methodChannelClass = Class .forName ("io.flutter.plugin.common.MethodChannel" );
148
+ Class taskQueueClass = Class .forName ("io.flutter.plugin.common.BinaryMessenger$TaskQueue" );
149
+ Method makeBackgroundTaskQueue = messenger .getClass ().getMethod ("makeBackgroundTaskQueue" );
150
+ Object taskQueue = makeBackgroundTaskQueue .invoke (messenger );
151
+ Constructor <MethodChannel > constructor =
152
+ methodChannelClass .getConstructor (
153
+ BinaryMessenger .class , String .class , MethodCodec .class , taskQueueClass );
154
+ channel =
155
+ constructor .newInstance (messenger , channelName , StandardMethodCodec .INSTANCE , taskQueue );
156
+ impl = new PathProviderBackgroundThread ();
157
+ Log .d (TAG , "use taskqueues" );
158
+ } catch (Exception ex ) {
159
+ channel = new MethodChannel (messenger , channelName );
160
+ impl = new PathProviderPlatformThread ();
161
+ Log .d (TAG , "don't use taskqueues" );
162
+ }
163
+ this .context = context ;
164
+ channel .setMethodCallHandler (this );
165
+ }
166
+
44
167
@ SuppressWarnings ("deprecation" )
45
168
public static void registerWith (io .flutter .plugin .common .PluginRegistry .Registrar registrar ) {
46
169
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 );
170
+ instance .setup (registrar .messenger (), registrar .context ());
50
171
}
51
172
52
173
@ Override
53
174
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 );
175
+ setup (binding .getBinaryMessenger (), binding .getApplicationContext ());
57
176
}
58
177
59
178
@ Override
@@ -62,52 +181,28 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
62
181
channel = null ;
63
182
}
64
183
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
-
89
184
@ Override
90
185
public void onMethodCall (MethodCall call , @ NonNull Result result ) {
91
186
switch (call .method ) {
92
187
case "getTemporaryDirectory" :
93
- executeInBackground (() -> getPathProviderTemporaryDirectory (), result );
188
+ impl . getTemporaryDirectory ( result );
94
189
break ;
95
190
case "getApplicationDocumentsDirectory" :
96
- executeInBackground (() -> getPathProviderApplicationDocumentsDirectory (), result );
191
+ impl . getApplicationDocumentsDirectory ( result );
97
192
break ;
98
193
case "getStorageDirectory" :
99
- executeInBackground (() -> getPathProviderStorageDirectory (), result );
194
+ impl . getStorageDirectory ( result );
100
195
break ;
101
196
case "getExternalCacheDirectories" :
102
- executeInBackground (() -> getPathProviderExternalCacheDirectories (), result );
197
+ impl . getExternalCacheDirectories ( result );
103
198
break ;
104
199
case "getExternalStorageDirectories" :
105
200
final Integer type = call .argument ("type" );
106
201
final String directoryName = StorageDirectoryMapper .androidType (type );
107
- executeInBackground (() -> getPathProviderExternalStorageDirectories ( directoryName ) , result );
202
+ impl . getExternalStorageDirectories ( directoryName , result );
108
203
break ;
109
204
case "getApplicationSupportDirectory" :
110
- executeInBackground (() -> getApplicationSupportDirectory (), result );
205
+ impl . getApplicationSupportDirectory (result );
111
206
break ;
112
207
default :
113
208
result .notImplemented ();
0 commit comments