如何在 android API LEVEL28 使用 Android SAF(存储访问框架)后将文档文件保存在外部存储中
How to save Document file in external storage after android API LEVEL28 With Android SAF(Storage Access Framework))
此代码适用于媒体文件我想要文档文件的解决方案
我不知道如何为文档文件设置内容值
fun getFile(fileName: String): File? {
with(sharePrefHelper.app){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues()
// Here is My Question That what should i Do Here Because this is for document not for image
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
// for MIME_TYPE "image/jpg" this is working
values.put(MediaStore.Images.Media.MIME_TYPE, "text/csv")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Donny")
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)?.let {
it.path?.let { finalPath ->
return File(finalPath)
}
}
} else {
val directory: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Donny")
if (!directory.exists()){
directory.mkdirs()
}
return File(directory, fileName)
}
return null
}
}
此代码适用于媒体文件
我的问题是如何将 CSV 文件等文档保存在 android 设备的外部文件夹中
编辑:
好吧好吧,我仍在尝试在“下载”目录中添加任何类型的文件。
Personnaly,我正在尝试从我的 assetFolder 复制一个文件并将其粘贴到“下载”文件夹。我还没有成功。
但是,我目前可以在该文件夹中创建任何类型的文件,它正在使用以下方法。希望对您有所帮助。
这是我的代码:
public void saveFileToPhone(InputStream inputStream, String filename) {
OutputStream outputStream;
Context myContext = requireContext();
try {
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.Q){
ContentResolver contentResolver = requireContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Downloads.DISPLAY_NAME,filename);
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
Uri collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri fileUri = contentResolver.insert(collection, contentValues);
outputStream = contentResolver.openOutputStream(Objects.requireNonNull(fileUri));
Objects.requireNonNull(outputStream);
}
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
这是我用干净的方式所做的
这是文件提供者activity
class FileProviderActivity : AppCompatActivity() {
var commonIntentLauncher: ActivityResultLauncher<Intent?> = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.let {
intent.getParcelableExtra<ResultReceiver>("FileReceiver")?.send(0, bundleOf(
"FileUri" to result?.data?.data.toString()
))
finish()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
val activityIntent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = intent.getStringExtra("fileType")
putExtra(Intent.EXTRA_TITLE, intent.getStringExtra("fileName"))
putExtra(DocumentsContract.EXTRA_INITIAL_URI, MediaStore.Downloads.EXTERNAL_CONTENT_URI)
}
commonIntentLauncher.launch(activityIntent)
}else{
val directory: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/Dunny/CSVFiles")
if (!directory.exists()){
directory.mkdirs()
}
intent.getParcelableExtra<ResultReceiver>("FileReceiver")?.send(0, bundleOf(
"FileUri" to File(directory, intent.getStringExtra("fileName")!!).toURI().toString()
))
finish()
}
}
}
这个 FileProviderHelper
class MyFileProvider {
companion object {
fun with(context: Context) = FileRequest(context)
}
class FileRequest(private val context: Context) {
fun request(fileName: String, fileType: String = "application/*", file: (Uri?) -> Unit ) {
val intent = Intent(context, FileProviderActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("fileName",fileName)
.putExtra("fileType", fileType)
.putExtras(bundleOf("FileReceiver" to FileReceiver(file)))
context.startActivity(intent)
}
}
internal class FileReceiver(private val file: (Uri?) -> Unit) : ResultReceiver(Handler(Looper.getMainLooper())) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
super.onReceiveResult(resultCode, resultData)
resultData?.let {
file(it.getString("FileUri")?.toUri())
}
}
}
}
这里是这个函数的使用
MyFileProvider.with(this).request("TestFile.csv","application/*") { fileUri ->
toast(fileUri.toString())
}
此代码适用于媒体文件我想要文档文件的解决方案
我不知道如何为文档文件设置内容值
fun getFile(fileName: String): File? {
with(sharePrefHelper.app){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues()
// Here is My Question That what should i Do Here Because this is for document not for image
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
// for MIME_TYPE "image/jpg" this is working
values.put(MediaStore.Images.Media.MIME_TYPE, "text/csv")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Donny")
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)?.let {
it.path?.let { finalPath ->
return File(finalPath)
}
}
} else {
val directory: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Donny")
if (!directory.exists()){
directory.mkdirs()
}
return File(directory, fileName)
}
return null
}
}
此代码适用于媒体文件
我的问题是如何将 CSV 文件等文档保存在 android 设备的外部文件夹中
编辑:
好吧好吧,我仍在尝试在“下载”目录中添加任何类型的文件。 Personnaly,我正在尝试从我的 assetFolder 复制一个文件并将其粘贴到“下载”文件夹。我还没有成功。 但是,我目前可以在该文件夹中创建任何类型的文件,它正在使用以下方法。希望对您有所帮助。
这是我的代码:
public void saveFileToPhone(InputStream inputStream, String filename) {
OutputStream outputStream;
Context myContext = requireContext();
try {
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.Q){
ContentResolver contentResolver = requireContext().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Downloads.DISPLAY_NAME,filename);
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
Uri collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri fileUri = contentResolver.insert(collection, contentValues);
outputStream = contentResolver.openOutputStream(Objects.requireNonNull(fileUri));
Objects.requireNonNull(outputStream);
}
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
这是我用干净的方式所做的
这是文件提供者activity
class FileProviderActivity : AppCompatActivity() {
var commonIntentLauncher: ActivityResultLauncher<Intent?> = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.let {
intent.getParcelableExtra<ResultReceiver>("FileReceiver")?.send(0, bundleOf(
"FileUri" to result?.data?.data.toString()
))
finish()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
val activityIntent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = intent.getStringExtra("fileType")
putExtra(Intent.EXTRA_TITLE, intent.getStringExtra("fileName"))
putExtra(DocumentsContract.EXTRA_INITIAL_URI, MediaStore.Downloads.EXTERNAL_CONTENT_URI)
}
commonIntentLauncher.launch(activityIntent)
}else{
val directory: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/Dunny/CSVFiles")
if (!directory.exists()){
directory.mkdirs()
}
intent.getParcelableExtra<ResultReceiver>("FileReceiver")?.send(0, bundleOf(
"FileUri" to File(directory, intent.getStringExtra("fileName")!!).toURI().toString()
))
finish()
}
}
}
这个 FileProviderHelper
class MyFileProvider {
companion object {
fun with(context: Context) = FileRequest(context)
}
class FileRequest(private val context: Context) {
fun request(fileName: String, fileType: String = "application/*", file: (Uri?) -> Unit ) {
val intent = Intent(context, FileProviderActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("fileName",fileName)
.putExtra("fileType", fileType)
.putExtras(bundleOf("FileReceiver" to FileReceiver(file)))
context.startActivity(intent)
}
}
internal class FileReceiver(private val file: (Uri?) -> Unit) : ResultReceiver(Handler(Looper.getMainLooper())) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
super.onReceiveResult(resultCode, resultData)
resultData?.let {
file(it.getString("FileUri")?.toUri())
}
}
}
}
这里是这个函数的使用
MyFileProvider.with(this).request("TestFile.csv","application/*") { fileUri ->
toast(fileUri.toString())
}