ShadowEnvironment.java revision d5191fc46f3997c3dedfea14680ec4f114124619
1cfb3d242306311ce27ec51bf511764377c173a7cKiran Ryali + Christian Williamspackage org.robolectric.shadows; 2e9d4b241c1e9b9225da1424698942c358ef22162Chris Heisterkamp & Joe Moore 343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglassimport java.io.File; 4c472650a6c989986a7276fcde482af7cdeba065aAlexander Blomimport java.io.IOException; 5c472650a6c989986a7276fcde482af7cdeba065aAlexander Blomimport java.nio.file.Files; 6c472650a6c989986a7276fcde482af7cdeba065aAlexander Blomimport java.nio.file.Path; 743a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglassimport java.util.Map; 843a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglassimport java.util.HashMap; 9e9d4b241c1e9b9225da1424698942c358ef22162Chris Heisterkamp & Joe Mooreimport android.os.Environment; 1043a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglassimport org.robolectric.annotation.Resetter; 11402e2422266b331d25374a90339711ed332952c0Christian Williamsimport org.robolectric.annotation.Implements; 1243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglassimport org.robolectric.annotation.Implementation; 13c472650a6c989986a7276fcde482af7cdeba065aAlexander Blomimport org.robolectric.util.TempDirectory; 149e11c64f01e0d72a3f469d5866b695c778387c26Christian Williams & Dimitris Couchell 15d5191fc46f3997c3dedfea14680ec4f114124619Christian Williamsimport static android.os.Build.VERSION_CODES; 16d5191fc46f3997c3dedfea14680ec4f114124619Christian Williamsimport static android.os.Build.VERSION_CODES.KITKAT; 17d5191fc46f3997c3dedfea14680ec4f114124619Christian Williamsimport static android.os.Build.VERSION_CODES.LOLLIPOP; 18d5191fc46f3997c3dedfea14680ec4f114124619Christian Williams 1913e343bf0b12d99043d3cdced94e86fb284e48d4Erich Douglass/** 2013e343bf0b12d99043d3cdced94e86fb284e48d4Erich Douglass * Shadow for {@link android.os.Environment}. 2113e343bf0b12d99043d3cdced94e86fb284e48d4Erich Douglass */ 22e9d4b241c1e9b9225da1424698942c358ef22162Chris Heisterkamp & Joe Moore@Implements(Environment.class) 23e9d4b241c1e9b9225da1424698942c358ef22162Chris Heisterkamp & Joe Moorepublic class ShadowEnvironment { 2443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass private static String externalStorageState = Environment.MEDIA_REMOVED; 2543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass private static final Map<File, Boolean> STORAGE_EMULATED = new HashMap<>(); 2643a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass private static final Map<File, Boolean> STORAGE_REMOVABLE = new HashMap<>(); 2729a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams 28c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom static Path EXTERNAL_CACHE_DIR; 29c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom static Path EXTERNAL_FILES_DIR; 30c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom 3129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams @Implementation 3229a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams public static String getExternalStorageState() { 3329a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams return externalStorageState; 3429a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams } 3529a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams 3643a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass /** 3743a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * Non-Android accessor. Sets the return value of {@link #getExternalStorageState()}. 3843a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * 3943a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * @param externalStorageState Value to return from {@link #getExternalStorageState()}. 4043a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass */ 4143a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static void setExternalStorageState(String externalStorageState) { 4243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass ShadowEnvironment.externalStorageState = externalStorageState; 4343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass } 4443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass 4543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass @Implementation 4643a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static File getExternalStorageDirectory() { 47c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom if (!exists(EXTERNAL_CACHE_DIR)) EXTERNAL_CACHE_DIR = TempDirectory.create(); 48c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom return EXTERNAL_CACHE_DIR.toFile(); 4943a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass } 5043a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass 5143a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass @Implementation 5243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static File getExternalStoragePublicDirectory(String type) { 53c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom if (!exists(EXTERNAL_FILES_DIR)) EXTERNAL_FILES_DIR = TempDirectory.create(); 54c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom if (type == null) return EXTERNAL_FILES_DIR.toFile(); 55c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom Path path = EXTERNAL_FILES_DIR.resolve(type); 56c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom try { 57f00fb170b988ce99dcc1ff5190e17c0d35b67234Alexander Blom Files.createDirectories(path); 58c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom } catch (IOException e) { 59c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom throw new RuntimeException(e); 60c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom } 61c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom return path.toFile(); 6243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass } 6343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass 6443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass @Resetter 6543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static void reset() { 66c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom TempDirectory.destroy(EXTERNAL_CACHE_DIR); 67c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom TempDirectory.destroy(EXTERNAL_FILES_DIR); 68c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom 69c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom EXTERNAL_CACHE_DIR = null; 70c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom EXTERNAL_FILES_DIR = null; 71c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom 7243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass STORAGE_EMULATED.clear(); 7343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass STORAGE_REMOVABLE.clear(); 7443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass } 7543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass 76c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom private static boolean exists(Path path) { 77c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom return path != null && Files.exists(path); 78c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom } 79c472650a6c989986a7276fcde482af7cdeba065aAlexander Blom 80df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish @Implementation 81df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish public static boolean isExternalStorageRemovable() { 82df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish final Boolean exists = STORAGE_REMOVABLE.get(getExternalStorageDirectory()); 83df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish return exists != null ? exists : false; 84df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish } 85df6ac64d05f00add83341e8f538072f0efcb85dcJonathan Gerrish 86d5191fc46f3997c3dedfea14680ec4f114124619Christian Williams @Implementation(minSdk = KITKAT) 87ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish public static String getStorageState(File path) { 88ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish return externalStorageState; 89ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish } 90ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish 91d5191fc46f3997c3dedfea14680ec4f114124619Christian Williams @Implementation(minSdk = LOLLIPOP) 92ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish public static String getExternalStorageState(File path) { 93ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish return externalStorageState; 94ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish } 95ef61bd4a7e62b3e1623ac7d8735232f1d629d6dfJonathan Gerrish 96d5191fc46f3997c3dedfea14680ec4f114124619Christian Williams @Implementation(minSdk = LOLLIPOP) 9743a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static boolean isExternalStorageRemovable(File path) { 9843a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass final Boolean exists = STORAGE_REMOVABLE.get(path); 9943a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass return exists != null ? exists : false; 10029a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams } 10129a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams 102d5191fc46f3997c3dedfea14680ec4f114124619Christian Williams @Implementation(minSdk = LOLLIPOP) 10343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static boolean isExternalStorageEmulated(File path) { 10443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass final Boolean emulated = STORAGE_EMULATED.get(path); 10543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass return emulated != null ? emulated : false; 10629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams } 1079fbd34e2cfc7b9b2be99ae8e27afa623cc61ae72Dimitris Couchell 10843a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass /** 10943a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * Non-Android accessor. Sets the "isRemovable" flag of a particular file. 11043a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * 11143a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * @param file Target file. 11243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * @param isRemovable True if the filesystem is removable. 11343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass */ 11443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static void setExternalStorageRemovable(File file, boolean isRemovable) { 11543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass STORAGE_REMOVABLE.put(file, isRemovable); 11643a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass } 11743a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass 11843a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass /** 11943a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * Non-Android accessor. Sets the "isEmulated" flag of a particular file. 12043a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * 12143a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * @param file Target file. 12243a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass * @param isEmulated True if the filesystem is emulated. 12343a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass */ 12443a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass public static void setExternalStorageEmulated(File file, boolean isEmulated) { 12543a35d3623cad51c47f5b07c41d71665e891b6a3Erich Douglass STORAGE_EMULATED.put(file, isEmulated); 12629a8359eaef1ee9f40c967d3c4b5c1117c8c2a43Christian Williams } 127e9d4b241c1e9b9225da1424698942c358ef22162Chris Heisterkamp & Joe Moore} 128