Android

关注公众号 jb51net

关闭
首页 > 软件编程 > Android > Android临时授权读写用户文件

Android无需读写权限通过临时授权读写用户文件详解

作者:用户5944254635000

这篇文章主要为大家介绍了Android无需读写权限通过临时授权读写用户文件详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

在进行需求开发的时候,我们总是避不开和用户的数据打交道,那提到获取用户的数据一定会想到的东西就是申请权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在我刚学习安卓的时候,我是以为APP一定要声明了读写用户空间权限并且在用户授权之后才能获取到用户的文件,即使是做个简简单单的更换头像的功能,或者是升级APP时下载新的APK。对于后者,我们其实可以将升级的APK包放到我们应用的私有目录下(无需权限),对于前者,有什么比较轻量,适合快速开发需求的方法来满足呢。

这里插三段小说明,如果只想知道方法的可以直接跳过

模拟获取用户的图片的逻辑

我们需要拿到代表用户临时授权给APP的Uri

通过

val intent = Intent(Intent.ACTION_GET_CONTENT)
    .addCategory(Intent.CATEGORY_OPENABLE)
    //这里传的参数是你要获取的文件类型的mimeType
    .setType(mimeType)
startActivityForResult(intent,1024)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 1024 && resultCode == RESULT_OK) {
        val uri = data?.data
        //这里获取到的uri就是用户临时授权的文件/文件夹的的标识
    }
}

或者

val launch = registerForActivityResult(ActivityResultContracts.GetContent()){uri-> 
//这里获取到的uri就是用户临时授权的文件/文件夹的的标识
}
//这里传的参数是你要获取的文件类型的mimeType
launch.launch("*/*")

启动系统的内容选择器让用户选择要分享给我们APP的文件,以获得文件的Uri

通过contentResolver打开文件的文件描述符FileDescriptor

val pfd : ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(uri, "r")

第一个参数是我们刚刚得到的文件的uri,第二个文件是表示我们对文件的操作模式,我现在示范的是读取用户图片所以用只读模式("r")就可以了,关于mode的具体注释,这里我直接粘贴原文了

mode – The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" or "rwt". SeeParcelFileDescriptor.parseMode for more details.

通过FileDescriptor可以打开一个文件IO流(FIS或者FOS),就可以读写文件啦

FileInputStream(pfd.fileDescriptor).use {
//这里可以先将用户的图片复制到私有目录中,再让用户做进一步的编辑操作
}
FileOutputStream(pfd.fileDescriptor).use {
}

但是注意,打开的fileDescriptor是Closeable对象,所以用完之后需要手动close(),这里我用的是ktolin的扩展函数,会在use代码块里的代码运行完之后自动关闭流

另一种读取文件的方法,还是使用contentResolver直接打开io流

context.contentResolver.openInputStream(uri)?.use {
}
context.contentResolver.openOutputStream(uri)?.use {
}

模拟将文件写入用户目录的操作

其实思路是一模一样的,只是你启动文件系统的意图(intent)不一样,以及对文件的操作不一样

我们需要拿到代表用户临时授权给APP的Uri

//这里传入你要创建的文件类型的mimeType,如果是"*/*"那就代表文件夹
val launcher = registerForActivityResult(ActivityResultContracts.CreateDocument("*/*")){uri->
    //这里获取到的uri是已经创建好的文件的uri
}
//这里传入要创建的文件名
launcher.launch("cache.png")

启动之后是这个界面

通过contentResolver打开文件的文件描述符FileDescriptor

val pfd : ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(uri, "rw")

第一个参数是我们刚刚得到的文件的uri,第二个文件是表示我们对文件的操作模式,我现在示范的是保存一张图片所以要用读写模式("rw")

通过FileDescriptor可以打开一个文件IO流(FIS或者FOS),就可以写文件啦

FileOutputStream(pfd.fileDescriptor).use {
//这里将处理好的图片利用fos写到用户刚才用uri指定的地方
}

另一种读取文件的方法,还是使用contentResolver直接打开io流

context.contentResolver.openOutputStream(uri)?.use {
}

模拟获取用户文件夹控制权的操作

最后再模拟一下获取用户文件夹控制权的操作,通过这个方法你可以拿到其他应用在外置存储里的目录(例如一些聊天软件的聊天记录其实就是存放在这个目录的)

(先截了张图,过两天填坑)

通过Uri获取文件信息

最后再介绍一 通过Uri获取文件信息(文件名/文件大小/文件Mime类型)的方法

//第二个参数相当于是sql里的select,列表里是要过滤的列名,如果传null那说明取所有的列,这样性能会比较差
val cursor: Cursor? = context.contentResolver.query(
    this,
    arrayOf(MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.SIZE),
    null,
    null,
    null
)?.use { cursor ->
    if (cursor.moveToFirst()) {
        val columnIndex1 = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
        if (columnIndex1 > -1) {
            name = cursor.getString(columnIndex1)
        }
        val columnIndex2 = cursor.getColumnIndex(MediaStore.MediaColumns.SIZE)
        if (columnIndex2 > -1) {
            size = cursor.getLong(columnIndex2)
        }
    }

文件的话,用正常途径也只能拿到文件名(MediaStore.MediaColumns.DISPLAY_NAME),文件大小(MediaStore.MediaColumns.SIZE),文件Mime类型(MediaStore.MediaColumns.MIME_TYPE)这三个有用的信息 注意,获取到的cursor是Closeable对象,所以用完之后需要手动close()

以上就是Android无需读写权限通过临时授权读写用户文件详解的详细内容,更多关于Android临时授权读写用户文件的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文