(#) Hardcoded reference to `/sdcard` !!! WARNING: Hardcoded reference to `/sdcard` This is a warning. Id : `SdCardPath` Summary : Hardcoded reference to `/sdcard` Severity : Warning Category : Correctness Platform : Android Vendor : Android Open Source Project Feedback : https://issuetracker.google.com/issues/new?component=192708 Since : Initial Affects : Kotlin and Java files Editing : This check runs on the fly in the IDE editor See : https://developer.android.com/training/data-storage#filesExternal Implementation : [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/SdCardDetector.kt) Tests : [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java) Copyright Year : 2011 Your code should not reference the `/sdcard` path directly; instead use `Environment.getExternalStorageDirectory().getPath()`. Similarly, do not reference the `/data/data/` path directly; it can vary in multi-user scenarios. Instead, use `Context.getFilesDir().getPath()`. (##) Example Here is an example of lint warnings produced by this check: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~text src/test/pkg/SdCardTest.java:13:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] private static final String SDCARD_TEST_HTML = "/sdcard/test.html"; ------------------- src/test/pkg/SdCardTest.java:14:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] public static final String SDCARD_ROOT = "/sdcard"; --------- src/test/pkg/SdCardTest.java:15:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] public static final String PACKAGES_PATH = "/sdcard/o/packages/"; --------------------- src/test/pkg/SdCardTest.java:16:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] File deviceDir = new File("/sdcard/vr"); ------------ src/test/pkg/SdCardTest.java:20:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] android.os.Debug.startMethodTracing("/sdcard/launcher"); ------------------ src/test/pkg/SdCardTest.java:22:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] if (new File("/sdcard").exists()) { --------- src/test/pkg/SdCardTest.java:24:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] String FilePath = "/sdcard/" + new File("test"); ---------- src/test/pkg/SdCardTest.java:29:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] intent.setDataAndType(Uri.parse("file://sdcard/foo.json"), "application/bar-json"); ------------------------ src/test/pkg/SdCardTest.java:30:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] intent.putExtra("path-filter", "/sdcard(/.+)*"); --------------- src/test/pkg/SdCardTest.java:31:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] intent.putExtra("start-dir", "/sdcard"); --------- src/test/pkg/SdCardTest.java:32:Warning: Do not hardcode "/data/"; use Context.getFilesDir().getPath() instead [SdCardPath] String mypath = "/data/data/foo"; ---------------- src/test/pkg/SdCardTest.java:33:Warning: Do not hardcode "/data/"; use Context.getFilesDir().getPath() instead [SdCardPath] String base = "/data/data/foo.bar/test-profiling"; ----------------------------------- src/test/pkg/SdCardTest.java:34:Warning: Do not hardcode "/sdcard/"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath] String s = "file://sdcard/foo"; ------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is the source file referenced above: `src/test/pkg/SdCardTest.java`: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~java linenumbers package test.pkg; import java.io.File; import android.content.Intent; import android.net.Uri; /** * Ignore comments - create("/sdcard/foo") */ public class SdCardTest { private static final boolean PROFILE_STARTUP = true; private static final String SDCARD_TEST_HTML = "/sdcard/test.html"; public static final String SDCARD_ROOT = "/sdcard"; public static final String PACKAGES_PATH = "/sdcard/o/packages/"; File deviceDir = new File("/sdcard/vr"); public SdCardTest() { if (PROFILE_STARTUP) { android.os.Debug.startMethodTracing("/sdcard/launcher"); } if (new File("/sdcard").exists()) { } String FilePath = "/sdcard/" + new File("test"); System.setProperty("foo.bar", "file://sdcard"); Intent intent = new Intent(Intent.ACTION_PICK); intent.setDataAndType(Uri.parse("file://sdcard/foo.json"), "application/bar-json"); intent.putExtra("path-filter", "/sdcard(/.+)*"); intent.putExtra("start-dir", "/sdcard"); String mypath = "/data/data/foo"; String base = "/data/data/foo.bar/test-profiling"; String s = "file://sdcard/foo"; } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can also visit the [source code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java) for the unit tests for this check to see additional scenarios. The above example was automatically extracted from the first unit test found for this lint check, `SdCardDetector.testBasic`. To report a problem with this extracted sample, visit https://issuetracker.google.com/issues/new?component=192708. (##) Suppressing You can suppress false positives using one of the following mechanisms: * Using a suppression annotation like this on the enclosing element: ```kt // Kotlin @Suppress("SdCardPath") fun method() { problematicStatement() } ``` or ```java // Java @SuppressWarnings("SdCardPath") void method() { problematicStatement(); } ``` * Using a suppression comment like this on the line above: ```kt //noinspection SdCardPath problematicStatement() ``` * Using a special `lint.xml` file in the source tree which turns off the check in that folder and any sub folder. A simple file might look like this: ```xml <?xml version="1.0" encoding="UTF-8"?> <lint> <issue id="SdCardPath" severity="ignore" /> </lint> ``` Instead of `ignore` you can also change the severity here, for example from `error` to `warning`. You can find additional documentation on how to filter issues by path, regular expression and so on [here](https://googlesamples.github.io/android-custom-lint-rules/usage/lintxml.md.html). * In Gradle projects, using the DSL syntax to configure lint. For example, you can use something like ```gradle lintOptions { disable 'SdCardPath' } ``` In Android projects this should be nested inside an `android { }` block. * For manual invocations of `lint`, using the `--ignore` flag: ``` $ lint --ignore SdCardPath ...` ``` * Last, but not least, using baselines, as discussed [here](https://googlesamples.github.io/android-custom-lint-rules/usage/baselines.md.html).