三星Galaxy Watch4录音文件上传AWS S3失败的代码修改咨询
解决AWS S3上传时的JobCancellationException问题
核心原因分析
kotlinx.coroutines.JobCancellationException 本质是上传过程中协程被提前终止,常见触发场景:
- 协程作用域与生命周期绑定过紧(比如用
viewModelScope但页面销毁,或手表应用后台被系统回收) - 文件读取/网络请求未做超时处理
- 录音完成后未正确关闭文件流,导致上传时文件无法读取
- AWS SDK调用未在IO调度器执行,阻塞主线程引发协程取消
针对性修改方案
1. 选择独立的协程作用域
避免使用与UI生命周期强绑定的作用域,改用不受页面销毁影响的独立作用域:
private val uploadScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
2. 确保录音文件可正常读取
录音结束后必须关闭相关流,上传前校验文件有效性:
// 录音完成后的收尾操作 private fun finishRecording() { recorder?.stop() recorder?.release() outputStream?.flush() outputStream?.close() // 必须关闭输出流,否则文件可能处于锁定状态 } // 上传前校验文件 private fun isValidRecordingFile(file: File): Boolean { return file.exists() && file.canRead() && file.length() > 0 }
3. 修改uploadFile函数,增加超时与异常处理
给上传任务添加超时限制,捕获取消异常并补充必要的错误处理:
fun uploadToS3(file: File, bucketName: String, s3Key: String) { uploadScope.launch { try { withTimeout(30000) { // 30秒超时限制 if (!isValidRecordingFile(file)) { throw IllegalArgumentException("录音文件无效或不可读") } // 初始化S3客户端(建议用Cognito身份池,避免硬编码密钥) val s3Client = AmazonS3ClientBuilder.standard() .withRegion(Regions.AP_SOUTHEAST_1) // 替换为你的存储桶区域 .build() val putRequest = PutObjectRequest(bucketName, s3Key, file) .withCannedAcl(CannedAccessControlList.Private) // 执行上传 s3Client.putObject(putRequest) // 上传成功后的逻辑:比如通知用户、删除本地文件 } } catch (e: TimeoutCancellationException) { Log.e("S3Upload", "上传超时", e) } catch (e: JobCancellationException) { Log.e("S3Upload", "上传任务被取消", e) // 可选:添加重试逻辑 } catch (e: Exception) { Log.e("S3Upload", "上传失败", e) } } }
4. 适配手表后台运行限制
Galaxy Watch4的Wear OS对后台任务有严格限制,需启动前台服务确保上传不被系统终止:
private fun startUploadForeground() { val notification = NotificationCompat.Builder(this, "UPLOAD_CHANNEL") .setContentTitle("正在上传录音") .setSmallIcon(R.drawable.ic_upload) .build() startForeground(1, notification) }
在uploadToS3函数开头调用此方法,上传完成后调用stopForeground(true)关闭前台服务。
5. 依赖库版本兼容检查
确保AWS SDK与协程版本匹配,建议使用稳定版:
// AWS S3 SDK implementation 'com.amazonaws:aws-android-sdk-s3:2.74.0' // Kotlin协程 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
关键注意事项
- 避免硬编码AWS密钥,建议使用Cognito身份池进行身份验证
- 录音文件存储路径选择
getExternalFilesDir(Environment.DIRECTORY_MUSIC),确保应用有权限访问 - 测试时保持手表网络稳定,避免上传过程中断网
内容的提问来源于stack exchange,提问作者Pranay
相关产品推荐
相关产品推荐

