设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间14 现在时间14 缓存数据 “你总爱编织谎言,我总是配合表演。”

“你总爱编织谎言,我总是配合表演。” -- 配合

查看: 338|回复: 0

Android kotlin语言实现删除文件的解决方案

[复制链接]

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
31
主题
27
精华
0
金钱
96
积分
60
注册时间
2023-9-29
最后登录
2025-5-31

发表于 2025-5-31 06:47:23 | 显示全部楼层 |阅读模式
一、前言

在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的这种操作就显得尤为重要了。但是在Android11+的操作系统中,权限声明变得复杂了起来,而且大多数的解决方案多为Java语言,kotlin语言的解决方案甚少,而且大多数的解决方案也没有用。
本人也是寻求多日无果后尝试多种解决方案拼合最终发现的本解决方案,在这里给广大开发者同志们提供一个模板,各位同志可以在本模版的基础上进行改写,从而减少无谓查询资料工作。

二、适用环境

语言:kotlin
操作系统版本:Android7+(本方案已经对Android11+和Android7-10进行了区分,可以放心使用)

三、模板内容


1.权限申请

首先在AndroidManifest.xml中必须注册这三项权限:
  1. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  3. <uses-permission
  4.         android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
  5.         tools:ignore="ScopedStorage" />
复制代码
完整的AndroidManifest.xml示例如下所示:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:tools="http://schemas.android.com/tools">
  4.     <application
  5.         android:allowBackup="true"
  6.         android:dataExtractionRules="@xml/data_extraction_rules"
  7.         android:fullBackupContent="@xml/backup_rules"
  8.         android:icon="@mipmap/ic_launcher"
  9.         android:label="@string/app_name"
  10.         android:roundIcon="@mipmap/ic_launcher_round"
  11.         android:supportsRtl="true"
  12.         android:theme="@style/Theme.AbstractFunctionDemo"
  13.         tools:targetApi="31">
  14.         <activity
  15.             android:name=".MainActivity"
  16.             android:exported="true">
  17.             <intent-filter>
  18.                 <action android:name="android.intent.action.MAIN" />
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.             </intent-filter>
  21.         </activity>
  22.     </application>
  23.     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  24.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  25.     <uses-permission
  26.         android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
  27.         tools:ignore="ScopedStorage" />
  28. </manifest>
复制代码
2.Activity中的模板

本人在模板中按步骤写了注释了,广大开发者同志在复制走后,按照注释的流程消化,然后进行简单的改写即可。
完整模板(MainActivity.kt)如下:
  1. package com.example.abstractfunctiondemo
  2. import android.os.Bundle
  3. import androidx.activity.enableEdgeToEdge
  4. import androidx.appcompat.app.AppCompatActivity
  5. import androidx.core.view.ViewCompat
  6. import androidx.core.view.WindowInsetsCompat
  7. import android.Manifest
  8. import android.app.Activity
  9. import android.content.ContentUris
  10. import android.content.ContentValues
  11. import android.content.Context
  12. import android.content.Intent
  13. import android.content.pm.PackageManager
  14. import android.provider.Settings
  15. import android.net.Uri
  16. import android.os.Build
  17. import android.os.Environment
  18. import android.provider.DocumentsContract
  19. import android.provider.MediaStore
  20. import android.provider.OpenableColumns
  21. import android.util.Log
  22. import android.widget.Toast
  23. import androidx.activity.result.contract.ActivityResultContracts
  24. import androidx.core.app.ActivityCompat
  25. import androidx.core.content.ContextCompat
  26. import androidx.documentfile.provider.DocumentFile
  27. import com.google.android.material.button.MaterialButton
  28. import java.io.File
  29. import java.io.FileInputStream
  30. import java.io.FileOutputStream
  31. import java.io.OutputStream
  32. class MainActivity : AppCompatActivity() {
  33.     /**
  34.      * 1.定义选择器的公共变量
  35.      *
  36.      * 定义这个全局变量是因为必须在onCreate的时候就注册,
  37.      * 不可以现用现注册
  38.      */
  39.     private lateinit var filePickerLauncher: androidx.activity.result.ActivityResultLauncher<Intent>
  40.     private var onFilePicked: ((String) -> Unit)? = null
  41.     /**
  42.      * 定义目标文件路径的公共变量
  43.      */
  44.     private var sourceFilePath: String? = null
  45.     override fun onCreate(savedInstanceState: Bundle?) {
  46.         super.onCreate(savedInstanceState)
  47.         enableEdgeToEdge()
  48.         setContentView(R.layout.activity_main)
  49.         ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
  50.             val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
  51.             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
  52.             insets
  53.         }
  54.         /**
  55.          * 5.注册文件选择器
  56.          */
  57.         filePickerLauncher =
  58.             registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
  59.                 if (result.resultCode == Activity.RESULT_OK) {
  60.                     val uri: Uri? = result.data?.data
  61.                     if (uri != null) {
  62.                         Log.e("选取文件", "选择的文件 URI: $uri")
  63.                         onFilePicked?.invoke(uri.toString()) // ✅ 直接返回 `Uri`
  64.                         deleteFileByUri(uri) // ✅ 直接用 `Uri` 删除
  65.                         Log.e("选取文件", "执行结束")
  66.                     } else {
  67.                         Toast.makeText(this, "无法获取文件", Toast.LENGTH_SHORT).show()
  68.                     }
  69.                 } else {
  70.                     Toast.makeText(this, "未选择文件", Toast.LENGTH_SHORT).show()
  71.                 }
  72.             }
  73.         val testButton2: MaterialButton = findViewById(R.id.testButton2)
  74.         testButton2.setOnClickListener {
  75.             /**
  76.              * 6.调用
  77.              */
  78.             if (checkAndRequestPermissions()) {
  79.                 pickFile()
  80.             }
  81.         }
  82.     }
  83.     /**
  84.      * 2.定义文件选择器激活函数
  85.      */
  86.     private fun pickFile() {
  87.         filePickerLauncher.launch(Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
  88.             addCategory(Intent.CATEGORY_OPENABLE)
  89.             type = "*/*"
  90.         })
  91.     }
  92.     /**
  93.      * 3.定义URI解析函数
  94.      */
  95.     private fun getFilePathFromUri(uri: Uri): String? {
  96.         val context = applicationContext
  97.         var filePath: String? = null
  98.         if (uri.scheme == "content") {
  99.             val projection = arrayOf(MediaStore.Files.FileColumns.DATA)
  100.             context.contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
  101.                 if (cursor.moveToFirst()) {
  102.                     val columnIndex =
  103.                         cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA)
  104.                     filePath = cursor.getString(columnIndex)
  105.                 }
  106.             }
  107.         }
  108.         return filePath
  109.     }
  110.     /**
  111.      * 4.定义文件删除函数
  112.      */
  113.     private fun deleteFileByUri(uri: Uri) {
  114.         try {
  115.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  116.                 // ✅ Android 10+ 需要用 `DocumentsContract.deleteDocument()`
  117.                 val deleted = DocumentsContract.deleteDocument(contentResolver, uri)
  118.                 if (deleted) {
  119.                     Log.e("删除文件", "文件删除成功: $uri")
  120.                     Toast.makeText(this, "文件删除成功", Toast.LENGTH_SHORT).show()
  121.                 } else {
  122.                     Log.e("删除文件", "文件删除失败: $uri")
  123.                     Toast.makeText(this, "无法删除文件", Toast.LENGTH_SHORT).show()
  124.                 }
  125.             } else {
  126.                 // ✅ Android 9 及以下,尝试转换为文件路径
  127.                 val filePath = getFilePathFromUri(uri)
  128.                 if (filePath != null) {
  129.                     val file = File(filePath)
  130.                     if (file.exists() && file.delete()) {
  131.                         Log.e("删除文件", "文件删除成功: $filePath")
  132.                         Toast.makeText(this, "文件删除成功", Toast.LENGTH_SHORT).show()
  133.                     } else {
  134.                         Log.e("删除文件", "文件删除失败: $filePath")
  135.                         Toast.makeText(this, "无法删除文件", Toast.LENGTH_SHORT).show()
  136.                     }
  137.                 } else {
  138.                     Toast.makeText(this, "无法获取文件路径,尝试手动删除", Toast.LENGTH_SHORT).show()
  139.                 }
  140.             }
  141.         } catch (e: Exception) {
  142.             e.printStackTrace()
  143.             Toast.makeText(this, "删除文件出错: ${e.message}", Toast.LENGTH_SHORT).show()
  144.         }
  145.     }
  146. }
复制代码
以上就是Android kotlin语言实现删除文件的解决方案的详细内容,更多关于Android kotlin删除文件的资料请关注晓枫资讯其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表