一、SharedPreferences的使用

  • SharedPreferences用于存放一些类似登录的配置信息
  • 本质上是一个xml文件,是通过类似键值对的方式存放信息
  • 位于程序私有目录中:data/data/[packageName]/shared_ prefs

案例使用操作:

在Activity打开的时候自动填入已保存的账号密码。

android 提示获取存储权限 安卓app获取本地存储数据_android


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

android 提示获取存储权限 安卓app获取本地存储数据_android 提示获取存储权限_02


进入此目录:data/data/[packageName]/shared_ prefs/

android 提示获取存储权限 安卓app获取本地存储数据_java_03


xml文件里保存的就是SharePreference的数据

android 提示获取存储权限 安卓app获取本地存储数据_android_04


Linux文件类型和权限说明:

android 提示获取存储权限 安卓app获取本地存储数据_包名_05


参考此网站:

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中。

android 提示获取存储权限 安卓app获取本地存储数据_包名_06


部分实现代码:

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的设置中,可以选择清除内部文件或内部缓存。

android 提示获取存储权限 安卓app获取本地存储数据_Android_07

3.内部存储与外部储存对比

android 提示获取存储权限 安卓app获取本地存储数据_android_08


开发中获取存储路径的常用方法:

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"/>