我在一个项目中需要给用户自定义保存数据的路径,但是现有的原生方法都是选取文件的,不能只选取文件夹,只好了解一下,做个文件夹路径选取的自定义页面。当然,获取文件路径也一样。
我们需要在AndroidManifest.xml注册两个权限,分别是外置存储的读和写的权限。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这个简单,大家应该都很熟悉,我使用了base类
// 检查权限
fun checkPermission(permission: String) : Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true
return checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
}
// 请求权限
fun reqPermission(permissions: Array<String>, reqCode: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return
requestPermissions(permissions, reqCode)
}
判断权限与请求
if (!checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
!checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) {
reqPermission(arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE),
P_WR_EXTERNAL_STORAGE
)
return
}
请求权限回调
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
val pass = !grantResults.contains(PackageManager.PERMISSION_DENIED)
when(requestCode) {
P_WR_EXTERNAL_STORAGE -> {
// 获取读写权限
if (pass) {
// 更新当前路径文件夹列表
updateArray()
}
}
}
}
FolderInfo.kt
/**
* 文件夹信息
*
* @author D10NG
* @date on 2019-12-06 10:04
*/
data class FolderInfo(
/** 图标 */
var iconRes: Int = R.mipmap.icon_folder,
/** 名称 */
var name: String = "",
/** 子文件个数 */
var sonNum: Long = 0L,
/** 最后修改时间 */
var lastEditTime: String = "",
/** 路径 */
var path: String = ""
) : Serializable {
}
一个常量:最原始最基本的默认路径
private lateinit var baseDirectory: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
baseDirectory = applicationContext.externalCacheDir?.path?: applicationContext.filesDir.path
}
一个变量:当前的文件夹路径
private lateinit var curPath: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
// 获取传递过来的路径
curPath = intent.getStringExtra("path")?: baseDirectory
}
你可以在判断文件夹类型里增加自己想要的文件类型,添加到列表里,显示出来。
/**
* 更新文件夹列表
*/
private fun updateArray() {
folderAdapter.update(getFolderArray(curPath))
}
/**
* 根据路径获取全部文件夹
*/
private fun getFolderArray(path: String): MutableList<FolderInfo> {
val files = File(path).listFiles()?: emptyArray()
val fList = mutableListOf<FolderInfo>()
val fileList = files.asList()
// 文件排序--按照名称排序
Collections.sort(fileList, object : Comparator<File>{
override fun compare(p0: File?, p1: File?): Int {
if (p0 == null) return -1
if (p1 == null) return 1
return p0.name.compareTo(p1.name)
}
})
for (file in fileList.iterator()) {
if (file == null) continue
// 在这里判断文件类型
if (file.isDirectory && !file.isHidden) {
val info = FolderInfo()
info.iconRes = R.mipmap.icon_folder
info.name = file.name
info.path = file.path
info.sonNum = getSonFolderNumber(file.path)
info.lastEditTime = DateUtils.getDateStr(file.lastModified(), "yyyy-MM-dd hh:mm:ss")
fList.add(info)
}
}
return fList
}
/**
* 获取文件夹的子文件夹数量
*/
private fun getSonFolderNumber(path: String) : Long {
var number = 0L
val files = File(path).listFiles()?: emptyArray()
for (file in files.iterator()) {
if (file == null) continue
if (file.isDirectory && !file.isHidden) {
number ++
}
}
return number
}
fun lastPage(view: View) {
// 返回上一页,如果到了尽头提示用户
val file = File(binding.curPath?: baseDirectory)
val parentPath = file.parent
if (parentPath == null) {
showSnackBar(binding.root, "已经是根目录了")
} else {
binding.curPath = parentPath
updateArray()
}
}
主要的逻辑都在上面了,剩下的都是些页面布局之类的定制化的东西就不发出来了。相信各位都可以举一反三。