Skip to content

Commit 7ddcf77

Browse files
committed
[camera] Update camera to 0.9.4
1 parent b60f782 commit 7ddcf77

File tree

9 files changed

+126
-137
lines changed

9 files changed

+126
-137
lines changed

packages/camera/CHANGELOG.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44

55
## 0.2.0
66

7-
* Apply new external texture APIs
7+
* Apply new external texture APIs.
88

99
## 0.2.1
1010

11-
* Fix a freezing preview issue
11+
* Fix a freezing preview issue.
12+
13+
## 0.3.0
14+
15+
* Update camera to 0.9.4.
16+
* Update the example app and integration_test.
17+
* Remove the unused test driver.

packages/camera/README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ The Tizen implementation of [`camera`](https://github.com/flutter/plugins/tree/m
44

55
## Supported devices
66

7-
This plugin is an experimental plug-in for the future
8-
9-
- Nothing
7+
This plugin is currently experimental and does not support any devices.
108

119
## Required privileges
1210

13-
To use this plugin, add below lines under the `<manifest>` section in your `tizen-manifest.xml` file,
11+
To use this plugin, add below lines under the `<manifest>` section in your `tizen-manifest.xml` file.
1412

1513
```xml
1614
<privileges>
@@ -25,19 +23,21 @@ This package is not an _endorsed_ implementation of `camera`. Therefore, you hav
2523

2624
```yaml
2725
dependencies:
28-
camera: ^0.8.1
29-
camera_tizen: ^0.2.1
26+
camera: ^0.9.4
27+
camera_tizen: ^0.3.0
3028
```
3129
3230
Then you can import `camera` in your Dart code:
3331

3432
```dart
3533
import 'package:camera/camera.dart';
3634
```
35+
3736
For detailed usage, see https://github.com/flutter/plugins/tree/master/packages/camera/camera#example.
3837

3938
## Notes
40-
CameraPreview currently does not support other platforms except Android and iOS. Therefor the camera preview to orient properly, you have to modify the `camera_preview.dart`.
39+
40+
For the camera preview to rotate correctly, you have to modify the `camera_preview.dart` file as follows.
4141

4242
```dart
4343
Widget _wrapInRotatedBox({required Widget child}) {

packages/camera/example/integration_test/camera_test.dart

+3-18
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
// TODO(mvanbeusekom): Remove this once flutter_driver supports null safety.
6-
// https://github.com/flutter/flutter/issues/71379
7-
// @dart = 2.9
85
import 'dart:async';
96
import 'dart:io';
107
import 'dart:ui';
@@ -17,7 +14,7 @@ import 'package:video_player/video_player.dart';
1714
import 'package:integration_test/integration_test.dart';
1815

1916
void main() {
20-
Directory testDir;
17+
late Directory testDir;
2118

2219
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
2320

@@ -30,18 +27,6 @@ void main() {
3027
await testDir.delete(recursive: true);
3128
});
3229

33-
// final Map<ResolutionPreset, Size> presetExpectedSizes =
34-
// <ResolutionPreset, Size>{
35-
// ResolutionPreset.low:
36-
// Platform.isAndroid ? const Size(240, 320) : const Size(288, 352),
37-
// ResolutionPreset.medium:
38-
// Platform.isAndroid ? const Size(480, 720) : const Size(480, 640),
39-
// ResolutionPreset.high: const Size(720, 1280),
40-
// ResolutionPreset.veryHigh: const Size(1080, 1920),
41-
// ResolutionPreset.ultraHigh: const Size(2160, 3840),
42-
// // Don't bother checking for max here since it could be anything.
43-
// };
44-
4530
final Map<ResolutionPreset, Size> presetExpectedSizes =
4631
<ResolutionPreset, Size>{
4732
ResolutionPreset.medium: const Size(480, 720),
@@ -63,7 +48,7 @@ void main() {
6348
// whether the image is exactly the desired resolution.
6449
Future<bool> testCaptureImageResolution(
6550
CameraController controller, ResolutionPreset preset) async {
66-
final Size expectedSize = presetExpectedSizes[preset];
51+
final Size expectedSize = presetExpectedSizes[preset]!;
6752
print(
6853
'Capturing photo at $preset (${expectedSize.width}x${expectedSize.height}) using camera ${controller.description.name}');
6954

@@ -108,7 +93,7 @@ void main() {
10893
// whether the image is exactly the desired resolution.
10994
Future<bool> testCaptureVideoResolution(
11095
CameraController controller, ResolutionPreset preset) async {
111-
final Size expectedSize = presetExpectedSizes[preset];
96+
final Size expectedSize = presetExpectedSizes[preset]!;
11297
print(
11398
'Capturing video at $preset (${expectedSize.width}x${expectedSize.height}) using camera ${controller.description.name}');
11499

packages/camera/example/lib/main.dart

+101-33
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'dart:async';
88
import 'dart:io';
99

1010
import 'package:camera/camera.dart';
11+
import 'package:flutter/foundation.dart';
1112
import 'package:flutter/material.dart';
1213
import 'package:video_player/video_player.dart';
1314

@@ -68,7 +69,7 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
6869
@override
6970
void initState() {
7071
super.initState();
71-
WidgetsBinding.instance?.addObserver(this);
72+
_ambiguate(WidgetsBinding.instance)?.addObserver(this);
7273

7374
_flashModeControlRowAnimationController = AnimationController(
7475
duration: const Duration(milliseconds: 300),
@@ -98,7 +99,7 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
9899

99100
@override
100101
void dispose() {
101-
WidgetsBinding.instance?.removeObserver(this);
102+
_ambiguate(WidgetsBinding.instance)?.removeObserver(this);
102103
_flashModeControlRowAnimationController.dispose();
103104
_exposureModeControlRowAnimationController.dispose();
104105
super.dispose();
@@ -231,7 +232,14 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
231232
? Container()
232233
: SizedBox(
233234
child: (localVideoController == null)
234-
? Image.file(File(imageFile!.path))
235+
? (
236+
// The captured image on the web contains a network-accessible URL
237+
// pointing to a location within the browser. It may be displayed
238+
// either with Image.network or Image.memory after loading the image
239+
// bytes to memory.
240+
kIsWeb
241+
? Image.network(imageFile!.path)
242+
: Image.file(File(imageFile!.path)))
235243
: Container(
236244
child: Center(
237245
child: AspectRatio(
@@ -267,17 +275,24 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
267275
color: Colors.blue,
268276
onPressed: controller != null ? onFlashModeButtonPressed : null,
269277
),
270-
IconButton(
271-
icon: Icon(Icons.exposure),
272-
color: Colors.blue,
273-
onPressed:
274-
controller != null ? onExposureModeButtonPressed : null,
275-
),
276-
IconButton(
277-
icon: Icon(Icons.filter_center_focus),
278-
color: Colors.blue,
279-
onPressed: controller != null ? onFocusModeButtonPressed : null,
280-
),
278+
// The exposure and focus mode are currently not supported on the web.
279+
...(!kIsWeb
280+
? [
281+
IconButton(
282+
icon: Icon(Icons.exposure),
283+
color: Colors.blue,
284+
onPressed: controller != null
285+
? onExposureModeButtonPressed
286+
: null,
287+
),
288+
IconButton(
289+
icon: Icon(Icons.filter_center_focus),
290+
color: Colors.blue,
291+
onPressed:
292+
controller != null ? onFocusModeButtonPressed : null,
293+
)
294+
]
295+
: []),
281296
IconButton(
282297
icon: Icon(enableAudio ? Icons.volume_up : Icons.volume_mute),
283298
color: Colors.blue,
@@ -399,6 +414,13 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
399414
onSetExposureModeButtonPressed(ExposureMode.locked)
400415
: null,
401416
),
417+
TextButton(
418+
child: Text('RESET OFFSET'),
419+
style: styleLocked,
420+
onPressed: controller != null
421+
? () => controller!.setExposureOffset(0.0)
422+
: null,
423+
),
402424
],
403425
),
404426
Center(
@@ -530,7 +552,16 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
530552
cameraController.value.isRecordingVideo
531553
? onStopButtonPressed
532554
: null,
533-
)
555+
),
556+
IconButton(
557+
icon: const Icon(Icons.pause_presentation),
558+
color:
559+
cameraController != null && cameraController.value.isPreviewPaused
560+
? Colors.red
561+
: Colors.blue,
562+
onPressed:
563+
cameraController == null ? null : onPausePreviewButtonPressed,
564+
),
534565
],
535566
);
536567
}
@@ -597,12 +628,14 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
597628
if (controller != null) {
598629
await controller!.dispose();
599630
}
631+
600632
final CameraController cameraController = CameraController(
601633
cameraDescription,
602-
ResolutionPreset.medium,
634+
kIsWeb ? ResolutionPreset.max : ResolutionPreset.medium,
603635
enableAudio: enableAudio,
604636
imageFormatGroup: ImageFormatGroup.jpeg,
605637
);
638+
606639
controller = cameraController;
607640

608641
// If the controller is updated then update the UI.
@@ -617,12 +650,17 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
617650
try {
618651
await cameraController.initialize();
619652
await Future.wait([
620-
cameraController
621-
.getMinExposureOffset()
622-
.then((value) => _minAvailableExposureOffset = value),
623-
cameraController
624-
.getMaxExposureOffset()
625-
.then((value) => _maxAvailableExposureOffset = value),
653+
// The exposure mode is currently not supported on the web.
654+
...(!kIsWeb
655+
? [
656+
cameraController
657+
.getMinExposureOffset()
658+
.then((value) => _minAvailableExposureOffset = value),
659+
cameraController
660+
.getMaxExposureOffset()
661+
.then((value) => _maxAvailableExposureOffset = value)
662+
]
663+
: []),
626664
cameraController
627665
.getMaxZoomLevel()
628666
.then((value) => _maxAvailableZoom = value),
@@ -690,16 +728,20 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
690728
}
691729

692730
void onCaptureOrientationLockButtonPressed() async {
693-
if (controller != null) {
694-
final CameraController cameraController = controller!;
695-
if (cameraController.value.isCaptureOrientationLocked) {
696-
await cameraController.unlockCaptureOrientation();
697-
showInSnackBar('Capture orientation unlocked');
698-
} else {
699-
await cameraController.lockCaptureOrientation();
700-
showInSnackBar(
701-
'Capture orientation locked to ${cameraController.value.lockedCaptureOrientation.toString().split('.').last}');
731+
try {
732+
if (controller != null) {
733+
final CameraController cameraController = controller!;
734+
if (cameraController.value.isCaptureOrientationLocked) {
735+
await cameraController.unlockCaptureOrientation();
736+
showInSnackBar('Capture orientation unlocked');
737+
} else {
738+
await cameraController.lockCaptureOrientation();
739+
showInSnackBar(
740+
'Capture orientation locked to ${cameraController.value.lockedCaptureOrientation.toString().split('.').last}');
741+
}
702742
}
743+
} on CameraException catch (e) {
744+
_showCameraException(e);
703745
}
704746
}
705747

@@ -741,6 +783,23 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
741783
});
742784
}
743785

786+
Future<void> onPausePreviewButtonPressed() async {
787+
final CameraController? cameraController = controller;
788+
789+
if (cameraController == null || !cameraController.value.isInitialized) {
790+
showInSnackBar('Error: select a camera first.');
791+
return;
792+
}
793+
794+
if (cameraController.value.isPreviewPaused) {
795+
await cameraController.resumePreview();
796+
} else {
797+
await cameraController.pausePreview();
798+
}
799+
800+
if (mounted) setState(() {});
801+
}
802+
744803
void onPauseButtonPressed() {
745804
pauseVideoRecording().then((_) {
746805
if (mounted) setState(() {});
@@ -881,8 +940,10 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
881940
return;
882941
}
883942

884-
final VideoPlayerController vController =
885-
VideoPlayerController.file(File(videoFile!.path));
943+
final VideoPlayerController vController = kIsWeb
944+
? VideoPlayerController.network(videoFile!.path)
945+
: VideoPlayerController.file(File(videoFile!.path));
946+
886947
videoPlayerListener = () {
887948
if (videoController != null && videoController!.value.size != null) {
888949
// Refreshing the state to update video player with the correct ratio.
@@ -951,3 +1012,10 @@ Future<void> main() async {
9511012
}
9521013
runApp(CameraApp());
9531014
}
1015+
1016+
/// This allows a value of type T or T? to be treated as a value of type T?.
1017+
///
1018+
/// We use this so that APIs that have become non-nullable can still be used
1019+
/// with `!` and `?` on the stable branch.
1020+
// TODO(ianh): Remove this once we roll stable in late 2021.
1021+
T? _ambiguate<T>(T? value) => value;

packages/camera/example/pubspec.yaml

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
name: camera_example
22
description: Demonstrates how to use the camera plugin.
3+
publish_to: "none"
34

45
dependencies:
5-
camera: ^0.8.1
6+
camera: ^0.9.4
67
camera_tizen:
78
path: ../
89
flutter:
910
sdk: flutter
1011
path_provider: ^2.0.0
1112
path_provider_tizen:
1213
path: ../../path_provider
13-
video_player: ^2.0.0
14+
video_player: ^2.1.4
1415
video_player_tizen:
1516
path: ../../video_player
1617

1718
dev_dependencies:
18-
flutter_driver:
19-
sdk: flutter
2019
flutter_test:
2120
sdk: flutter
2221
integration_test:

0 commit comments

Comments
 (0)