在Android中,你是不是只会在根目录下存文件?靠着一行代码走天下:
String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
很多人搞不明白Android中的存储路径,我们大概只知道内部存储和外部存储,然而这两个路径究竟在哪里?什么路径需要权限,什么路径不需要权限?Android到底给我们准备了多少路径供我们使用?你能准确的调用这些API吗?
如果你能准确的回答这些问题,那么请忽略本篇帖子
让我们先来说内部存储,这个也比较容易理解
内部存储,位于data/data/包名/路径下
对于设备中每一个安装的 App,系统都会在 data/data 目录下自动创建与之对应的文件夹。这个文件夹用于 App 中的 WebView 缓存页面信息,SharedPreferences 和 SQLiteDatabase 持久化应用相关数据等。
一图胜千言

大家知道Android系统是基于Linux的操作系统,所以文件系统也借鉴了Linux的。data就是系统根目录下的的一个文件夹,而第二个data就是专门让各种App存储内部数据的。
data/data/是为所有App准备的内部存储空间,怎么对这些数据加以区分呢?往下看👇

第二个data展开后会有很多以包名命名的目录,每个包名都对应一个App的内部存储空间,即我们常说的内部存储空间,别的App是断然无法访问到的。图中红框是本篇帖子的示例App的目录。
可以看到,假如我们只是创建了一个App,那么在内部存储空间中(本篇以后所有的内部存储空间都专指App的内部存储),系统默认只给我们创建了一个cache文件夹,这个是让我们用来存放App的缓存数据
现在我们进行下列操作
SharedPreferences test_sp = getSharedPreferences("test_sp", MODE_PRIVATE);
我们再来看,我们的内部存储下有什么目录

可以看到,在上述代码执行后,系统在我们的内部存储中创建了shared_prefs
目录,但是这个目录是空的,并没有创建对应的sp文件
现在我们把代码补全
SharedPreferences test_sp = getSharedPreferences("test_sp", MODE_PRIVATE);
SharedPreferences.Editor edit = test_sp.edit();
edit.putString("test", "test");
edit.commit();
现在再来看👇

终于看到我们熟悉的sp文件了

可以看到,系统会自动在内部存储中创建
databases
目录,而我们创建的test_db.db
文件则位于该目录下接下来我们看看WebView的缓存问题
public class WebActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
WebView webView = new WebView(this);
linearLayout.addView(webView,LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
webView.loadUrl("http://www.baidu.com");
setContentView(linearLayout);
}
}
启动WebActivity
等页面渲染出来以后我们查看内部存储路径中的目录有什么变化

可以看到,系统一次为我们创建了
app_textures
、app_webview
、org.chromium.android_webview
三个文件夹,而这三个文件夹的路径如上图所示,每个文件夹下的内容我们也看不懂,可以确认的是这里面的东西都是跟WebView缓存相关的。需要注意的是
org.chromium.android_webview
这个文件夹是位于cache
目录下的。到目前为止,我们知道了
sp文件、数据库文件、webView的缓存文件
在内部存储中的具体路径,并且这些路径都是由系统创建的,也就是说我们并不能操作该路径,例如,我们无法在databases路径下存放其他文件,也没有办法把数据库文件放到shared_prefs目录下那么,我们就只能在内部存储中存放这三种文件吗?
答案是否定的
现在来调这个API
//这个是Context对象的方法
//返回一个File对象,这个对象的路径是data/data/包名/files/
File filesDir = getFilesDir();
String absolutePath = filesDir.getAbsolutePath();

与其他目录相同,该目录也不会自动创建,只有我们调用了相应的API的时候系统才会为我们创建对应的目录,不管此时该
现在我们在该目录(
files
)下创建两个文件
try {
File filesDir = getFilesDir();
File txtFile = new File(filesDir,"test.txt");
File imgFile = new File(filesDir,"test.jpg");
txtFile.createNewFile();
imgFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
我们看目录中的文件👇

可以看到,files目录以及我们创建的两份文件已经如期在内部存储中了
现在我们来获取内部存储路径下的cache目录
//这个是Context对象的方法
//返回一个File对象,这个对象的路径是data/data/包名/files/
File cacheDir = getCacheDir();
String absolutePath = cacheDir.getAbsolutePath();
注意
File cacheDir = getCacheDir();
与File filesDir = getFilesDir();
有什么区别?
答案是:当手机的内部存储空间比较低的时候,cache文件夹下的文件有可能会被删除。api中同时注明了,你不要指望系统会帮你删除此文件夹,你应该自己设定一个阀值,每次存储的时候检测一下。
在手机的应用管理器中,每个应用都有一个clearData和clearCache
第一个按钮清除的是整个应用的内部存储数据
第二个按钮清除的是cache路径下的数据
一、内部存储的路径在data/data/包名/路径下
二、内部存储路径中的文件是分类存储的,我们无法干涉,除了cache目录,别的目录系统不会自动创建
三、除了files目录,别的目录我们几乎都是无法手动操作的
四、别的App几乎无法访问内部存储中的数据,除了用非法手段或者我们主动暴露
五、内部存储目录下的文件夹及文件会随着app的卸载而被系统自动删除
//在本App的内部存储中创建一个文件,这个文件的路径为data/data/packageName/文件名
//但是在测试的时候发现系统实际创建了一个app_test的文件
File test = getDir("test", MODE_PRIVATE);
//获取本App的内部存储目录,这个路径是data/data/packageName/
//但是这个Api从24开始才有
File dataDir = getDataDir();
//在本App内部存储中创建一个文件
File dirs = new File(dataDir,"test");
if (!dirs.exists()) {
dirs.createNewFile();
}
//获取内部存储的cache目录
File cacheDir = getCacheDir();
//在cacahe目录中创建一个文件
File myCacheFile = new File(cacheDir,"myCachefile");
if (!myCacheFile.exists()) {
myCacheFile.createNewFile();
}
//直接获取内部存储中databases目录下的数据库文件
File databasePath = getDatabasePath("test2.db");
//在databases目录下创建该文件
//ps:感觉不到这个Api存在的意义,因为我们创建数据库文件应该使用SQLiteOpenHelper类
//不过我们可以利用这个方法在databases目录中创建别的文件,但是这样做并不好
if (!databasePath.exists()) {
databasePath.createNewFile();
}
//获取内部存储的根目录,这个路径是/data
File dataDirectory = Environment.getDataDirectory();
//这个目录我们没有操作权限,我都不知道要这个Api干啥
File file = new File(dataDirectory,"datatest");
if (!file.exists()) {
file.createNewFile();
}
到此,Android中的内部存储就全部结束了,相信你应该对内部存储了解的比较透彻了。
网友评论