一、SharedPreferences的使用
- SharedPreferences用于存放一些类似登录的配置信息
- 本质上是一个xml文件,是通过类似键值对的方式存放信息
- 位于程序私有目录中:data/data/[packageName]/shared_ prefs
案例使用操作:
在Activity打开的时候自动填入已保存的账号密码。
1.储存信息到SharePreference
findViewById(R.id.sign).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取输入框到内容
String account = accEdt.getText().toString();
String password = pwdEdt.getText().toString();
//简单验证账号密码
if (account.equals("admin") && password.equals("123")) {
//储存信息到SharePreference
//1.获取SharePreference对象(参数1:文件名 参数2:模式)
// MODE_ PRIVATE:私有方式存储,其他应用无法访问
// MODE_ WORLD_ READABLE:可被其他应用读取
// MODE_ WORLD_ WRITEABLE:可被其他应用写入
SharedPreferences share = getSharedPreferences("myTest", MODE_PRIVATE);
//2.获取Editor对象
SharedPreferences.Editor editor = share.edit();
//3.储存信息
editor.putString("account", account);
editor.putString("password", password);
//4.指定提交操作
editor.commit();
//editor.clear(); 清除SharedPreferences对象里到数据
Toast.makeText(ShareActivity.this,"登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ShareActivity.this,"账号或密码错误", Toast.LENGTH_SHORT).show();
}
}
});
2.读取SharePreference中的数据
//SharePreference的读取
//1.获取SharePreference对象(参数1:文件名 参数2:模式)
SharedPreferences share = getSharedPreferences("myTest", MODE_PRIVATE);
//2.根据key获取内容(参数1:key 参数2:当对应key不存在时,返回参数2的内容作为默认值)
String accStr = share.getString("account", "");
String pwdStr = share.getString("password", "");
//设置保存好的账号密码
accEdt.setText(accStr);
pwdEdt.setText(pwdStr);
3.查找创建的SharedPreferences的文件
在工具栏中选择:View -> Tool Windows -> Device File Explorer
进入此目录:data/data/[packageName]/shared_ prefs/
xml文件里保存的就是SharePreference的数据
Linux文件类型和权限说明:
参考此网站:
https://www.runoob.com/linux/linux-file-attr-permission.html
二、内部和外部到文件存储
1.外部存储 ExternalStorage
- storage 或者 mnt 文件夹
- 公有目录( DCIM、 DOWNLOAD等)
- 私有目录( Android/data/ 应用包名)
获取外部存储的目录的方法:
Environment.getExternalStorageDirectory();
获取目录 SDCard/
当手机中没有安装外置SD卡时,它返回的是内置SD卡目录。使用Log打印信息可以发现,Environment.getExternalStorageDirectory() 打印出来的目录是/storage/emulated/0,但使用Device File Explorer查看发现,内容实际是在/sdcard/里面。(使用的是AS自带的模拟器)
Android SDK 29中,getExternalStorageDirector()方法已经废弃,推荐使用以下两种方法:
Context.getExternalFilesDir(String type);
获取目录 SDCard/Android/data/包名/files/
Context.getExternalCacheDir();
获取目录 SDCard/Android/data/包名/cache/
案例使用操作:
将EditView的内容保存到内存里,然后读取到TextView中。
部分实现代码:
public void click(View view){
//获取SD卡的路径 + 测试文件名称
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/test.txt";
Log.e("TAG", path);
//判断是否装载了SD卡
//if(Environment.getExternalStorageState().equals("mounted"))
switch (view.getId()){
case R.id.save_btn:
File f = new File(path);
try {
if (!f.exists()) {
f.createNewFile();
}
//文件输出流参数2为true,追加文件内容
FileOutputStream fos = new FileOutputStream(path, true);
String str = infoEdt.getText().toString();
fos.write(str.getBytes());
fos.close();
} catch (IOException e){
e.printStackTrace();
}
break;
case R.id.read_btn:
try {
FileInputStream fis = new FileInputStream(path);
//读1024个字节用于测试
byte[] b = new byte[1024];
int len = fis.read(b);
String str2 = new String(b, 0, len);
fis.close();
txt.setText(str2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
Android 6.0以上版本需要动态请求权限:
在AndroidManifest.xml中设置代码
<manifest xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions"/>
设置完之后还需要让用户同意申请该权限
protected void onCreate(Bundle savedInstanceState) {
int permisson = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permisson!=PackageManager.PERMISSION_GRANTED) {
//动态去申请权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
//在申请权限时会回调该方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 1){
//stub code
}
}
2.内部存储 InternalStorage
获取内部存储的目录的方法:
Context.getFileDir();
获取目录 /data/data/包名/files/
Context.getCacheDir();
获取目录 /data/data/包名/cache
部分实现代码:
File f = new File(getFilesDir(), "getFilesDirs.txt");
FileOutputStream fos = new FileOutputStream(f);
fos.write(edt.getText().toString().getBytes());
fos.close();
手动清除App的储存文件:
在App的设置中,可以选择清除内部文件或内部缓存。
3.内部存储与外部储存对比
开发中获取存储路径的常用方法:
public static String getFilePath(Context context, String dir) {
String directoryPath = "";
//判断SD卡是否可用
if (MEDIA MOUNTED.equals(Environment.getExternalStorageState())) {
directoryPath = context.getExternalFilesDir(dir).getAbsolutePath();
//directoryPath =context.getExternalCacheDir(.getAbsolutePath();
} else {
//没内存卡就使用机身内存
directoryPath = context.getFilesDir0 + File.separator + dir;
//directoryPath = context.getCacheDir0 + File.separator + dir;
}
File file = new File(directoryPath);
//判断文件目录是否存在
if (!file.existst()) {
file.mkdirs();
}
return directoryPath;
}
4.FileNotFound异常解决方案
- 检查下错误提示中的路径是否存在
- 检查权限是否处理正确
- 确认设备是否有SDCard
if (Environment.getExternalStorageState().equals(Environment.MEDIA.MOUNTED))
if (Environment.getExternalStorageState().equals(“mounted”)) - 如果设备是Android Q版本,则需要在AndroidManifest.xml中声明:
<application android:requestLegacyExternalStorage="true"/>