1010import android .content .Context ;
1111import android .graphics .drawable .Drawable ;
1212import android .net .Uri ;
13- import android .util .DisplayMetrics ;
14- import android .view .WindowManager ;
1513
1614import androidx .annotation .NonNull ;
1715import androidx .annotation .Nullable ;
1816
1917import java .io .File ;
2018import java .util .HashMap ;
2119import java .util .Map ;
22- import java .util .concurrent .ConcurrentHashMap ;
2320
2421import javax .annotation .concurrent .ThreadSafe ;
2522
2623/** Helper class for obtaining information about local images. */
2724@ ThreadSafe
2825public class ResourceDrawableIdHelper {
2926
30- private final Map <String , Integer > mResourceDrawableIdMap ;
27+ private Map <String , Integer > mResourceDrawableIdMap ;
3128
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- };
4129 private static final String LOCAL_RESOURCE_SCHEME = "res" ;
4230 private static volatile ResourceDrawableIdHelper sResourceDrawableIdHelper ;
4331
44- private int densityDpi ;
45-
4632 private ResourceDrawableIdHelper () {
47- mResourceDrawableIdMap = new HashMap <>();
48- mResourceCacheMap = new ConcurrentHashMap <>();
33+ mResourceDrawableIdMap = new HashMap <String , Integer >();
4934 }
5035
5136 public static ResourceDrawableIdHelper getInstance () {
@@ -98,7 +83,7 @@ private String sanitizeResourceDrawableId(@NonNull String name) {
9883 name = sanitizeResourceDrawableId (name );
9984
10085 // 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 );
10287 if (otaFile != null ) {
10388 return Drawable .createFromPath (otaFile .getAbsolutePath ());
10489 }
@@ -115,7 +100,7 @@ public Uri getResourceDrawableUri(Context context, @Nullable String name) {
115100 name = sanitizeResourceDrawableId (name );
116101
117102 // 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 );
119104 if (otaFile != null ) {
120105 return Uri .fromFile (otaFile );
121106 }
@@ -125,127 +110,4 @@ public Uri getResourceDrawableUri(Context context, @Nullable String name) {
125110 ? new Uri .Builder ().scheme (LOCAL_RESOURCE_SCHEME ).path (String .valueOf (resId )).build ()
126111 : Uri .EMPTY ;
127112 }
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- }
251113}
0 commit comments