|
一、前言
在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的这种操作就显得尤为重要了。但是在Android11+的操作系统中,权限声明变得复杂了起来,而且大多数的解决方案多为Java语言,kotlin语言的解决方案甚少,而且大多数的解决方案也没有用。
本人也是寻求多日无果后尝试多种解决方案拼合最终发现的本解决方案,在这里给广大开发者同志们提供一个模板,各位同志可以在本模版的基础上进行改写,从而减少无谓查询资料工作。
二、适用环境
语言:kotlin
操作系统版本:Android7+(本方案已经对Android11+和Android7-10进行了区分,可以放心使用)
三、模板内容
1.权限申请
首先在AndroidManifest.xml中必须注册这三项权限: - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission
- android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
- tools:ignore="ScopedStorage" />
复制代码完整的AndroidManifest.xml示例如下所示: - <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools">
- <application
- android:allowBackup="true"
- android:dataExtractionRules="@xml/data_extraction_rules"
- android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/Theme.AbstractFunctionDemo"
- tools:targetApi="31">
- <activity
- android:name=".MainActivity"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission
- android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
- tools:ignore="ScopedStorage" />
- </manifest>
复制代码 2.Activity中的模板
本人在模板中按步骤写了注释了,广大开发者同志在复制走后,按照注释的流程消化,然后进行简单的改写即可。
完整模板(MainActivity.kt)如下: - package com.example.abstractfunctiondemo
- import android.os.Bundle
- import androidx.activity.enableEdgeToEdge
- import androidx.appcompat.app.AppCompatActivity
- import androidx.core.view.ViewCompat
- import androidx.core.view.WindowInsetsCompat
- import android.Manifest
- import android.app.Activity
- import android.content.ContentUris
- import android.content.ContentValues
- import android.content.Context
- import android.content.Intent
- import android.content.pm.PackageManager
- import android.provider.Settings
- import android.net.Uri
- import android.os.Build
- import android.os.Environment
- import android.provider.DocumentsContract
- import android.provider.MediaStore
- import android.provider.OpenableColumns
- import android.util.Log
- import android.widget.Toast
- import androidx.activity.result.contract.ActivityResultContracts
- import androidx.core.app.ActivityCompat
- import androidx.core.content.ContextCompat
- import androidx.documentfile.provider.DocumentFile
- import com.google.android.material.button.MaterialButton
- import java.io.File
- import java.io.FileInputStream
- import java.io.FileOutputStream
- import java.io.OutputStream
- class MainActivity : AppCompatActivity() {
- /**
- * 1.定义选择器的公共变量
- *
- * 定义这个全局变量是因为必须在onCreate的时候就注册,
- * 不可以现用现注册
- */
- private lateinit var filePickerLauncher: androidx.activity.result.ActivityResultLauncher<Intent>
- private var onFilePicked: ((String) -> Unit)? = null
- /**
- * 定义目标文件路径的公共变量
- */
- private var sourceFilePath: String? = null
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContentView(R.layout.activity_main)
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
- val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
- insets
- }
- /**
- * 5.注册文件选择器
- */
- filePickerLauncher =
- registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
- if (result.resultCode == Activity.RESULT_OK) {
- val uri: Uri? = result.data?.data
- if (uri != null) {
- Log.e("选取文件", "选择的文件 URI: $uri")
- onFilePicked?.invoke(uri.toString()) // ✅ 直接返回 `Uri`
- deleteFileByUri(uri) // ✅ 直接用 `Uri` 删除
- Log.e("选取文件", "执行结束")
- } else {
- Toast.makeText(this, "无法获取文件", Toast.LENGTH_SHORT).show()
- }
- } else {
- Toast.makeText(this, "未选择文件", Toast.LENGTH_SHORT).show()
- }
- }
- val testButton2: MaterialButton = findViewById(R.id.testButton2)
- testButton2.setOnClickListener {
- /**
- * 6.调用
- */
- if (checkAndRequestPermissions()) {
- pickFile()
- }
- }
- }
- /**
- * 2.定义文件选择器激活函数
- */
- private fun pickFile() {
- filePickerLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
- addCategory(Intent.CATEGORY_OPENABLE)
- type = "*/*"
- })
- }
- /**
- * 3.定义URI解析函数
- */
- private fun getFilePathFromUri(uri: Uri): String? {
- val context = applicationContext
- var filePath: String? = null
- if (uri.scheme == "content") {
- val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
- context.contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
- if (cursor.moveToFirst()) {
- val columnIndex =
- cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)
- filePath = cursor.getString(columnIndex)
- }
- }
- }
- return filePath
- }
- /**
- * 4.定义文件删除函数
- */
- private fun deleteFileByUri(uri: Uri) {
- try {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- // ✅ Android 10+ 需要用 `DocumentsContract.deleteDocument()`
- val deleted = DocumentsContract.deleteDocument(contentResolver, uri)
- if (deleted) {
- Log.e("删除文件", "文件删除成功: $uri")
- Toast.makeText(this, "文件删除成功", Toast.LENGTH_SHORT).show()
- } else {
- Log.e("删除文件", "文件删除失败: $uri")
- Toast.makeText(this, "无法删除文件", Toast.LENGTH_SHORT).show()
- }
- } else {
- // ✅ Android 9 及以下,尝试转换为文件路径
- val filePath = getFilePathFromUri(uri)
- if (filePath != null) {
- val file = File(filePath)
- if (file.exists() && file.delete()) {
- Log.e("删除文件", "文件删除成功: $filePath")
- Toast.makeText(this, "文件删除成功", Toast.LENGTH_SHORT).show()
- } else {
- Log.e("删除文件", "文件删除失败: $filePath")
- Toast.makeText(this, "无法删除文件", Toast.LENGTH_SHORT).show()
- }
- } else {
- Toast.makeText(this, "无法获取文件路径,尝试手动删除", Toast.LENGTH_SHORT).show()
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Toast.makeText(this, "删除文件出错: ${e.message}", Toast.LENGTH_SHORT).show()
- }
- }
- }
复制代码以上就是Android kotlin语言实现删除文件的解决方案的详细内容,更多关于Android kotlin删除文件的资料请关注晓枫资讯其它相关文章!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|