Skip to content

Commit 47ffbc5

Browse files
authored
[camera] fix RECORD_AUDIO permission on Android when there is no permission (#10424)
Allows to record video without audio when we init the CameraController with `enableAudio=false` ``` final controller = CameraController( camera.first, ResolutionPreset.high, enableAudio: false, ); ``` Related issue: flutter/flutter#175020 ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent 5d8d954 commit 47ffbc5

File tree

4 files changed

+39
-10
lines changed

4 files changed

+39
-10
lines changed

packages/camera/camera_android_camerax/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.24+4
2+
3+
* Allows for video recording without audio when permission RECORD_AUDIO is denied.
4+
15
## 0.6.24+3
26

37
* Bumps com.android.tools.build:gradle from 8.12.1 to 8.13.1.

packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PendingRecordingProxyApi.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,17 @@ public PendingRecording asPersistentRecording(PendingRecording pigeonInstance) {
3838
@NonNull
3939
@Override
4040
public PendingRecording withAudioEnabled(PendingRecording pigeonInstance, boolean initialMuted) {
41-
if (!initialMuted
42-
&& ContextCompat.checkSelfPermission(
41+
boolean hasPermission =
42+
ContextCompat.checkSelfPermission(
4343
getPigeonRegistrar().getContext(), Manifest.permission.RECORD_AUDIO)
44-
== PackageManager.PERMISSION_GRANTED) {
45-
return pigeonInstance.withAudioEnabled(false);
44+
== PackageManager.PERMISSION_GRANTED;
45+
46+
if (hasPermission) {
47+
return pigeonInstance.withAudioEnabled(initialMuted);
4648
}
4749

48-
return pigeonInstance.withAudioEnabled(true);
50+
// By default, the recording will not contain audio.
51+
return pigeonInstance;
4952
}
5053

5154
@NonNull

packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PendingRecordingTest.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.mockito.ArgumentMatchers.eq;
99
import static org.mockito.Mockito.any;
1010
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.never;
1112
import static org.mockito.Mockito.verify;
1213
import static org.mockito.Mockito.when;
1314

@@ -52,7 +53,6 @@ public void withAudioEnabled_doesNotEnableAudioWhenRequestedAndPermissionNotGran
5253
final PigeonApiPendingRecording api =
5354
new TestProxyApiRegistrar().getPigeonApiPendingRecording();
5455
final PendingRecording instance = mock(PendingRecording.class);
55-
final PendingRecording newInstance = mock(PendingRecording.class);
5656

5757
try (MockedStatic<ContextCompat> mockedContextCompat =
5858
Mockito.mockStatic(ContextCompat.class)) {
@@ -63,10 +63,32 @@ public void withAudioEnabled_doesNotEnableAudioWhenRequestedAndPermissionNotGran
6363
any(Context.class), eq(Manifest.permission.RECORD_AUDIO)))
6464
.thenAnswer((Answer<Integer>) invocation -> PackageManager.PERMISSION_DENIED);
6565

66-
when(instance.withAudioEnabled(true)).thenReturn(newInstance);
66+
when(instance.withAudioEnabled(false)).thenReturn(instance);
6767

68-
assertEquals(api.withAudioEnabled(instance, false), newInstance);
69-
verify(instance).withAudioEnabled(true);
68+
assertEquals(api.withAudioEnabled(instance, false), instance);
69+
verify(instance, never()).withAudioEnabled(false);
70+
}
71+
}
72+
73+
@Test
74+
public void withAudioEnabled_doesNotEnableAudioWhenNotRequestedAndPermissionNotGranted() {
75+
final PigeonApiPendingRecording api =
76+
new TestProxyApiRegistrar().getPigeonApiPendingRecording();
77+
final PendingRecording instance = mock(PendingRecording.class);
78+
79+
try (MockedStatic<ContextCompat> mockedContextCompat =
80+
Mockito.mockStatic(ContextCompat.class)) {
81+
mockedContextCompat
82+
.when(
83+
() ->
84+
ContextCompat.checkSelfPermission(
85+
any(Context.class), eq(Manifest.permission.RECORD_AUDIO)))
86+
.thenAnswer((Answer<Integer>) invocation -> PackageManager.PERMISSION_DENIED);
87+
88+
when(instance.withAudioEnabled(true)).thenReturn(instance);
89+
90+
assertEquals(api.withAudioEnabled(instance, true), instance);
91+
verify(instance, never()).withAudioEnabled(true);
7092
}
7193
}
7294

packages/camera/camera_android_camerax/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: camera_android_camerax
22
description: Android implementation of the camera plugin using the CameraX library.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.6.24+3
5+
version: 0.6.24+4
66

77
environment:
88
sdk: ^3.9.0

0 commit comments

Comments
 (0)