10
10
import android .content .Context ;
11
11
import android .graphics .drawable .Drawable ;
12
12
import android .net .Uri ;
13
- import android .util .DisplayMetrics ;
14
- import android .view .WindowManager ;
15
13
16
14
import androidx .annotation .NonNull ;
17
15
import androidx .annotation .Nullable ;
18
16
19
17
import java .io .File ;
20
18
import java .util .HashMap ;
21
19
import java .util .Map ;
22
- import java .util .concurrent .ConcurrentHashMap ;
23
20
24
21
import javax .annotation .concurrent .ThreadSafe ;
25
22
@@ -29,23 +26,11 @@ public class ResourceDrawableIdHelper {
29
26
30
27
private final Map <String , Integer > mResourceDrawableIdMap ;
31
28
32
- private final ConcurrentHashMap <String , String > mResourceCacheMap ;
33
-
34
- private static final String CACHE_DRAWABLE_DIRECTORY_SCHEME = "otas/app/src/main/res" ;
35
- private static final String [] RESOURCE_EXTENSIONS = {
36
- "xml" ,
37
- "png" ,
38
- "svg" ,
39
- "jpg"
40
- };
41
29
private static final String LOCAL_RESOURCE_SCHEME = "res" ;
42
30
private static volatile ResourceDrawableIdHelper sResourceDrawableIdHelper ;
43
31
44
- private int densityDpi ;
45
-
46
32
private ResourceDrawableIdHelper () {
47
33
mResourceDrawableIdMap = new HashMap <>();
48
- mResourceCacheMap = new ConcurrentHashMap <>();
49
34
}
50
35
51
36
public static ResourceDrawableIdHelper getInstance () {
@@ -98,7 +83,7 @@ private String sanitizeResourceDrawableId(@NonNull String name) {
98
83
name = sanitizeResourceDrawableId (name );
99
84
100
85
// Checks to see if we have an ota version of the file, otherwise default to normal behavior.
101
- File otaFile = getDrawableFileFromCache (context , name );
86
+ File otaFile = ResourceDrawableUtils . getDrawableFileFromCache (context , name );
102
87
if (otaFile != null ) {
103
88
return Drawable .createFromPath (otaFile .getAbsolutePath ());
104
89
}
@@ -115,7 +100,7 @@ public Uri getResourceDrawableUri(Context context, @Nullable String name) {
115
100
name = sanitizeResourceDrawableId (name );
116
101
117
102
// Checks to see if we have an ota version of the file, otherwise default to normal behavior.
118
- File otaFile = getDrawableFileFromCache (context , name );
103
+ File otaFile = ResourceDrawableUtils . getDrawableFileFromCache (context , name );
119
104
if (otaFile != null ) {
120
105
return Uri .fromFile (otaFile );
121
106
}
@@ -125,127 +110,4 @@ public Uri getResourceDrawableUri(Context context, @Nullable String name) {
125
110
? new Uri .Builder ().scheme (LOCAL_RESOURCE_SCHEME ).path (String .valueOf (resId )).build ()
126
111
: Uri .EMPTY ;
127
112
}
128
-
129
- /**
130
- * Checks the cache to see if there is a drawable file downloaded via OTA.
131
- */
132
- @ Nullable
133
- private File getDrawableFileFromCache (Context context , @ Nullable String fileName ) {
134
- if (fileName == null || fileName .isEmpty ()) {
135
- return null ;
136
- }
137
-
138
- String cacheMapFileName = mResourceCacheMap .get (fileName );
139
-
140
- // Check the cache to see if we've already looked up the file before.
141
- if (cacheMapFileName != null ) {
142
- return new File (cacheMapFileName );
143
- }
144
-
145
- File file = null ;
146
- int densityDpi = getDensityDpi (context );
147
- PhoneDensity [] phoneDensities = PhoneDensity .values ();
148
-
149
- // We start from the medium dpi and go up.
150
- for (PhoneDensity phoneDensity : phoneDensities ) {
151
- String drawableFileParent = String .format ("drawable-%s" , phoneDensity .fileParentSuffix );
152
- String mipMapFileParent = String .format ("mipmap-%s" , phoneDensity .fileParentSuffix );
153
-
154
- String [] parentFileNames = { drawableFileParent , mipMapFileParent };
155
-
156
- File resourceFile = checkFiles (context , parentFileNames , fileName );
157
-
158
- if (resourceFile != null ) {
159
- file = resourceFile ;
160
- }
161
-
162
- // If we've found a file at our current dpi level, return it.
163
- // Otherwise continue looking up the chain.
164
- if (densityDpi <= phoneDensity .density ) {
165
- if (file != null ) {
166
- mResourceCacheMap .put (fileName , file .getAbsolutePath ());
167
- return file ;
168
- }
169
- }
170
- }
171
-
172
- // As a last resort, check the drawable/raw folders.
173
- String [] parentFileNames = { "drawable" , "raw" };
174
- file = checkFiles (context , parentFileNames , fileName );
175
-
176
- if (file != null ) {
177
- mResourceCacheMap .put (fileName , file .getAbsolutePath ());
178
- }
179
-
180
- return file ;
181
- }
182
-
183
- /**
184
- * Given a list of files, check if any of them exist.
185
- * Checks multiple extension types.
186
- */
187
- private File checkFiles (Context context , String [] parentFileNames , String fileName ) {
188
- for (String parentFileName : parentFileNames ) {
189
- for (String extension : RESOURCE_EXTENSIONS ) {
190
- File file = getFile (context , parentFileName , fileName , extension );
191
- if (file .exists ()) {
192
- return file ;
193
- }
194
- }
195
- }
196
-
197
- return null ;
198
- }
199
-
200
- /**
201
- * Returns a file object with the correct directory extensions.
202
- */
203
- private File getFile (Context context , String parentFileName , String fileName , String extension ) {
204
- String fullDrawableFileName = String .format (
205
- "%s/%s/%s.%s" ,
206
- CACHE_DRAWABLE_DIRECTORY_SCHEME ,
207
- parentFileName ,
208
- fileName ,
209
- extension
210
- );
211
-
212
- return new File (context .getCacheDir (), fullDrawableFileName );
213
- }
214
-
215
- /**
216
- * Returns the density dpi for the device.
217
- */
218
- private int getDensityDpi (Context context ) {
219
- if (densityDpi == 0 ) {
220
- DisplayMetrics metrics = new DisplayMetrics ();
221
-
222
- WindowManager windowManager = (WindowManager ) context .getSystemService (Context .WINDOW_SERVICE );
223
- windowManager .getDefaultDisplay ().getMetrics (metrics );
224
-
225
- densityDpi = metrics .densityDpi ;
226
- }
227
-
228
- return densityDpi ;
229
- }
230
-
231
- enum PhoneDensity {
232
- Medium (DisplayMetrics .DENSITY_MEDIUM , "mdpi" ),
233
- High (DisplayMetrics .DENSITY_HIGH , "hdpi" ),
234
- XHigh (DisplayMetrics .DENSITY_XHIGH , "xhdpi" ),
235
- XXHigh (DisplayMetrics .DENSITY_XXHIGH , "xxhdpi" ),
236
- XXXHigh (DisplayMetrics .DENSITY_XXXHIGH , "xxxhdpi" );
237
-
238
- int density ;
239
-
240
- @ NonNull
241
- String fileParentSuffix ;
242
-
243
- PhoneDensity (
244
- int density ,
245
- @ NonNull String fileParentSuffix
246
- ) {
247
- this .density = density ;
248
- this .fileParentSuffix = fileParentSuffix ;
249
- }
250
- }
251
113
}
0 commit comments