1.manifeast文件
(1)app权限
<!--存储权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
(2)application配置
<application
...
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
...>
(3)组件配置
注意:Android 12以上,组件创建会自动生成以下属性
android:exported="true"
表示”是否支持其它应用调用当前组件”
如果不添加改属性,会报错。
2.动态申请文件存储权限
说明,Android的权限根据版本号分为三种
1:Android6.0之前
2:Android6.0-Android 10
3:Android 11以后
其中,6.0之前不需要动态申请权限,只需要在manifest文件中申请即可。从6.0之后,app需要动态申请权限,即弹框询问用户,是否给用户授权。Android 11以后,对权限的控制进一步收紧,很多的权限申请发生改变,例如,此前操作文件,只需要声明读写权限即可,但是现在划分了图片、音频、视频等等,并且操作普通文件的权限也变为MANAGE_EXTERNAL_STORAGE
代码如下:
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private boolean havePermission = false;
@Override
protected void onResume() {
super.onResume();
checkPermission();
}
private AlertDialog dialog;
private void checkPermission() {
//检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
if (Build.VERSION.SDK_INT >= 30) {
if (!Environment.isExternalStorageManager()) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用本应用!")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivity(intent);
}
}).create();
dialog.show();
} else {
havePermission = true;
Log.i("swyLog", "Android 11以上,当前已有权限");
}
} else {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
//申请权限
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
dialog = new AlertDialog.Builder(this)
.setTitle("提示")//设置标题
.setMessage("请开启文件访问权限,否则无法正常使用本应用!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(BrowserActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}).create();
dialog.show();
} else {
havePermission = true;
Log.i("swyLog", "Android 6.0以上,11以下,当前已有权限");
}
} else {
havePermission = true;
Log.i("swyLog", "Android 6.0以下,已获取权限");
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
havePermission = true;
Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
} else {
havePermission = false;
Toast.makeText(this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
3.文件操作
(1)定义文件保存的路径及文件名
private String FILE_SAVE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MobileReport/";
private String FILE_NAME = "user.txt";
(2)保存文件
private void saveLoginAccount(String json) {
if (TextUtils.isEmpty(json)) {
return;
}
Log.i("swyLog", "saveLoginAccount called");
String value = encodeToString(json);
Log.i("swyLog", "save 明文:" + json);
Log.i("swyLog", "save 密文:" + value);
File storage = new File(FILE_SAVE_PATH);
if (!storage.exists()) {
storage.mkdirs();
}
File tmepfile = new File(storage.getPath());
if (!tmepfile.exists()) {
tmepfile.mkdirs();
}
File file = new File(tmepfile, FILE_NAME);
if (file.exists()) {
Log.i("swyLog", "删除原有文件");
file.delete();
}
if (!file.exists()) {
Log.i("swyLog", "文件删除成功");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(value.getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(3)读取文件
private String uploadLoginAccount() {
Log.i("swyLog", "uploadLoginAccount called");
InputStream inputStream = null;
Reader reader = null;
BufferedReader bufferedReader = null;
try {
File storage = new File(FILE_SAVE_PATH);
if (!storage.exists()) {
return "";
}
File file = new File(storage, FILE_NAME);
if (!file.exists()) {
return "";
}
inputStream = new FileInputStream(file);
reader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(reader);
StringBuilder result = new StringBuilder();
String temp;
while ((temp = bufferedReader.readLine()) != null) {
result.append(temp);
}
String value = decodeToString(result.toString());
Log.i("swyLog", "upload 密文:" + result);
Log.i("swyLog", "upload 明文:" + value);
return value;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "";
}
(4)删除文件
private void deleteLoginAccount() {
Log.i("swyLog", "deleteLoginAccount called");
File storage = new File(FILE_SAVE_PATH);
if (!storage.exists()) {
storage.mkdirs();
}
File tmepfile = new File(storage.getPath());
if (!tmepfile.exists()) {
tmepfile.mkdirs();
}
File file = new File(tmepfile, FILE_NAME);
if (file.exists()) {
try {
Log.i("swyLog", "删除原有文件");
file.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
if (!file.exists()) {
Log.i("swyLog", "文件删除成功");
}
}
(5)base64 加解密方法
/**
* 字符Base64加密
*
* @param str
* @return
*/
public static String encodeToString(String str) {
try {
return Base64.encodeToString(str.getBytes("UTF-8"), Base64.DEFAULT);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
/**
* 字符Base64解密
*
* @param str
* @return
*/
public static String decodeToString(String str) {
try {
return new String(Base64.decode(str.getBytes("UTF-8"), Base64.DEFAULT));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
说明:我这里是从项目中复制的代码,作用是,将字符串加密之后,保存到sd卡种,加密的原因自然不言而喻,因为有些信息是不方便直接展示给用户看的。