registerForActivityResult(ActivityResultContracts.TakeVideo()) 始终为空
registerForActivityResult(ActivityResultContracts.TakeVideo()) is always null
我使用以下代码来捕获视频。一切正常,但在捕获视频后,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}")
}
}
发生了什么事?
An ActivityResultContract
to take a video saving it into the provided
content-Uri
.
Returns a thumbnail.
来源TakeVideo docs,强调我的。
您不需要缩略图(无论如何这是可选的),您需要指向实际视频的 Uri
。但是您已经知道 Uri
,因为您将其作为输入提供。
现在怎么办?
完成这项工作需要几个步骤:
将输入 Uri
存储在一个变量中并正确处理保存的状态,这样当您从相机应用返回时,您的应用就会知道您一直在录制视频。
编写自定义 TakeVideo
合约,如果视频捕获成功,returns。无法使用检查非空预览 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;
}
}
我使用以下代码来捕获视频。一切正常,但在捕获视频后,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}")
}
}
发生了什么事?
An
ActivityResultContract
to take a video saving it into the provided content-Uri
.Returns a thumbnail.
来源TakeVideo docs,强调我的。
您不需要缩略图(无论如何这是可选的),您需要指向实际视频的 Uri
。但是您已经知道 Uri
,因为您将其作为输入提供。
现在怎么办?
完成这项工作需要几个步骤:
将输入
Uri
存储在一个变量中并正确处理保存的状态,这样当您从相机应用返回时,您的应用就会知道您一直在录制视频。编写自定义
TakeVideo
合约,如果视频捕获成功,returns。无法使用检查非空预览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;
}
}