有好多的非处女们确实让大家反感,知道为什么吗?其实你们应该检讨下自己!

本文探讨了部分人在恋爱及婚姻选择上的态度变化及其带来的社会争议。作者批评了一些女性在初次恋爱时过于轻率地对待自己的行为,并在寻找终身伴侣时设定过高且偏颇的标准。
有好多的非处女们确实让大家反感,知道为什么吗?其实你们应该检讨下自己! 上学时,为了一份所谓的“爱情”,跟一个要啥没啥的男朋友上床,觉得自己很伟大,把第一次献给了自己所爱的人,他们连一份婚姻承认都没有,更别提什么物质条件,车房了。你们就把自己所有美好的一切给予了。 你们逍遥快活的过了4年,毕业了,男的拍拍屁股走人,为找工作大家各奔前程去了。你们也到了该嫁人的年龄了,于是开始打起了自己的小算盘,要长的帅的,有房,有车,有钱,有权的,我就不明白了,你们到底是在找老公还是找一个饭票?! 扪心自问,你把最美好的青春,身体献给了一个上完拍拍屁股走的不负责的男人,而去难为一个一辈子养你,爱你,呵护你的男人,你的心难道就真的好过吗? 我可不是空口白话的说,你们去看看好多的女人自己和男朋友分手了,就说自己累了,不想在漂泊了,想找个人嫁了,我想问一句,凭什么好男人就应该吃别人“剩饭”,穿别人扔掉的“破鞋”要为别人的错误买一辈子的单?更可气的是还提出一大堆条件,要长相,工作,房车,最好反而人品基本可以忽略不计,完了还要求男的不能嫌弃自己不是处女,搞的好像有处女情节的男人都是龌龊男人,该千刀万剐,还有说的自己永远不能忘记自己的第一个男朋友,你自己是个什么东西呀!!!我说这些话可能会戳到很多有这样想法的女人,同时也戳到你们的痛处,在此不好意思,我发表这个是希望女人们,能明白,男人很辛苦,别去伤害,爱你的男人。摸摸自己的良心,你们心底何曾有过一丝愧疚呢?
<think>我们正在讨论一个关于Android中检查Uri权限的方法。用户提供了一个`hasUriPermission`函数,使用`DocumentFile`来检查权限,但发现新建的Uri没有权限,因此怀疑该方法是否正确。 根据引用[1],内容提供程序需要声明支持细化的URI权限(通过`android:grantUriPermissions`属性或`<grant-uri-permissions>`标记)。这意味着,即使我们使用`DocumentFile`,如果内容提供程序没有正确支持,我们可能无法正确判断权限。 此外,引用[3]提到,当处理一个URI集合时,权限的传递也可能存在问题。 现在,我们来分析用户的方法: ```kotlin fun hasUriPermission(context: Context, uri: Uri): Boolean { return try { val docFile = DocumentFile.fromSingleUri(context, uri) docFile?.canRead() ?: false && docFile?.canWrite() ?: false } catch (e: SecurityException) { false } } ``` 这个方法试图通过`DocumentFile`的`canRead()`和`canWrite()`来判断权限。但是,这里有几个问题: 1. **新建的Uri没有权限**:这是正常的,因为Uri权限需要显式获取(例如通过`Intent.FLAG_GRANT_READ_URI_PERMISSION`和`Intent.FLAG_GRANT_WRITE_URI_PERMISSION`)。在新建Uri时,如果没有通过SAF(存储访问框架)请求权限,那么默认是没有权限的。 2. **DocumentFile的局限性**:`DocumentFile`是一个辅助类,它封装了对`DocumentsProvider`的访问。但是,`canRead()`和`canWrite()`方法实际上是通过检查`DocumentsContract.Document`的`FLAG_SUPPORTS_READ`和`FLAG_SUPPORTS_WRITE`标志来判断的,这些标志表示文档的元数据(即文档是否支持读写),而不是当前应用是否被授予了读写权限。 3. **权限检查的正确方法**:实际上,要检查应用是否对某个Uri有权限,应该使用`ContentResolver`的`checkUriPermission`方法,但这个方法仅适用于`content://`开头的Uri,并且需要内容提供程序支持。更可靠的方法是尝试打开一个文件描述符(如果成功则说明有权限,失败则没有)。 因此,用户的方法可能不正确,因为它检查的是文档本身是否支持读写,而不是当前应用是否有权限。 ### 改进方法 我们可以使用以下两种方法来改进: #### 方法1:使用ContentResolver尝试打开文件 ```kotlin fun hasFilePermission(context: Context, uri: Uri): Boolean { return try { context.contentResolver.openFileDescriptor(uri, "r")?.close() true // 有读权限 } catch (e: SecurityException) { false } catch (e: FileNotFoundException) { false } } ``` 注意:这个方法只检查读权限。如果要同时检查读写权限,可以尝试以读写模式打开(`"rw"`),但要注意,有些内容提供程序可能不支持同时读写。 #### 方法2:检查持久化的权限 如果权限是通过`takePersistableUriPermission`持久化的,我们可以检查系统记录的持久化权限: ```kotlin fun hasPersistedPermission(context: Context, uri: Uri): Boolean { val persistedUriPermissions = context.contentResolver.persistedUriPermissions return persistedUriPermissions.any { it.uri == uri && it.isReadPermission && it.isWritePermission } } ``` 但是,这种方法只能检查持久化权限,临时权限(例如通过`Intent`传递的)不会被记录在这里。 ### 综合方法 结合两种方法,我们可以这样写: ```kotlin fun hasUriPermission(context: Context, uri: Uri, requireWrite: Boolean = true): Boolean { // 首先检查持久化权限(如果有) val persistedList = context.contentResolver.persistedUriPermissions val persisted = persistedList.find { it.uri == uri } if (persisted != null) { if (requireWrite) { return persisted.isWritePermission } return persisted.isReadPermission } // 尝试打开文件来检查 return try { val mode = if (requireWrite) "rw" else "r" context.contentResolver.openFileDescriptor(uri, mode)?.close() true } catch (e: Exception) { false } } ``` 注意:这个方法首先检查持久化权限,如果没有,则尝试打开文件。但是,尝试打开文件可能会触发安全异常或文件不存在异常。 ### 注意事项 1. **权限的临时性和持久性**:通过`Intent`传递的URI权限通常是临时的(在接收Activity存活期间有效),而通过`takePersistableUriPermission`获取的权限是持久的(即使设备重启也有效)。 2. **内容提供程序的实现**:如引用[1]所述,内容提供程序必须声明支持`android:grantUriPermissions`,否则可能无法获取权限。 3. **权限的细化**:在Android 11(API 30)及以上,系统会进一步限制对存储的访问,因此必须使用存储访问框架(SAF)来请求权限。 ### 结论 用户原来的方法不正确,因为它检查的是文档是否支持读写,而不是当前应用是否有权限。我们应该使用`ContentResolver`的`openFileDescriptor`方法来实际验证权限,或者检查系统记录的持久化权限。 ### 改进后的代码 ```kotlin fun hasUriPermission(context: Context, uri: Uri, requireWrite: Boolean = true): Boolean { // 检查是否在持久化权限列表中 val persistedPermissions = context.contentResolver.persistedUriPermissions persistedPermissions.forEach { permission -> if (permission.uri == uri) { if (requireWrite) { return permission.isWritePermission } return permission.isReadPermission } } // 尝试打开文件描述符 return try { val mode = if (requireWrite) "rw" else "r" context.contentResolver.openFileDescriptor(uri, mode)?.close() true } catch (e: Exception) { when (e) { is SecurityException, is FileNotFoundException -> false else -> throw e // 其他异常重新抛出 } } } ``` ### 使用示例 ```kotlin val uri = ... // 你的Uri if (hasUriPermission(context, uri)) { // 有读写权限 } else { // 请求权限 } ``` ### 引用说明 - 引用[1]指出,内容提供程序需要声明支持细化的URI权限[^1]。 - 引用[3]提到,当处理多个URI时,权限传递的问题[^3]。 §§相关问题§§ 1. 如何正确请求对URI的持久化权限? 2. 在Android中,URI权限的临时性和持久性有什么区别? 3. 如何处理内容提供程序不支持URI权限的情况?</think>### Kotlin Android `hasUriPermission()` 方法问题分析 您实现的 `hasUriPermission()` 方法存在几个关键问题,导致无法正确判断 URI 权限。以下是详细分析和改进方案: #### 原始方法的问题 ```kotlin fun hasUriPermission(context: Context, uri: Uri): Boolean { return try { val docFile = DocumentFile.fromSingleUri(context, uri) docFile?.canRead() ?: false && docFile?.canWrite() ?: false } catch (e: SecurityException) { false } } ``` 1. **`DocumentFile` 的局限性** `DocumentFile.canRead()`/`canWrite()` 仅检查**文档元数据**(是否支持读写),而实际权限: ```kotlin // 实际返回的是 DocumentsContract.Document 的 FLAG_SUPPORTS_READ/WRITE // 不验证当前应用是否被授予权限[^1] ``` 2. **新建 URI 无权限的原因** - 通过 SAF (Storage Access Framework) 获取的 URI 需要显式获取权限 - 未持久化的权限仅在当前会话有效(应用重启后失效)[^3] 3. **错误处理不足** `SecurityException` 无法覆盖所有权限错误场景(如文件不存在、权限撤销等) --- ### 正确实现方案 #### 方法 1:直接通过 ContentResolver 验证(推荐) ```kotlin fun hasUriPermission(context: Context, uri: Uri, requireWrite: Boolean = true): Boolean { return try { // 尝试打开文件描述符 val mode = if (requireWrite) "rw" else "r" context.contentResolver.openFileDescriptor(uri, mode)?.use { // 成功打开说明有权限 true } ?: false } catch (e: FileNotFoundException) { false // 文件不存在 } catch (e: SecurityException) { false // 无权限 } catch (e: UnsupportedOperationException) { false // URI 方案不支持 } } ``` #### 方法 2:检查持久化权限记录 ```kotlin fun hasPersistedUriPermission(context: Context, uri: Uri): Boolean { val persistedPermissions = context.contentResolver.persistedUriPermissions return persistedPermissions.any { it.uri == uri && it.isReadPermission && it.isWritePermission } } ``` --- ### 完整权限管理方案 #### 1. 请求 URI 权限 ```kotlin private val permissionLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { result.data?.data?.let { uri -> // 获取持久化权限 context.contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) } } } fun requestUriPermission(uri: Uri) { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { setDataAndType(uri, "*/*") addCategory(Intent.CATEGORY_OPENABLE) addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) } permissionLauncher.launch(intent) } ``` #### 2. 权限检查流程 ```mermaid graph TD A[获取保存的URI] --> B{hasPersistedUriPermission} B -- 有持久化权限 --> C[直接使用] B -- 无持久化权限 --> D{hasUriPermission<br>实时检查} D -- 有临时权限 --> E[尝试持久化] D -- 无权限 --> F[请求新权限] ``` --- ### 关键注意事项 1. **URI 权限类型**: - **临时权限**:通过 `Intent.FLAG_GRANT_READ_URI_PERMISSION` 传递,接收方销毁后失效 - **持久化权限**:通过 `takePersistableUriPermission()` 获取,需用户显式同意[^1] 2. **Android 版本差异**: ```kotlin // Android 10+ 必须使用 SAF 访问共享文件 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // 强制使用 ContentResolver } ``` 3. **内容提供程序支持**: - 提供程序需声明 `<grant-uri-permissions>` 或 `android:grantUriPermissions`[^1] - 系统应用(如媒体库)已支持,自定义提供程序需实现权限验证 4. **资源 URI 处理**: 对于 `android.resource://` 类型的 URI(如引用[4]),直接视为有权限: ```kotlin fun isResourceUri(uri: Uri) = uri.scheme == ContentResolver.SCHEME_ANDROID_RESOURCE ``` > **实测建议**:使用 `adb shell content query --uri content://media/external/audio/media` 验证权限状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值