android - registerForActivityResult(ActivityResultContracts.TakeVideo()) 始终为空
问题描述
我使用以下代码来捕获视频。一切正常,但在捕获视频后, registerForActivityResult(ActivityResultContracts.TakeVideo())
始终为空。捕获的视频存在于给定路径中。我可以通过什么方式解决这个问题?
private fun openCameraForMovie() {
val packageManager = requireContext().packageManager
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also { takeVideoIntent ->
takeVideoIntent.resolveActivity(packageManager)?.also {
startRecording()
}
}
}
private fun startRecording() {
try {
val root = File(
requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
.toString() + "/media/"
)
if (!root.exists()) {
root.mkdir()
}
val videoName = "vid_" + System.currentTimeMillis() + ".mp4"
val sdImageMainDirectory = File(root, videoName)
var fileUri: Uri? = FileProvider.getUriForFile(
requireContext(),
context?.applicationContext?.packageName + ".provider",
sdImageMainDirectory
) ?: return
mViewModel.videoUri.postValue(fileUri)
} catch (ex: Exception) {
Timber.d("startRecording ${ex.localizedMessage}")
}
}
此代码始终为空:
private val recordVideoResult =
registerForActivityResult(ActivityResultContracts.TakeVideo()) { it ->
try {
if (it != null) {
Timber.d(">>>> Video Bitmap: $it")
}
} catch (ex: Exception) {
Timber.d(">>>> Video Bitmap: ${ex.localizedMessage}")
}
}
解决方案
发生了什么?
将
ActivityResultContract
视频保存到提供的内容Uri
中 - 。返回缩略图。
来源TakeVideo 文档,强调我的。
您不想要缩略图(无论如何这是可选的),您想要Uri
指向实际视频的缩略图。但是您已经知道Uri
, 因为您提供了它作为输入。
怎么办?
完成这项工作需要几个步骤:
将输入存储
Uri
在变量中并正确处理保存的状态,这样当您从相机应用程序返回时,您的应用程序就知道您一直在录制视频。编写自定义
TakeVideo
合同,如果视频捕获成功则返回。Bitmap
不能使用检查非空预览,因为预览是可选的。
它可能看起来像这样:
private AtomicReference<Uri> recordingUri = new AtomicReference<>();
private ActivityResultLauncher<Uri> recordVideoResult =
registerForActivityResult(new TakeVideo2(), success -> {
final Uri uri = recordingUri.getAndSet(null);
if (success) {
// Do something with the video.
}
});
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
// ...
if (savedInstanceState != null) {
recordingUri.set(savedInstanceState.getParcelable("recordingUri"));
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
// ...
outState.putParcelable("recordingUri", recordingUri.get());
}
private void startRecording() {
final Uri uri = // ...;
recordingUri.set(uri);
recordVideoResult.launch(uri);
}
public static class TakeVideo2 extends ActivityResultContract<Uri, Boolean> {
@CallSuper
@NonNull
@Override
public Intent createIntent(@NonNull Context context, @NonNull Uri input) {
return new Intent(MediaStore.ACTION_VIDEO_CAPTURE)
.putExtra(MediaStore.EXTRA_OUTPUT, input);
}
@Nullable
@Override
public final SynchronousResult<Boolean> getSynchronousResult(@NonNull Context context,
@NonNull Uri input) {
return null;
}
@Override
public final Boolean parseResult(int resultCode, @Nullable Intent intent) {
return resultCode == Activity.RESULT_OK;
}
}
推荐阅读
- javascript - Javascript:将 JSON 字符串转换为 ES6 映射或其他以保留键的顺序
- c++ - 如何使用 std::regex_replace 将字符串替换为小写?
- java - 实现 SparseMatrix 的有效方法
- protractor - 我们可以将 AfterAll 函数中的数据获取到量角器中的 afterLaunch 吗
- python - 使用 keras_model_sequential() 在 R 中调用 keras 时出错
- php - 在循环内使用 PDO 插入
- mysql - MySQL用户注册存储过程似乎不起作用
- php - 如何以编程方式启用 php 扩展 intl
- ios - 来自 iOS 节点管理员的 Firebase 消息传递
- ios - 如何在 iOS 中创建一个同时具有标题和图像的条形按钮项,并且图像按原样显示而没有色调?