• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package io.flutter.view;
6 
7 import android.content.Context;
8 import android.os.AsyncTask;
9 import android.os.Handler;
10 import android.util.Log;
11 
12 import io.flutter.BuildConfig;
13 
14 import java.io.File;
15 import java.io.FilenameFilter;
16 
17 /**
18  * A class to clean up orphaned resource directories after unclean shutdowns.
19  **/
20 class ResourceCleaner {
21     private static final String TAG = "ResourceCleaner";
22     private static final long DELAY_MS = 5000;
23 
24     private static class CleanTask extends AsyncTask<Void, Void, Void> {
25         private final File[] mFilesToDelete;
26 
CleanTask(File[] filesToDelete)27         CleanTask(File[] filesToDelete) {
28             mFilesToDelete = filesToDelete;
29         }
30 
hasFilesToDelete()31         boolean hasFilesToDelete() {
32             return mFilesToDelete != null && mFilesToDelete.length > 0;
33         }
34 
35         @Override
doInBackground(Void... unused)36         protected Void doInBackground(Void... unused) {
37             if (BuildConfig.DEBUG) {
38                 Log.i(TAG, "Cleaning " + mFilesToDelete.length + " resources.");
39             }
40             for (File file : mFilesToDelete) {
41                 if (file.exists()) {
42                     deleteRecursively(file);
43                 }
44             }
45             return null;
46         }
47 
deleteRecursively(File parent)48         private void deleteRecursively(File parent) {
49             if (parent.isDirectory()) {
50                 for (File child : parent.listFiles()) {
51                     deleteRecursively(child);
52                 }
53             }
54             parent.delete();
55         }
56     }
57 
58     private final Context mContext;
59 
ResourceCleaner(Context context)60     ResourceCleaner(Context context) {
61         mContext = context;
62     }
63 
start()64     void start() {
65         File cacheDir = mContext.getCacheDir();
66         if (cacheDir == null) {
67             return;
68         }
69 
70         final CleanTask task = new CleanTask(cacheDir.listFiles(new FilenameFilter() {
71             @Override
72             public boolean accept(File dir, String name) {
73                 boolean result = name.startsWith(ResourcePaths.TEMPORARY_RESOURCE_PREFIX);
74                 return result;
75             }
76         }));
77 
78         if (!task.hasFilesToDelete()) {
79             return;
80         }
81 
82         new Handler().postDelayed(new Runnable() {
83             @Override
84             public void run() {
85                 task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
86             }
87         }, DELAY_MS);
88     }
89 }
90