android - 我们如何使用 Kotlin for Android 从 InputStream 中保存任何类型的文件?
问题描述
语境:
我的项目是在 WiFi P2P/WiFi Direct 领域。我找到并遵循了一些有用的教程和问题,并且有一个可以在手机之间发送图像的工作应用程序。打开一个套接字并将一个 OutputStream 发送到另一个设备。设备 2 接收流并且必须采用 mime 类型才能压缩并保存到文件。*
编辑:*只需压缩图像,但需要知道文件类型才能将其保存到存储中。
我现在想打开此功能以传输任何(常见)类型的文件,并让其他设备愉快地接收它并将其存储在适当的位置(或者全部下载可能会使它更简单)。
我的问题:
我可以使用什么来确定作为 InputStream 传入的所有(图像、文本、日历事件、联系人、视频)文件的 MIME 类型。
当前代码尝试:
我尝试使用BitmapFactory.decodeStream()来接收选项和 mimeType。这仅适用于图像。
guessContentTypeFromStream()根本没有用,我认为它可能只适合从互联网源流式传输?
任何关于如何在此处使用存储访问框架的说明/提示,或确定 mimeType 的技术,都值得赞赏!
以下是接收端使用的代码:
inner class RxClass: Thread() {
lateinit var socket: Socket
lateinit var serverSocket: ServerSocket
override fun run() {
try {
serverSocket = ServerSocket(8888)
socket = serverSocket.accept()
//If this line is reached, then a connection has been established between server and client
Log.d("RECEIVE", "Connection established")
lateinit var bitmap: Bitmap
lateinit var inputStream: InputStream
lateinit var outputStream: OutputStream
var mimeType: String? = null
lateinit var path: String
try {
inputStream = socket.getInputStream()
Log.d("RECEIVE", "got InputStream")
runOnUiThread { Toast.makeText(applicationContext, "Receiving file...", Toast.LENGTH_SHORT).show() }
//mimeType = guessContentTypeFromStream(inputStream)
val options = BitmapFactory.Options()
bitmap = BitmapFactory.decodeStream(inputStream, null, options)!! //TODO: this needs to be for all file types
mimeType = options.outMimeType
Log.d("RECEIVE", "Decoded input, Type: $mimeType")
} catch (e: IOException) {
e.printStackTrace()
}
when(mimeType){ //I was hoping that my attempt would let me know what MIME type was and then here I can act on it differently if neccessary
"image/jpeg" -> path = Environment.DIRECTORY_PICTURES
"image/jpg" -> path = Environment.DIRECTORY_PICTURES
"image/bmp" -> path = Environment.DIRECTORY_PICTURES
"image/gif" -> path = Environment.DIRECTORY_PICTURES
"image/png" -> path = Environment.DIRECTORY_PICTURES
"audio/mpeg" -> path = Environment.DIRECTORY_MUSIC
"audio/x-wav" -> path = Environment.DIRECTORY_MUSIC
"video/wav" -> path = Environment.DIRECTORY_MOVIES
"video/mp4" -> path = Environment.DIRECTORY_MOVIES
"text/plain" -> path = Environment.DIRECTORY_DOCUMENTS
"text/html" -> path = Environment.DIRECTORY_DOCUMENTS
"text/x-vcard" -> path = Environment.DIRECTORY_DOCUMENTS
"text/x-vcalendar" -> path = Environment.DIRECTORY_DOCUMENTS
null -> Log.d("RECEIVE", "MIMETYPE is NULL")
}
Log.d("RECEIVE", "Save file in location: $path")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver: ContentResolver = contentResolver
val contentValues = ContentValues()
//contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, name)
//contentValues.put(MediaStore.Images.Media.MIME_TYPE, mimeType)
//contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, path)
val rxUri: Uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)!!
val inputStream = socket.getInputStream()
outputStream = resolver.openOutputStream(rxUri)!!
Log.d("RECEIVE", "Sending File: $rxUri")
inputStream.copyTo(outputStream)
if(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)) {
runOnUiThread { Toast.makeText(applicationContext, "File Saved", Toast.LENGTH_SHORT).show() }
}
Log.d("RECEIVE", "close streams")
outputStream.flush()
outputStream.close()
inputStream.close()
runOnUiThread {
ReceivedImage.setImageURI(rxUri)
}
} else { //Version less than Android Q is not implemented
}
} catch (e: IOException){
e.printStackTrace()
}
}
}
有用的链接
https://developer.android.com/training/data-storage
https://developer.android.com/training/data-storage/shared/media#add-item
https://developer.android.com/reference/kotlin/android/graphics/BitmapFactory
提前致谢
解决方案
推荐阅读
- git - 如何在开发服务器中测试新功能
- c# - 在 C# 图形上绘制“位图”字体
- sql - 为什么我的 CREATE TABLE 语句会引发 ORA-00905:缺少关键字错误
- python - 通过List在python中包含相等值的索引问题
- node.js - 有没有更好的方法在Nodejs中加入MongoDB中的两个集合
- java - 我可以动态更改父类吗
- sql - 什么可能导致此 SQL 作业随机执行失败?
- angular - Angular 英雄之旅 HttpClient CRUD 方法
- python - Spider 运行但不输出文件
- android - 试图序列化一个对象(将它保存到一个文件中),得到一个说只读文件系统的异常