ShadowEnvironment.java revision df6ac64d05f00add83341e8f538072f0efcb85dc
1package org.robolectric.shadows;
2
3import java.io.File;
4import java.io.IOException;
5import java.nio.file.Files;
6import java.nio.file.Path;
7import java.util.Map;
8import java.util.HashMap;
9import android.os.Environment;
10import org.robolectric.annotation.Resetter;
11import org.robolectric.annotation.Implements;
12import org.robolectric.annotation.Implementation;
13import org.robolectric.util.TempDirectory;
14
15/**
16 * Shadow for {@link android.os.Environment}.
17 */
18@Implements(Environment.class)
19public class ShadowEnvironment {
20  private static String externalStorageState = Environment.MEDIA_REMOVED;
21  private static final Map<File, Boolean> STORAGE_EMULATED = new HashMap<>();
22  private static final Map<File, Boolean> STORAGE_REMOVABLE = new HashMap<>();
23
24  static Path EXTERNAL_CACHE_DIR;
25  static Path EXTERNAL_FILES_DIR;
26
27  @Implementation
28  public static String getExternalStorageState() {
29    return externalStorageState;
30  }
31
32  /**
33   * Non-Android accessor. Sets the return value of {@link #getExternalStorageState()}.
34   *
35   * @param externalStorageState Value to return from {@link #getExternalStorageState()}.
36   */
37  public static void setExternalStorageState(String externalStorageState) {
38    ShadowEnvironment.externalStorageState = externalStorageState;
39  }
40
41  @Implementation
42  public static File getExternalStorageDirectory() {
43    if (!exists(EXTERNAL_CACHE_DIR)) EXTERNAL_CACHE_DIR = TempDirectory.create();
44    return EXTERNAL_CACHE_DIR.toFile();
45  }
46
47  @Implementation
48  public static File getExternalStoragePublicDirectory(String type) {
49    if (!exists(EXTERNAL_FILES_DIR)) EXTERNAL_FILES_DIR = TempDirectory.create();
50    if (type == null) return EXTERNAL_FILES_DIR.toFile();
51    Path path = EXTERNAL_FILES_DIR.resolve(type);
52    try {
53      Files.createDirectories(path);
54    } catch (IOException e) {
55      throw new RuntimeException(e);
56    }
57    return path.toFile();
58  }
59
60  @Resetter
61  public static void reset() {
62    TempDirectory.destroy(EXTERNAL_CACHE_DIR);
63    TempDirectory.destroy(EXTERNAL_FILES_DIR);
64
65    EXTERNAL_CACHE_DIR = null;
66    EXTERNAL_FILES_DIR = null;
67
68    STORAGE_EMULATED.clear();
69    STORAGE_REMOVABLE.clear();
70  }
71
72  private static boolean exists(Path path) {
73    return path != null && Files.exists(path);
74  }
75
76  @Implementation
77  public static boolean isExternalStorageRemovable() {
78    final Boolean exists = STORAGE_REMOVABLE.get(getExternalStorageDirectory());
79    return exists != null ? exists : false;
80  }
81
82#if ($api >= 19)
83  @Implementation
84  public static String getStorageState(File path) {
85    return externalStorageState;
86  }
87#end
88
89#if ($api >= 21)
90  @Implementation
91  public static String getExternalStorageState(File path) {
92    return externalStorageState;
93  }
94
95  @Implementation
96  public static boolean isExternalStorageRemovable(File path) {
97    final Boolean exists = STORAGE_REMOVABLE.get(path);
98    return exists != null ? exists : false;
99  }
100
101  @Implementation
102  public static boolean isExternalStorageEmulated(File path) {
103    final Boolean emulated = STORAGE_EMULATED.get(path);
104    return emulated != null ? emulated : false;
105  }
106
107  /**
108   * Non-Android accessor. Sets the "isRemovable" flag of a particular file.
109   *
110   * @param file Target file.
111   * @param isRemovable True if the filesystem is removable.
112   */
113  public static void setExternalStorageRemovable(File file, boolean isRemovable) {
114    STORAGE_REMOVABLE.put(file, isRemovable);
115  }
116
117  /**
118   * Non-Android accessor. Sets the "isEmulated" flag of a particular file.
119   *
120   * @param file Target file.
121   * @param isEmulated True if the filesystem is emulated.
122   */
123  public static void setExternalStorageEmulated(File file, boolean isEmulated) {
124    STORAGE_EMULATED.put(file, isEmulated);
125  }
126#end
127}
128