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

 更新时间:2025年02月03日 11:01:41   作者:ElsaArendelle  
这篇文章主要介绍了Android kotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的这种操作就显得尤为重要了,需要的朋友可以参考下

一、前言

在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的这种操作就显得尤为重要了。但是在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删除文件的资料请关注脚本之家其它相关文章!

相关文章

  • Kotlin中标准函数run、with、let、also与apply的使用和区别详解

    Kotlin中标准函数run、with、let、also与apply的使用和区别详解

    相比Java, Kotlin提供了不少高级语法特性。对于一个Kotlin的初学者来说经常会写出一些不够优雅的代码,下面这篇文章主要给大家介绍了关于Kotlin中标准函数run、with、let、also与apply的使用和区别的相关资料,需要的朋友可以参考下。
    2018-03-03
  • Android中Retrofit库的高级使用与原理

    Android中Retrofit库的高级使用与原理

    在 Android 开发中,网络请求是一个极为关键的部分,Retrofit 作为一个强大的网络请求库,能够简化开发流程,提供高效的网络请求能力,本文将深入介绍 Retrofit 的高级使用与原理,帮助读者更全面地理解和应用这一库,需要的朋友可以参考下
    2023-08-08
  • Android Studio 下自动注释(自定义作者,类作用等)图文详解

    Android Studio 下自动注释(自定义作者,类作用等)图文详解

    android studio 下自动注释功能居然被隐藏了,很多功能都不见了,下面小编通过本文给大家分享Android Studio 下自动注释(自定义作者,类作用等)图文详解,需要的朋友参考下吧
    2017-11-11
  • Android写一个实时输入框功能

    Android写一个实时输入框功能

    这篇文章主要介绍了Android写一个实时输入框功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Android 下载网络图片并显示到本地

    Android 下载网络图片并显示到本地

    本文主要介绍了Android实现下载网络图片并显示到本地功能的示例代码。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03
  • Android onClick按钮单击事件的四种常用写法

    Android onClick按钮单击事件的四种常用写法

    本文主要介绍了Android onClick按钮单击事件的四种常用写法,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • android微信支付源码分享

    android微信支付源码分享

    这篇文章主要为大家详细介绍了android微信支付源码,具有一定的实用性和参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • ListView滑动隐藏显示ToolBar的实例

    ListView滑动隐藏显示ToolBar的实例

    下面小编就为大家分享一篇ListView滑动隐藏显示ToolBar的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Android仿直播特效之点赞飘心效果

    Android仿直播特效之点赞飘心效果

    这篇文章主要为大家详细介绍了Android实现点赞飘心效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • android4.0屏蔽HOME键的简单实现

    android4.0屏蔽HOME键的简单实现

    这篇文章主要介绍了android4.0屏蔽HOME键的简单实现,需要的朋友可以参考下
    2014-02-02

最新评论