我编写了一个代码,该代码应该复制从 Storage Access Framework 中选择的文件并将其粘贴到我的应用程序的私有目录中。但是某些文件无法创建和复制。
代码的运行方式
复制/粘贴和文件创建工作由我创建的后台线程处理。
可运行类被馈送自SAF的clip(ClipData)
线程是start()
Runnable类中的for循环使用索引在剪辑中移动
在第一次迭代中,确定文件类型并将其发送到 createPrivateFile()函数。
该功能弹出指定扩展名的文件,并为其设置了 pickedFile 变量。
openOutputStream()使用创建的文件 URI
openInputStream()被提供了剪辑的URI。
使用 byteArray 将inputStream中的字节提供给文件。
不幸的是,就我而言,我没有太多选择。我已经搜索了2天,但没有成功。
class AttachmentReceiverRunnable internal constructor(private val clip: ClipData, context: Context) : Runnable {
private val weakContextReference = WeakReference(context)
private var progressUpdater: ProgressBarResultPublisher? = context as ProgressBarResultPublisher
override fun run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
val context = weakContextReference.get()
val actualProgress: Int = 100 / clip.itemCount
var clipSize = clip.itemCount
val clipCount = (clip.itemCount) - 1
var lastProgress = 0
val contentResolver: ContentResolver = context!!.contentResolver
for (item: Int in 0 until clipCount) {
val clipItem = clip.getItemAt(item)
val fileType = contentResolver.getType(clipItem.uri)
val extension = fileType!!.substringAfter("/")
Log.d("FILE TYPE", extension)
val pickedFile = createPrivateFile(extension)
if(pickedFile.createNewFile())
Log.d("FILE CREATION","SUCCESFUL")
else
Log.d("FILE CREATION"," NOT SUCCESFUL")
val fileContentURI = FileProvider.getUriForFile(context, "com.minutecodes.openote.fileprovider", pickedFile)
val out = contentResolver.openOutputStream(fileContentURI)
val inStream = contentResolver.openInputStream(clipItem!!.uri)
val byteArray: ByteArray = inStream!!.readBytes()
pickedFile.writeBytes(byteArray)
lastProgress += actualProgress
progressUpdater!!.onProgressUpdate(lastProgress, clipSize)
clipSize -= 1
out!!.flush()
out.close()
inStream.close()
}
return
}
@SuppressLint("SimpleDateFormat")
@Throws(IOException::class)
private fun createPrivateFile(fileExtension: String): File {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(System.currentTimeMillis())
@Suppress("JoinDeclarationAndAssignment") val storageDir: File?
val newFile: File?
var extension: String = fileExtension
if (fileExtension == "plain")
extension = "txt"
storageDir = weakContextReference.get()!!.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
if (!storageDir!!.exists())
storageDir.mkdirs()
newFile = File(storageDir,"FILE_$timeStamp.$extension")
return newFile
}
}
预期结果::如果选择了6个文件,则应创建6个文件并用byteArray填充。
实际结果::如果选择了6个文件,则通常会创建3个文件,因此仅复制了3个所选文件。如果选择了20个文件,则将复制大约11-13个文件。
不幸的是,并非总是能够实现一致性,并且随机复制了选定数量的所选文件。
据我测试,问题出在文件创建而不是文件复制上。
Logcat
2019-03-23 18:14:53.932 19579-19666/com.minutecodes.openote D/FOR LOOP RUNNING: 0
2019-03-23 18:14:53.951 19579-19666/com.minutecodes.openote D/FILE TYPE: jpeg
2019-03-23 18:14:53.963 19579-19666/com.minutecodes.openote D/FILE CREATION: SUCCESFUL
2019-03-23 18:14:54.001 19579-19666/com.minutecodes.openote D/FOR LOOP RUNNING: 1
2019-03-23 18:14:54.009 19579-19666/com.minutecodes.openote D/FILE TYPE: aac
2019-03-23 18:14:54.016 19579-19666/com.minutecodes.openote D/FILE CREATION: SUCCESFUL
2019-03-23 18:14:54.133 19579-19666/com.minutecodes.openote D/FOR LOOP RUNNING: 2
2019-03-23 18:14:54.137 19579-19666/com.minutecodes.openote D/FILE TYPE: aac
2019-03-23 18:14:54.142 19579-19666/com.minutecodes.openote D/FILE CREATION: NOT SUCCESFUL
2019-03-23 18:14:54.195 19579-19666/com.minutecodes.openote D/FOR LOOP RUNNING: 3
2019-03-23 18:14:54.197 19579-19666/com.minutecodes.openote D/FILE TYPE: mpeg
2019-03-23 18:14:54.201 19579-19666/com.minutecodes.openote D/FILE CREATION: SUCCESFUL
2019-03-23 18:14:54.251 19579-19666/com.minutecodes.openote D/FOR LOOP RUNNING: 4
2019-03-23 18:14:54.257 19579-19666/com.minutecodes.openote D/FILE TYPE: aac
2019-03-23 18:14:54.263 19579-19666/com.minutecodes.openote D/FILE CREATION: NOT SUCCESFUL
当选择6个项目时,捕获了以下Logcat。如您所见,有时文件创建不成功,因此我无法复制文件。