本地数据存储
Android常用数据存储
- 1. SharedPreferences存储数据
- 2. 文件存储(内部,外部)
- 3. SQLite数据库存储
- 4. ContentProvider存储数据
- 5. 网络存储数据
一、SharedPreferences存储数据
SharedPreferences
•用于存放一些类似登录的配置信息
• 本质上是一个xml文件,是通过类似键值对的方式存放信息
• 位于程序私有目录中,即data/data/[packageName]/shared_prefs
特点:
* (1)以键值对的形式保存到data/data/应用程序包名/shared_prefs目录的XXX.xml文件中
* (2)目前支持的数据类型有String int float boolean long
* (3)不支持自定义的Object
* (4)通常用来存储App上的用户配置信息.如:是否震动,是否打开背景音乐 小游戏积分 用户账号密码信息
SharedPreferences操作模式
-
MODE_APPEND: 追加方式存储
-
MODE_PRIVATE: 私有方式存储,其他应用无法访问
-
MODE_WORLD_READABLE: 可被其他应用读取
-
MODE_WORLD_WRITEABLE:可被其他应用写入
案例实现:
存储信息到sharedPreference中
SharedPreferences share = getSharedPreferences("myshare", MODE_PRIVATE);
//2.获取Editor对象
SharedPreferences.Editor editor = share.edit();
//3.存储信息
editor.putString("account", accountStr);
editor.putString("pwd", pwdStr);
//4.指定提交操作
editor.commit();
读取SharedPreference中的信息
/**
* 自动读取SharedPreference的数据
*/
//1获取Sharedpreference对象
SharedPreferences share=getSharedPreferences("myshare",MODE_PRIVATE);
//2根据key获取内容(参数1:key,参数2:当对应key不存在时返回参数2 的内容作为默认值)
String accStr=share.getString("account","");
String pwdStr=share.getString("pwd","");
//让控件显示sharedpreference的信息
account.setText(accStr);
pwd.setText(pwdStr);
完整案例:
public class ShareActivity extends AppCompatActivity {
private EditText account;
private EditText pwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share);
account = findViewById(R.id.account);
pwd = findViewById(R.id.pwd);
/**
* 自动读取SharedPreference的数据
*/
//1获取Sharedpreference对象
SharedPreferences share=getSharedPreferences("myshare",MODE_PRIVATE);
//2根据key获取内容(参数1:key,参数2:当对应key不存在时返回参数2 的内容作为默认值)
String accStr=share.getString("account","");
String pwdStr=share.getString("pwd","");
//让控件显示sharedpreference的信息
account.setText(accStr);
pwd.setText(pwdStr);
/**
* 存储数据到sharedpreference
*/
findViewById(R.id.login_bt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//1获取两个输入框的内容
String accountStr=account.getText().toString();
String pwdStr=pwd.getText().toString();
//2.验证
//2.1验证成功,存储信息到sharepreference
//1.获取sharedpreference对象(参数1:文件名称,参数2:操作模式)
if(accountStr.equals("admin")&&pwdStr.equals("123")) {
SharedPreferences share = getSharedPreferences("myshare", MODE_PRIVATE);
//2.获取Editor对象
SharedPreferences.Editor editor = share.edit();
//3.存储信息
editor.putString("account", accountStr);
editor.putString("pwd", pwdStr);
//4.指定提交操作
editor.commit();
Toast.makeText(ShareActivity.this, "验证成功", Toast.LENGTH_SHORT).show();
}
//2.2验证失败,提示用户
else
Toast.makeText(ShareActivity.this,"验证失败",Toast.LENGTH_SHORT).show();
}
});
}
}
位于程序私有目录中,即data/data/[packageName]/shared_prefs/myshare.xml
外部存储ExternalStorage
内存:设备实际的容量
内部存储:文件存储在内部存储中,只能被该应用使用如:SharedPreference
* Internal Storage特点:
* 1.内部存储总是可用的
* 2.内部存储的文件默认只能被当前应用程序访问,它是私有的
* 3.如果App卸载,内部存储文件也会被删除
* 4.如果文件只提供给当前的应用程序访问,那么放到内部存储中比较合适
* 5.内部存储器的读取速度最快且内部存储空间十分珍贵,开发中需要合理使用
*
外部存储ExternalStorage的特点
* 1.外部存储不见得总是可用的: 例如:SD卡被移除了
* 2.外部存储是全局可见的,存放到外部存储中的文件可以被当前设备中所有能够操作该文件的app访问
* 3.为了更好的管理外部存储,Android系统进行了更细致的划分:公共的外部存储和私有的外部存储,当app卸载的时候
* 公共的外部存储中的文件不会被删除,私有外部存储的文件会被删除
* 4.如果你当前文件需要分享给其它的app访问或者使用,文件需要长久保存,文件比较大,或者文件的安全性不做具体要求时,可以考虑使用外部存储
- storage或者mnt文件夹
- Environment.getExternalStorageDirectory() //获取外部存储的文件目录
- 公有目录(DCIM、DOWNLOAD等)//可以被其他应用访问
- 私有目录(Android/data/应用包名)//随应用卸载而卸载
外部存储的动态权限(android6.0后要动态请求权限)
一、读写文件的时候要获取权限
1.在AndroidManifest.xml中声明权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
2.android6.0之后要在动态申请权限
//android6.0之后要动态获取权限
private void checkPermission(Activity activity) {
// Storage Permissions
final int REQUEST_EXTERNAL_STORAGE = 1;
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(DownLoadActivity.this,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(DownLoadActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
• ContextCompat.checkSelfPermission(context,permission)
• ActivityCompat.requestPermissions(activity,permissions,code)
案例:
public class ExternalActivity extends AppCompatActivity {
private EditText infoEdit;
private TextView txt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_external);
infoEdit = findViewById(R.id.info_Edit);
txt = findViewById(R.id.show_txt);
//动态添加权限
checkPermission(this);
}
//操作方法
public void operate(View v) {
//判断内存卡是否存在
if (Environment.getExternalStorageState().equals("mounted")) {
//获取外部存储的的绝对路径
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/text.txt";
//查看一下路径
Log.e("TAG", path);
switch (v.getId()) {
//保存内容
case R.id.save_btn:
//新建text.txt文件
File file = new File(path);
//如果文件不存在,则创建
try {
if (!file.exists()) {
file.createNewFile();
}
//创建文件输入流写入数据
//参数1:文件路径,参数2:可以拼接
FileOutputStream fos = new FileOutputStream(path, true);
String str = infoEdit.getText().toString();
//以字节流的方式写进去
fos.write(str.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
//读取内容
case R.id.read_btn:
//文件输入流读取数据
try {
FileInputStream fis=new FileInputStream(path);
byte[] b=new byte[1024];
//返回实际读取长度
int len=fis.read(b);
//利用字节数组生成字符串
String str=new String(b,0,len);
//显示在文本框上
txt.setText(str);
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
//android6.0之后要动态获取权限
private void checkPermission(Activity activity) {
// Storage Permissions
final int REQUEST_EXTERNAL_STORAGE = 1;
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(ExternalActivity.this,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(ExternalActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
存储路径: /storage/emulated/0/text.txt
获取外部存储的目录(私有目录)
好处:
- 应用被卸载后,这两个目录的内容也会被清除掉
- 不需要任何权限就可以操作
• Context.getExternalFilesDir(String type);//需要长时间保存的数据
String type是Environment下的文件类型
获取到 SDCard/Android/data/包名/files/ 目录
• Context.getExternalCacheDir();//临时保存的数据
获取到 SDCard/Android/data/包名/cache/目录
内部存储InternalStorage
- 内部存储,简称为内存
- 通过DDMS-->File Explorer可以找到,文件夹叫做data
- 内存中有两个文件夹:app,data
- app:应用的apk文件存放位置
- data:应用包名的文件夹
* Internal Storage特点:
* 1.内部存储总是可用的
* 2.内部存储的文件默认只能被当前应用程序访问,它是私有的
* 3.如果App卸载,内部存储文件也会被删除
* 4.如果文件只提供给当前的应用程序访问,那么放到内部存储中比较合适
* 5.内部存储器的读取速度最快且内部存储空间十分珍贵,开发中需要合理使用
*
获取内部存储的目录(不需要设置权限就可以读写操作)
• Context.getFilesDir() 获取/data/data/包名/files (files:放的是普通数据)
• Context.getCacheDir() 获取/data/data/包名/cache(cache:放的是缓存数据)
与上面外部存储的操作除了路径不一样几乎一样的操作
不需要权限
//操作方法
public void operate(View v) {
String path = InternalActivity.this.getFilesDir().getPath()+"/text.txt";
//查看一下路径
Log.e("TAG", path);
switch (v.getId()) {
//保存内容
case R.id.save_btn:
//新建text.txt文件
File file = new File(path);
//等价File file = new File(getFilesDir(),"text.txt");
//如果文件不存在,则创建
try {
if (!file.exists()) {
file.createNewFile();
}
//创建文件输入流写入数据
//参数1:文件路径,参数2:可以拼接
FileOutputStream fos = new FileOutputStream(path, true);
String str = infoEdit.getText().toString();
//以字节流的方式写进去
fos.write(str.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
//读取内容
case R.id.read_btn:
//文件输入流读取数据
try {
FileInputStream fis=new FileInputStream(path);
byte[] b=new byte[1024];
//返回实际读取长度
int len=fis.read(b);
//利用字节数组生成字符串
String str=new String(b,0,len);
//显示在文本框上
txt.setText(str);
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
FileNotFound异常解决方案
1. 检查下错误提示中的路径是否存在
2. 检查权限是否处理正确
3. 确认设备是否有SDCard
DDMS中data、SDCard目录无法展开
1. 模拟器需要更改只读权限,有的真机data目录需要root
2. Environment.getExternalStorageDirectory()的获取目 录才是SDCard的实际目录,因为系统不同路径会有差异