敏捷冲刺日志 - Day 4

敏捷冲刺日志 - Day 4

站立会议

站立时会议改为线上进行。

  • 昨天已完成的工作:

    • 实现了视频的多选和队列压缩功能。
    • UI 可以正确显示批量压缩的进度。
  • 今天计划完成的工作:

    • 新功能:实现“保存到相册”功能,确保用户压缩的视频能被其他应用(如图库)发现。
    • Bug 调查:开始调查用户反馈的“替换原视频”功能会导致应用闪退的问题。
  • 工作中遇到的困难:

    • MediaStore API 在不同安卓版本上的行为有差异。在 Android 10 (Q) 及以上,需要使用 ContentValuesIS_PENDING 标志位,以确保文件在完全写入前对其他应用不可见,这是一个需要特别注意的细节。
    • 初步排查发现,“替换”闪退是由一个 SecurityException 引起的。这意味着我们的应用没有权限去直接删除用户通过文件选择器(ACTION_GET_CONTENT)提供的原始文件。

项目燃尽图

daf4b569a5df62009fc2686b6b618eee

代码/文档签入记录

  • 代码签入: feat(gallery): Save compressed videos to public gallery & fix(replace): Initial investigation of crash
  • 签入记录对应的Issue内容与链接:
    • Issue: #TASK-003 - 实现“保存到相册”功能, #BUG-001 - “替换”功能闪退
    • 链接: [链接到内部工单系统]
  • Code Review: 编码规范文档无变化。

最新模块的代码

这是新实现的 saveVideoToGallery 方法。它使用了 MediaStore API,能将文件正确地插入到系统的公共电影目录,并处理了新版安卓的 IS_PENDING 机制。

    /**
     * 将指定的视频文件保存到系统公共相册(Movies目录)。
     * @param videoPath 视频文件的本地路径
     * @param showToast 是否显示操作结果的Toast提示
     * @return 返回保存后在MediaStore中的URI,失败则返回null
     */
    private fun saveVideoToGallery(videoPath: String, showToast: Boolean): Uri? {
        val file = File(videoPath)
        if (!file.exists()) {
            if (showToast) Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show()
            return null
        }

        val contentValues = ContentValues().apply {
            put(MediaStore.Video.Media.DISPLAY_NAME, file.name)
            put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
            // 针对 Android Q (10) 及以上版本,使用相对路径和IS_PENDING标志
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES)
                put(MediaStore.Video.Media.IS_PENDING, 1)
            }
        }

        val resolver = contentResolver
        val uri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues)

        if (uri != null) {
            try {
                // 将文件内容写入新的URI
                resolver.openOutputStream(uri).use { outputStream ->
                    file.inputStream().use { inputStream ->
                        inputStream.copyTo(outputStream!!)
                    }
                }
                // 在 Android Q 及以上版本,更新IS_PENDING标志,使文件对其他应用可见
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    contentValues.clear()
                    contentValues.put(MediaStore.Video.Media.IS_PENDING, 0)
                    resolver.update(uri, contentValues, null, null)
                }
                if (showToast) Toast.makeText(this, "视频已保存到相册", Toast.LENGTH_SHORT).show()
                return uri
            } catch (e: Exception) {
                if (showToast) Toast.makeText(this, "保存失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        } else {
            if (showToast) Toast.makeText(this, "无法创建媒体文件", Toast.LENGTH_SHORT).show()
        }
        return null
    }

运行结果的截图

f558df38d7cea79c992f9f8a0a04689b

每日每人总结

  • 刘瑞康 (开发): 在多个安卓版本的模拟器上复现了“替换”闪退问题,并整理了详细的 Logcat 日志。同时为 saveVideoToGallery 方法补充了单元测试,覆盖文件不存在等异常场景。
  • 刘泽昊 (开发): 将“保存到相册”功能集成到批量压缩完成后的流程中,设计了一个简洁的对话框,允许用户一键“全部保存”。
  • 伊尔番 (PM): 已将“替换”闪退问题设为最高优先级,并同步告知用户修复已启动。同时把“保存到相册”功能的成功实现纳入产品亮点清单。
posted @ 2025-12-03 22:18  二熊苏尔  阅读(3)  评论(0)    收藏  举报