1. 文件内容的保存看代码,其中id在xml中已经定义
1 package com.example.qq_login_demo; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 5 import android.os.Bundle; 6 import android.speech.tts.TextToSpeech; 7 import android.text.TextUtils; 8 import android.util.Log; 9 import android.view.View; 10 import android.widget.Button; 11 import android.widget.EditText; 12 import android.widget.Toast; 13 14 import java.io.BufferedReader; 15 import java.io.File; 16 import java.io.FileInputStream; 17 import java.io.FileNotFoundException; 18 import java.io.FileOutputStream; 19 import java.io.InputStreamReader; 20 21 public class MainActivity extends AppCompatActivity { 22 23 private static final String TAG = "MainActivity"; 24 private EditText mUsername; 25 private EditText mPassword; 26 private Button mLogin; 27 28 @Override 29 protected void onCreate(Bundle savedInstanceState) { 30 super.onCreate(savedInstanceState); 31 setContentView(R.layout.qq_ui_login_layout); 32 33 // 第一步,找到控件 34 initview(); 35 36 // 第二步,给登录按钮设置点击事件 37 initListener(); 38 } 39 40 /** 41 * 这个方法,我们用来找到对应的控件 42 */ 43 private void initview(){ 44 mUsername = (EditText) this.findViewById(R.id.Username); 45 mPassword = (EditText) this.findViewById(R.id.Password); 46 mLogin = (Button) this.findViewById(R.id.Login); 47 48 } 49 50 /** 51 * 这个方法,我们用来设置监听事件 52 */ 53 private void initListener(){ 54 mLogin.setOnClickListener(new View.OnClickListener() { 55 @Override 56 public void onClick(View v) { 57 // 当方法的内容比较长时,可以在方法外写,有助于代码阅读 58 // 写完方法名后,alt + enter 在外层定义函数 59 handlerLoginEvent(v); 60 } 61 }); 62 } 63 64 @Override 65 protected void onResume() { 66 super.onResume(); 67 // File filesDir = this.getFilesDir(); 68 // File saveFile = new File(filesDir, "info.text"); 69 // 可以使用以下的方法来获取数据 70 try { 71 FileInputStream fileInputStream = this.openFileInput("info.text"); 72 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream)); 73 String info = bufferedReader.readLine(); 74 75 // fout.write((username + ": " + password).getBytes()); 76 // 这行代码是之前使用的保存形式,也就是说拿到数据以后,要对数据进行切割 77 String[] splits = info.split(": "); 78 String username = splits[0]; 79 String password = splits[1]; 80 81 // 回显数据 82 mPassword.setText(password); 83 mUsername.setText(username); 84 } catch (Exception e) { 85 e.printStackTrace(); 86 } 87 } 88 89 /** 90 * 处理按钮事件 91 */ 92 private void handlerLoginEvent(View v) { 93 // 第三步,取出EditText内的内容,即输入的账号和密码 94 // 账号 95 String password = mPassword.getText().toString(); 96 String username = mUsername.getText().toString(); 97 98 // 对账号密码进行检查,在实际开发中对用户的账号和密码进行数据校验 99 100 // 账号密码进行判空 101 // 第一种办法: 102 // if(username.length() == 0){ 103 // // 账号长度为空 104 // // 这里的this向上溯源,继承Context类,指代当前的activity 105 // // https://www.iteye.com/blog/cai-bird-1245146 toast的使用详解 106 // Toast.makeText(this, "账号不可以为空", Toast.LENGTH_SHORT).show(); 107 // return; 108 // } 109 // else if (password.length() == 0) { 110 // Toast.makeText(this, "密码不可以为空", Toast.LENGTH_SHORT).show(); 111 // return; 112 // } 113 114 // 第二种方法: 115 // https://www.jianshu.com/p/4095639631aa TextUtil工具类的使用 116 if (TextUtils.isEmpty(username)) { 117 // 账号为空 118 Toast.makeText(this, "账号不能为空", Toast.LENGTH_SHORT).show(); 119 return; 120 } 121 else if(TextUtils.isEmpty(password)){ 122 // 密码为空 123 Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show(); 124 return; 125 } 126 127 // 把账号和密码保存起来: 128 saveUserInfo(password, username); 129 } 130 131 private void saveUserInfo(String password, String username) { 132 Log.d(TAG, "保存用户信息"); 133 /** 134 * 直接写一个文件名的时候,去写文件,爆出的异常是read-only 135 * 在Android系统中,每一个应用就是一个用户,每一个用户的权限是特定的,不可以操作其他应用的内容,所以需要特地的文件路径以及要提前创建文件 136 * 以"/"为根目录 137 */ 138 File file = new File("/data/data/com.example.qq_login_demo/info.text"); 139 140 // 实际情况下,该目录比较长,不实用,所以用以下方法来解决: 141 File filesDir = this.getFilesDir(); 142 Log.d(TAG, "files dir == " + filesDir.toString()); 143 // 输出的结果为: /data/user/0/com.example.qq_login_demo/files 144 // 也就是说,getFilesDir()这个方法它拿到的路径为/data/data/包名/files这个路径(即新建一个files文件夹 145 // 改进的方法为: 146 File saveFile = new File(filesDir, "info.text"); 147 Log.d(TAG, "saveFile == " + saveFile.toString()); 148 file = saveFile; 149 // 此时这里的saveFile就是/data/data/com.example.qq_login_demo/files/info.text 150 151 // 相应的,cache也有相应的路径,结果为: /data/user/0/com.example.qq_login_demo/cache 152 File cacheDir = this.getCacheDir(); 153 Log.d(TAG, "cache dir == " + cacheDir.toString()); 154 155 /** 156 * /data/user/0/com.example.qq_login_demo/files 157 * 上面这个路径为保存文件路径,我们可以用代码删除,也可以通过设置里的应用列表里的选项进行清理 158 * /data/user/0/com.example.qq_login_demo/cache 159 * 上面这个为缓存路径,用于保存缓存文件,该目录下的文件,会由系统根据存储情况进行清理 160 */ 161 162 try { 163 // 如果文件不存在,则创建文件 164 if(!file.exists()){ 165 file.createNewFile(); 166 } 167 FileOutputStream fout = new FileOutputStream(file); 168 // 以特定的格式来存储账号密码 169 // 格式: username: password 170 fout.write((username + ": " + password).getBytes()); 171 fout.close(); 172 Toast.makeText(this, "数据保存成功", Toast.LENGTH_SHORT).show(); 173 } catch (Exception e) { 174 e.printStackTrace(); 175 } 176 } 177 }
2. layout定义
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@mipmap/img_20191105_072932" 7 android:orientation="vertical" 8 > 9 10 <LinearLayout 11 android:layout_width="match_parent" 12 android:layout_height="wrap_content" 13 android:layout_marginTop="50dp" 14 android:padding="30dp" 15 android:orientation="vertical"> 16 <TextView 17 android:drawableLeft="@mipmap/ic_launcher" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:textSize="40sp" 21 android:text="QQ"/> 22 23 <EditText 24 android:id="@+id/Username" 25 android:layout_width="match_parent" 26 android:layout_height="match_parent" 27 android:hint="QQ号码/手机号/邮箱" 28 android:textColorHint="@color/white" /> 29 30 <EditText 31 android:id="@+id/Password" 32 android:inputType="textPassword" 33 android:layout_marginTop="30dp" 34 android:layout_width="match_parent" 35 android:hint="密码" 36 android:textColorHint="@color/white" 37 android:layout_height="match_parent"/> 38 39 <Button 40 android:id="@+id/Login" 41 android:layout_width="match_parent" 42 android:layout_height="wrap_content" 43 android:text="登录" 44 android:textSize="20sp" 45 android:background="#00aaff"/> 46 47 <RelativeLayout 48 android:layout_width="match_parent" 49 android:layout_height="wrap_content"> 50 51 <TextView 52 android:layout_width="wrap_content" 53 android:layout_height="wrap_content" 54 android:text="忘记密码" 55 android:textColor="#00aaff" 56 android:textSize="16sp"/> 57 58 <TextView 59 android:layout_width="wrap_content" 60 android:layout_height="wrap_content" 61 android:text="新用户注册" 62 android:textColor="#00aaff" 63 android:textSize="16sp" 64 android:layout_alignParentRight="true"/> 65 66 </RelativeLayout> 67 68 </LinearLayout> 69 70 <TextView 71 android:layout_width="wrap_content" 72 android:layout_height="wrap_content" 73 android:layout_alignParentBottom="true" 74 android:layout_centerHorizontal="true" 75 android:layout_marginBottom="20dp" 76 android:text="登录即代表阅读并同意服务条款" 77 android:textColor="#00aaff" 78 android:textSize="20sp" 79 android:id="@+id/a"> 80 </TextView> 81 </RelativeLayout>
3. 文件内容查看
第一种方法:
在dbs shell中进入到所创建文件的包中。本例子的路径为:
/data/data/com.example.qq_login_demo
包的名字可以在manifests文件夹下的AndroidManifest.xml中查看
第二种方法:
view--Tool Windows--Device File Explorer中,将模拟器中的文件导出查看