Android 保存/读取本地SD卡文件(兼容Android 13)

时间:2024-11-08 22:52:06

文件

(1)app权限

<!--存储权限-->
<uses-permission android:name=".WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name=".READ_EXTERNAL_STORAGE"/>
<uses-permission android:name=".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 = {
        .READ_EXTERNAL_STORAGE,
        .WRITE_EXTERNAL_STORAGE
};
private boolean havePermission = false;
@Override
protected void onResume() {
    ();
    checkPermission();
}
private AlertDialog dialog;

private void checkPermission() {
    //检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
    if (.SDK_INT >= 30) {
        if (!()) {
            if (dialog != null) {
                ();
                dialog = null;
            }
            dialog = new (this)
                    .setTitle("提示")//设置标题
                    .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
                    .setNegativeButton("取消", new () {
                        @Override
                        public void onClick(DialogInterface dialog, int i) {
                            ();
                        }
                    })
                    .setPositiveButton("确定", new () {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ();
                            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                            (("package:" + getPackageName()));
                            startActivity(intent);
                        }
                    }).create();
            ();
        } else {
            havePermission = true;
            ("swyLog", "Android 11以上,当前已有权限");
        }
    } else {
        if (.SDK_INT > Build.VERSION_CODES.M) {
            if ((this, .WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                //申请权限
                if (dialog != null) {
                    ();
                    dialog = null;
                }
                dialog = new (this)
                        .setTitle("提示")//设置标题
                        .setMessage("请开启文件访问权限,否则无法正常使用本应用!")
                        .setPositiveButton("确定", new () {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ();
                                (, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
                            }
                        }).create();
                ();
            } else {
                havePermission = true;
                ("swyLog", "Android 6.0以上,11以下,当前已有权限");
            }
        } else {
            havePermission = true;
            ("swyLog", "Android 6.0以下,已获取权限");
        }
    }
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
(requestCode, permissions, grantResults);    
switch (requestCode) {
        case REQUEST_EXTERNAL_STORAGE: {
            if ( > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                havePermission = true;
                (this, "授权成功!", Toast.LENGTH_SHORT).show();
            } else {
                havePermission = false;
                (this, "授权被拒绝!", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
}

3.文件操作

(1)定义文件保存的路径及文件名

private String FILE_SAVE_PATH = ().getAbsolutePath() + "/MobileReport/";
private String FILE_NAME = "";

(2)保存文件

private void saveLoginAccount(String json) {
    if ((json)) {
        return;
    }
    ("swyLog", "saveLoginAccount called");
    String value = encodeToString(json);
    ("swyLog", "save 明文:" + json);
    ("swyLog", "save 密文:" + value);
    File storage = new File(FILE_SAVE_PATH);
    if (!()) {
        ();
    }
    File tmepfile = new File(());
    if (!()) {
        ();
    }
    File file = new File(tmepfile, FILE_NAME);
    if (()) {
        ("swyLog", "删除原有文件");
        ();
    }
    if (!()) {
        ("swyLog", "文件删除成功");
        try {
            ();
        } catch (IOException e) {
            ();
        }
    }
    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(file);
        (());
    } catch (Exception e) {
        ();
    } finally {
        if (fileOutputStream != null) {
            try {
                ();
            } catch (IOException e) {
                ();
            }
        }
    }
}

(3)读取文件

private String uploadLoginAccount() {
    ("swyLog", "uploadLoginAccount called");
    InputStream inputStream = null;
    Reader reader = null;
    BufferedReader bufferedReader = null;
    try {
        File storage = new File(FILE_SAVE_PATH);
        if (!()) {
            return "";
        }
        File file = new File(storage, FILE_NAME);
        if (!()) {
            return "";
        }
        inputStream = new FileInputStream(file);
        reader = new InputStreamReader(inputStream);
        bufferedReader = new BufferedReader(reader);
        StringBuilder result = new StringBuilder();
        String temp;
        while ((temp = ()) != null) {
            (temp);
        }
        String value = decodeToString(());
        ("swyLog", "upload 密文:" + result);
        ("swyLog", "upload 明文:" + value);
        return value;
    } catch (Exception e) {
        ();
    } finally {
        if (reader != null) {
            try {
                ();
            } catch (IOException e) {
                ();
            }
        }
        if (inputStream != null) {
            try {
                ();
            } catch (IOException e) {
                ();
            }
        }
        if (bufferedReader != null) {
            try {
                ();
            } catch (IOException e) {
                ();
            }
        }
    }
    return "";
}

(4)删除文件

private void deleteLoginAccount() {
    ("swyLog", "deleteLoginAccount called");
    File storage = new File(FILE_SAVE_PATH);
    if (!()) {
        ();
    }
    File tmepfile = new File(());
    if (!()) {
        ();
    }
    File file = new File(tmepfile, FILE_NAME);
    if (()) {
        try {
            ("swyLog", "删除原有文件");
            ();
        } catch (Exception e) {
            ();
        }
    }
    if (!()) {
        ("swyLog", "文件删除成功");
    }
}

(5)base64 加解密方法

/**
 * 字符Base64加密
 *
 * @param str
 * @return
 */
public static String encodeToString(String str) {
    try {
        return (("UTF-8"), );
    } catch (UnsupportedEncodingException e) {
        ();
    }
    return "";
}

/**
 * 字符Base64解密
 *
 * @param str
 * @return
 */
public static String decodeToString(String str) {
    try {
        return new String((("UTF-8"), ));
    } catch (UnsupportedEncodingException e) {
        ();
    }
    return "";
}

说明:我这里是从项目中复制的代码,作用是,将字符串加密之后,保存到sd卡种,加密的原因自然不言而喻,因为有些信息是不方便直接展示给用户看的。