案例演示:把数据存在手机内存/sd卡。

存在手机内存
XML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.xxhuang.myapplication.MainActivity">

<EditText
android:id="@+id/et_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入账号"/>

<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:password="true"
android:hint="请输入密码"/>
<CheckBox
android:id="@+id/ck_remmber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码"
android:checked="true"/>
<Button
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"/>
</LinearLayout>

MainActivity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class MainActivity extends AppCompatActivity {
private EditText etNumber;
private EditText etPassword;
private Button btLogin;
private CheckBox ckRemmber;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

etNumber = (EditText) findViewById(R.id.et_number);
etPassword = (EditText) findViewById(R.id.et_password);
btLogin = (Button) findViewById(R.id.bt_login);
ckRemmber = (CheckBox) findViewById(R.id.ck_remmber);

//如果不为空,get到Map的key 回显数据
Map<String,String> loadMap = Util.load();
if (loadMap != null){
etNumber.setText(loadMap.get("number"));
etPassword.setText(loadMap.get("password"));
}

//光标定位在number字符后面
etNumber.setSelection(etNumber.length());


btLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String number = etNumber.getText().toString();
String password = etPassword.getText().toString();

//如果number。password为空
if (TextUtils.isEmpty(number) || TextUtils.isEmpty(password)){
Toast.makeText(MainActivity.this,"输入框不能为空",Toast.LENGTH_SHORT).show();
}

if (ckRemmber.isChecked() && !TextUtils.isEmpty(number) && !TextUtils.isEmpty(password)){
boolean isSuccess = Util.save(number, password);
if (isSuccess){
Toast.makeText(MainActivity.this,"保存成功",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this,"保存失败",Toast.LENGTH_SHORT).show();
}
}

}
});

}
}

Util类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class Util{
public static boolean save(String number,String password){
try{
String path = "/data/data/com.example.xxhuang.myapplication/huang.text";
FileOutputStream fos = new FileOutputStream(path);

//123456##321,用符号隔开,这样方便拿,取的时候分割一下
String data = number + "##" +password;

//getByte()将字符串转化成一个字节数组,因为流里不能直接存字符
fos.write(data.getBytes());

// 强制把缓冲区的数据刷出去,不必等到填满再刷出去
fos.flush();
fos.close();
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}

public static Map<String,String> load() {
try {
String path = "/data/data/com.example.xxhuang.myapplication/huang.text";
FileInputStream fis = new FileInputStream(path);
BufferedReader buffer = new BufferedReader(new InputStreamReader(fis));
String s = buffer.readLine();

if (!TextUtils.isEmpty(s)) {

//切割数据
String[] sqlit = s.split("##");
//向上转型
Map<String, String> loadMap = new HashMap<String, String>();

//填入对应的键值对
loadMap.put("number", sqlit[0]);
loadMap.put("password", sqlit[1]);
return loadMap;
}

}catch(Exception e){
e.printStackTrace();
}
return null;
}

}

这样写,每次更改包名地址,path链接都需要改变,优化写法:
Util类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//方法形参中加入Context参数,因为getFilesDir()是MainActivity类的方法,就是上下文
public static boolean save(Context context ,String number,String password){
try{

//得到文件对象
File fileDir = context.getFilesDir();

//新建文件夹对象,给对象名字所以传入对象和文件名
File file = new File(fileDir,"xxhuang.text");

//把文件作为参数传给流
FileOutputStream fos = new FileOutputStream(file);

... //其他一致
1
2
3
4
5
6
7
public static Map<String,String> load(Context context) {

try {

File fileDir = context.getFilesDir();
File file = new File(fileDir,"xxhuang.text");
FileInputStream fis = new FileInputStream(file);

MainActivity

1
2
3
//传入形参需要的上下文参数即可
Map<String,String> loadMap = Util.load(this);
boolean isSuccess = Util.save(MainActivity.this, number, password);

存在sd卡
得到sd卡的文件路径对象就是(其他和存储在手机内存是一样的意思)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Util{
public static boolean save(Context context ,String number,String password){
try{

//判断当前的手机是否有sd卡状态,状态返回的是一个String值
String state = Environment.getExternalStorageState();

//如果state不等于这个常量MEDIA_MOUNTED,则已经挂载了sd卡
if (!Environment.MEDIA_MOUNTED.equals(state)){
return false;
}

//getExternalStorageDirectory()得到sd卡的路径文件对象
File sdCard = Environment.getExternalStorageDirectory();

//加上创建的名字
File file = new File(sdCard,"xxhuang.text");

FileOutputStream fos = new FileOutputStream(file);
1
2
3
4
5
6
7
8
9
10
11
12
13
public static Map<String,String> load(Context context) {

try {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)){
return null;
}

File sdCard = Environment.getExternalStorageDirectory();
File file = new File(sdCard,"xxhuang.text");

FileInputStream fis = new FileInputStream(file);
BufferedReader buffer = new BufferedReader(new InputStreamReader(fis));

添加往sd卡写入的权限。

1
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>