Android internal storage mechanism

584 Views Asked by At

I am trying to understand how Android internal storage works. For that I read a few tutorials and a number of posts on StackOverFlow.

Nevertheless things are not all that clear when testing real code.

Here is one problem, the following code is meant to create a directory and a file:

val dirName = "myNewDir"
createDir(dirName)

val fileName = "myNewFile"
writeToFile("Some random text for testing purpose ...",fileName)

val directory = filesDir

val files: Array<File> = directory.listFiles()
println("Files count = "+files.size)

for (f in files) {
    println("Name: "+f.name)
}

This is the code for the two functions createDir() and writeToFile() :

fun createDir(dirName:String): File? {
    return applicationContext.getDir(dirName, MODE_PRIVATE)
} /* End of createDir */


fun writeToFile(dataBufr:String, fileName:String) {
    applicationContext.openFileOutput(fileName, Context.MODE_PRIVATE).use {
            output -> output.write(dataBufr.toByteArray())
    }
} /* End of writeToFile */

And this is what appears in the console when executing the code above:

I/System.out: Files count = 1
I/System.out: Name: myNewFile

My question is: Why is the directory (myNewDir) not created or at list does not appear in the console?

1

There are 1 best solutions below

4
haoxiqiang On

Latest android version, all default dirs will be created in the first open by LoadAPK.java, getDir will get the exists dir.

public File getDir(String name, int mode) {
    checkMode(mode);
    name = "app_" + name;
    File file = makeFilename(getDataDir(), name);
    if (!file.exists()) {
        file.mkdir();
        setFilePermissionsFromMode(file.getPath(), mode,
                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
    }
    return file;
}

In the getDataDir()

@Override
public File getDataDir() {
    if (mPackageInfo != null) {
        File res = null;
        if (isCredentialProtectedStorage()) {
            res = mPackageInfo.getCredentialProtectedDataDirFile();
        } else if (isDeviceProtectedStorage()) {
            res = mPackageInfo.getDeviceProtectedDataDirFile();
        } else {
            res = mPackageInfo.getDataDirFile();
        }

        if (res != null) {
            if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
                Log.wtf(TAG, "Data directory doesn't exist for package " + getPackageName(),
                        new Throwable());
            }
            return res;
        } else {
            throw new RuntimeException(
                    "No data directory found for package " + getPackageName());
        }
    } else {
        throw new RuntimeException(
                "No package details found for package " + getPackageName());
    }
}

In the frameworks/base/core/java/android/app/LoadedApk.java all file will be init by ApplicationInfo.

private void setApplicationInfo(ApplicationInfo aInfo) {
    final int myUid = Process.myUid();
    aInfo = adjustNativeLibraryPaths(aInfo);
    mApplicationInfo = aInfo;
    mAppDir = aInfo.sourceDir;
    mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
    mLegacyOverlayDirs = aInfo.resourceDirs;
    mOverlayPaths = aInfo.overlayPaths;
    mDataDir = aInfo.dataDir;
    mLibDir = aInfo.nativeLibraryDir;
    mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
    mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
    mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);

    mSplitNames = aInfo.splitNames;
    mSplitAppDirs = aInfo.splitSourceDirs;
    mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
    mSplitClassLoaderNames = aInfo.splitClassLoaderNames;

    if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
        mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
    }
}

frameworks/base/core/java/android/os/FileUtils.java

public static @Nullable File newFileOrNull(@Nullable String path) {
    return (path != null) ? new File(path) : null;
}

public static @Nullable File createDir(File baseDir, String name) {
    final File dir = new File(baseDir, name);

    return createDir(dir) ? dir : null;
}

public static boolean createDir(File dir) {
    if (dir.mkdir()) {
        return true;
    }

    if (dir.exists()) {
        return dir.isDirectory();
    }

    return false;
}