读取文件(N以上无需存储权限)
为兼容Android N
以下设备,需要检查存储权限
在AndroidManifest.xml
中添加如下声明(位于application
标签之外)
< uses-permission android: name= " android.permission.READ_EXTERNAL_STORAGE" />
编写检查函数
private fun checkReadPermission ( ) : Boolean {
return if ( Build. VERSION. SDK_INT < Build. VERSION_CODES. N && ContextCompat. checkSelfPermission ( this , Manifest. permission. READ_EXTERNAL_STORAGE) != PackageManager. PERMISSION_GRANTED) {
ActivityCompat. requestPermissions ( this , arrayOf ( Manifest. permission. READ_EXTERNAL_STORAGE) , 1 )
false
} else true
}
编写选择文件函数
private fun pickFile ( ) {
val i = Intent ( Intent. ACTION_GET_CONTENT)
i. type = "*/*"
startActivityForResult ( i, 1 )
}
在onRequestPermissionsResult
中处理requestCode
override fun onRequestPermissionsResult ( requestCode: Int, permissions: Array< String? > , grantResults: IntArray) {
when ( requestCode) {
1 -> {
if ( grantResults. isNotEmpty ( ) && grantResults[ 0 ] == PackageManager. PERMISSION_GRANTED) pickFile ( )
else Toast. makeText ( this , R. string. permissionDenied, Toast. LENGTH_SHORT) . show ( )
}
}
}
因为pickFile
函数的startActivityForResult
调用了其它应用,所以需要设置onActivityResult
private fun generateCacheFile ( name: String) = File ( cacheDir, name)
override fun onActivityResult ( requestCode: Int, resultCode: Int, data : Intent? ) {
super . onActivityResult ( requestCode, resultCode, data )
if ( resultCode == RESULT_OK) when ( requestCode) {
1 -> data ? . data? . let {
saveFile ( generateCacheFile ( "input" ) , it) }
}
}
编写获取uri
后打开FileInputStream
读取文件进行保存的函数,这里将其存储在了cache
目录下的input
文件
private fun saveFile ( f: File? , uri: Uri) {
val fd = contentResolver. openFileDescriptor ( uri, "r" )
fd? . fileDescriptor? . let {
val fi = FileInputStream ( it)
f? . outputStream ( ) ? . let {
fi. copyTo ( it)
it. close ( )
}
fi. close ( )
}
fd? . close ( )
}
保存文件
编写自定义保存文件名函数
private fun createFile ( fileName: String, type: String = "*/*" ) {
val intent = Intent ( Intent. ACTION_CREATE_DOCUMENT)
intent. addCategory ( Intent. CATEGORY_OPENABLE)
intent. type = type
intent. putExtra ( Intent. EXTRA_TITLE, fileName)
startActivityForResult ( intent, 2 )
}
因为createFile
函数的startActivityForResult
调用了其它应用,所以需要设置onActivityResult
override fun onActivityResult ( requestCode: Int, resultCode: Int, data : Intent? ) {
super . onActivityResult ( requestCode, resultCode, data )
if ( resultCode == RESULT_OK) when ( requestCode) {
2 -> data ? . data? . let {
save2Uri ( it) }
}
}
编写保存文件函数
private fun generateCacheFile ( name: String) = File ( cacheDir, name)
private fun save2Uri ( uri: Uri) {
val outputFile = generateCacheFile ( "output" )
contentResolver. openOutputStream ( uri) ? . let {
val fi = outputFile. inputStream ( )
fi. copyTo ( it)
fi. close ( )
it. close ( )
}
}