This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[camerax] Implement camera preview #7112
Merged
Merged
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
7894cc2
Add base code from proof of concept
camsim99 efca3ed
Fix analyzer
camsim99 b4ae1db
Add example app and tests
camsim99 7c8168b
Actually add tets and visible for testing annotation
camsim99 93d442b
Make methods private
camsim99 d99ef9c
Merge remote-tracking branch 'upstream/main' into camx_preview
camsim99 bf1ca9a
Fix tests
camsim99 b237d6e
Fix analyze:
camsim99 a21429a
Update changelog
camsim99 dcff8bc
Formatting
camsim99 a183944
Merge remote-tracking branch 'upstream/main' into camx_preview
camsim99 f163907
Update todos with links and modify camera controller
camsim99 285659d
Format and add availableCameras
camsim99 cffc0ac
Fix mocks
camsim99 889802d
Try bumping mockito version
camsim99 24ee512
Review documentation
camsim99 573cf33
Re-generate mocks
camsim99 d08c087
Fix typo
camsim99 1e1dd8b
Fix another typo
camsim99 e1cea85
Address review and fix bug
camsim99 5ccc872
Merge remote-tracking branch 'upstream/main' into camx_preview
camsim99 7129845
Fix analyze
camsim99 c54c547
Merge remote-tracking branch 'upstream/main' into camx_preview
camsim99 5f30bc7
Fix tests
camsim99 8fc71f9
Foramtting
camsim99 d50bd87
Clear preview is paused
camsim99 de2fc29
Add unknown lens
camsim99 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Merge remote-tracking branch 'upstream/main' into camx_preview
- Loading branch information
commit d99ef9ce80a30530bf2e68b22e03d65db9b02692
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ import 'package:async/async.dart'; | |
| import 'package:camera_android_camerax/camera_android_camerax.dart'; | ||
| import 'package:camera_android_camerax/src/camerax_library.g.dart'; | ||
| import 'package:camera_android_camerax/src/camera.dart'; | ||
| import 'package:camera_android_camerax/src/camera_info.dart'; | ||
| import 'package:camera_android_camerax/src/camera_selector.dart'; | ||
| import 'package:camera_android_camerax/src/preview.dart'; | ||
| import 'package:camera_android_camerax/src/process_camera_provider.dart'; | ||
|
|
@@ -24,15 +25,71 @@ import 'android_camera_camerax_test.mocks.dart'; | |
| @GenerateNiceMocks(<MockSpec<Object>>[ | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @stuartmorgan @bparrishMines Generate mocks for
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like the error is about a typedef that was added on master recently, so it's not on stable. You can probably just generate the mocks on |
||
| MockSpec<BuildContext>(), | ||
| MockSpec<Camera>(), | ||
| MockSpec<CameraInfo>(), | ||
| MockSpec<CameraSelector>(), | ||
| MockSpec<Preview>(), | ||
| MockSpec<ProcessCameraProvider>(), | ||
| ]) | ||
| void main() { | ||
| TestWidgetsFlutterBinding.ensureInitialized(); | ||
|
|
||
| test('Should fetch CameraDescription instances for available cameras', | ||
| () async { | ||
| // Arrange | ||
| final MockAndroidCameraCamerax camera = MockAndroidCameraCamerax(); | ||
| final List<dynamic> returnData = <dynamic>[ | ||
| <String, dynamic>{ | ||
| 'name': 'Camera 0', | ||
| 'lensFacing': 'back', | ||
| 'sensorOrientation': 0 | ||
| }, | ||
| <String, dynamic>{ | ||
| 'name': 'Camera 1', | ||
| 'lensFacing': 'front', | ||
| 'sensorOrientation': 90 | ||
| } | ||
| ]; | ||
|
|
||
| // Create mocks to use | ||
| final MockCameraInfo mockFrontCameraInfo = MockCameraInfo(); | ||
| final MockCameraInfo mockBackCameraInfo = MockCameraInfo(); | ||
|
|
||
| // Mock calls to native platform | ||
| when(camera.testProcessCameraProvider.getAvailableCameraInfos()).thenAnswer( | ||
| (_) async => <MockCameraInfo>[mockBackCameraInfo, mockFrontCameraInfo]); | ||
| when(camera.mockBackCameraSelector.filter(<MockCameraInfo>[mockFrontCameraInfo])) | ||
| .thenAnswer((_) async => <MockCameraInfo>[]); | ||
| when(camera.mockBackCameraSelector.filter(<MockCameraInfo>[mockBackCameraInfo])) | ||
| .thenAnswer((_) async => <MockCameraInfo>[mockBackCameraInfo]); | ||
| when(camera.mockFrontCameraSelector.filter(<MockCameraInfo>[mockBackCameraInfo])) | ||
| .thenAnswer((_) async => <MockCameraInfo>[]); | ||
| when(camera.mockFrontCameraSelector.filter(<MockCameraInfo>[mockFrontCameraInfo])) | ||
| .thenAnswer((_) async => <MockCameraInfo>[mockFrontCameraInfo]); | ||
| when(mockBackCameraInfo.getSensorRotationDegrees()) | ||
| .thenAnswer((_) async => 0); | ||
| when(mockFrontCameraInfo.getSensorRotationDegrees()) | ||
| .thenAnswer((_) async => 90); | ||
|
|
||
| final List<CameraDescription> cameraDescriptions = | ||
| await camera.availableCameras(); | ||
|
|
||
| expect(cameraDescriptions.length, returnData.length); | ||
| for (int i = 0; i < returnData.length; i++) { | ||
| final Map<String, Object?> typedData = | ||
| (returnData[i] as Map<dynamic, dynamic>).cast<String, Object?>(); | ||
| final CameraDescription cameraDescription = CameraDescription( | ||
| name: typedData['name']! as String, | ||
| lensDirection: (typedData['lensFacing']! as String) == 'front' | ||
| ? CameraLensDirection.front | ||
| : CameraLensDirection.back, | ||
| sensorOrientation: typedData['sensorOrientation']! as int, | ||
| ); | ||
| expect(cameraDescriptions[i], cameraDescription); | ||
| } | ||
| }); | ||
|
|
||
| test( | ||
| 'createCamera requests permissions, starts listening for device orientation changes, and returns flutter surface texture ID ', | ||
| 'createCamera requests permissions, starts listening for device orientation changes, and returns flutter surface texture ID', | ||
| () async { | ||
| final MockAndroidCameraCamerax camera = MockAndroidCameraCamerax(); | ||
| const CameraLensDirection testLensDirection = CameraLensDirection.back; | ||
|
|
@@ -58,7 +115,7 @@ void main() { | |
| expect(camera.startedListeningForDeviceOrientationChanges, isTrue); | ||
|
|
||
| // Verify CameraSelector is set with appropriate lens direction. | ||
| expect(camera.cameraSelector, equals(camera.testCameraSelector)); | ||
| expect(camera.cameraSelector, equals(camera.mockBackCameraSelector)); | ||
|
|
||
| // Verify ProcessCameraProvider instance is received. | ||
| expect( | ||
|
|
@@ -306,6 +363,8 @@ class MockAndroidCameraCamerax extends AndroidCameraCameraX { | |
| final MockProcessCameraProvider testProcessCameraProvider = | ||
| MockProcessCameraProvider(); | ||
| final MockPreview testPreview = MockPreview(); | ||
| final MockCameraSelector mockBackCameraSelector = MockCameraSelector(); | ||
| final MockCameraSelector mockFrontCameraSelector = MockCameraSelector(); | ||
| final MockCameraSelector testCameraSelector = MockCameraSelector(); | ||
|
|
||
| @override | ||
|
|
@@ -327,7 +386,14 @@ class MockAndroidCameraCamerax extends AndroidCameraCameraX { | |
|
|
||
| @override | ||
| CameraSelector createCameraSelector(int cameraSelectorLensDirection) { | ||
| return testCameraSelector; | ||
| switch(cameraSelectorLensDirection) { | ||
| case CameraSelector.LENS_FACING_FRONT: | ||
| return mockFrontCameraSelector; | ||
| case CameraSelector.LENS_FACING_BACK: | ||
| return mockBackCameraSelector; | ||
| default: | ||
| return testCameraSelector; | ||
| } | ||
| } | ||
|
|
||
| @override | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You are viewing a condensed version of this merge commit. You can view the full changes here.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It may be worth moving all the
@visibleForTestingfields and methods to a separate class and pass that class as an optional parameter in a constructor. Calling it something likeAndroidCameraXProxy. This could help organize the code a bit. You can decide which is easier to use.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would honestly find this kind of confusing, especially since this would involve some of the major use case instances. Are you open to reconsidering this later on? I could see it helping organizationally if there ends up being a lot of different fields (especially booleans and things that aren't necessarily CameraX objects) that need to be visible or there are a bunch more methods we'll need to create to mock.