You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Jetpack Compose中仅选图库视频及推荐上传方案?

在Jetpack Compose中实现视频上传功能

一、Compose中仅选择视频的实现

在Compose中选择视频依然依赖Android的Intent体系,但需要配合Activity Result API和Compose的rememberLauncherForActivityResult来处理结果,替代传统的startActivityForResult写法。

实现步骤:

  1. 定义视频选择器Launcher
    使用ActivityResultContracts.GetContent并指定MIME类型为video/*,限制仅能选择视频文件:

    val videoPickerLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.GetContent()
    ) { uri: Uri? ->
        uri?.let {
            // 处理选中的视频Uri,比如暂存Uri用于后续上传流程
        }
    }
    
  2. 添加触发选择的UI按钮
    在Compose布局中添加交互按钮,点击时启动视频选择器:

    Button(onClick = { videoPickerLauncher.launch("video/*") }) {
        Text("选择视频")
    }
    
  3. 可选:将Uri转换为本地文件
    如果需要将Uri转为可直接操作的File对象,可通过ContentResolver实现:

    fun getVideoFileFromUri(context: Context, uri: Uri): File? {
        val contentResolver = context.contentResolver
        val inputStream = contentResolver.openInputStream(uri) ?: return null
        val tempFile = File(context.cacheDir, "temp_video_${System.currentTimeMillis()}.mp4")
        inputStream.use { input ->
            tempFile.outputStream().use { output ->
                input.copyTo(output)
            }
        }
        return tempFile
    }
    

二、视频上传方案推荐

1. Retrofit + OkHttp Multipart(首选,原生稳定)

你计划的Retrofit Multipart方案完全可行,这是Android文件上传的标准方案——Retrofit底层基于OkHttp,天然复用OkHttp的超时配置、拦截器等特性,无需额外依赖。

实现示例:

  • 定义Retrofit上传接口:

    interface VideoUploadApi {
        @Multipart
        @POST("upload/video")
        suspend fun uploadVideo(
            @Part video: MultipartBody.Part,
            @Part("title") title: RequestBody // 可选的额外参数
        ): Response<UploadResult> // UploadResult为自定义的响应实体类
    }
    
  • 构建Multipart请求并执行上传:

    fun prepareVideoPart(file: File): MultipartBody.Part {
        val requestBody = file.asRequestBody("video/mp4".toMediaTypeOrNull())
        return MultipartBody.Part.createFormData(
            name = "video_file", // 对应后端接收的参数名
            filename = file.name,
            body = requestBody
        )
    }
    
    // 在ViewModel或Repository中调用上传逻辑
    suspend fun uploadVideo(file: File, title: String) {
        val videoPart = prepareVideoPart(file)
        val titleBody = title.toRequestBody("text/plain".toMediaTypeOrNull())
        val response = videoUploadApi.uploadVideo(videoPart, titleBody)
        if (response.isSuccessful) {
            // 上传成功后的处理逻辑
        } else {
            // 上传失败的错误处理
        }
    }
    

2. 大视频上传优化(可选)

如果上传的视频文件较大(如100MB以上),可以添加以下优化:

  • 上传进度监听:自定义OkHttp的RequestBody来实时获取上传进度:

    class ProgressRequestBody(
        private val delegate: RequestBody,
        private val onProgress: (Int) -> Unit
    ) : RequestBody() {
        override fun contentType(): MediaType? = delegate.contentType()
    
        override fun writeTo(sink: BufferedSink) {
            val bufferedSink = object : ForwardingSink(sink) {
                var bytesWritten = 0L
                var contentLength = 0L
    
                override fun write(source: Buffer, byteCount: Long) {
                    super.write(source, byteCount)
                    if (contentLength == 0L) contentLength = contentLength()
                    bytesWritten += byteCount
                    onProgress(((bytesWritten * 100) / contentLength).toInt())
                }
            }
            delegate.writeTo(BufferedSink(bufferedSink))
        }
    }
    

    使用时将file.asRequestBody()替换为ProgressRequestBody(...)即可获取实时进度。

  • 断点续传:需后端配合支持范围请求(Range Header),记录已上传字节数,下次上传时从断点处继续,避免重复上传已完成部分。

3. 其他可选方案

如果需要后台稳定上传,可结合AndroidX的WorkManager封装上传任务,避免页面销毁导致上传中断,但核心的文件上传逻辑依然依赖Retrofit/OkHttp的Multipart机制。


内容的提问来源于stack exchange,提问作者Ahmed Rabee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:34:43