99import android .os .Build .VERSION_CODES ;
1010import android .os .Handler ;
1111import android .os .Looper ;
12+ import android .util .Log ;
1213import androidx .annotation .NonNull ;
1314import com .google .common .util .concurrent .FutureCallback ;
1415import com .google .common .util .concurrent .Futures ;
1516import com .google .common .util .concurrent .SettableFuture ;
1617import com .google .common .util .concurrent .ThreadFactoryBuilder ;
1718import io .flutter .embedding .engine .plugins .FlutterPlugin ;
19+ import io .flutter .plugin .common .BinaryMessenger ;
1820import io .flutter .plugin .common .MethodCall ;
1921import io .flutter .plugin .common .MethodChannel ;
2022import io .flutter .plugin .common .MethodChannel .MethodCallHandler ;
2123import io .flutter .plugin .common .MethodChannel .Result ;
24+ import io .flutter .plugin .common .MethodCodec ;
25+ import io .flutter .plugin .common .StandardMethodCodec ;
2226import io .flutter .util .PathUtils ;
2327import java .io .File ;
28+ import java .lang .reflect .Constructor ;
29+ import java .lang .reflect .Method ;
2430import java .util .ArrayList ;
2531import java .util .List ;
2632import java .util .concurrent .Callable ;
2733import java .util .concurrent .Executor ;
2834import java .util .concurrent .Executors ;
2935
3036public 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 ();
0 commit comments