Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[camera] Add camera_platform_interface package #3253

Merged
merged 4 commits into from Dec 4, 2020

Conversation

mvanbeusekom
Copy link
Contributor

@mvanbeusekom mvanbeusekom commented Nov 6, 2020

Description

Adds CameraPlatform which can be overridden to implement camera on other platforms (which may not want to use MethodChannels).

The PR is marked as draft so it can serve as a starting point on discussing the platform interface for the camera plugin. I have followed the article "How To Write a Flutter Web Plugin: Part 2" as a guide on which steps to take to migrate the camera plugin to the federated architecture. Below is an overview of steps:

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@google-cla google-cla bot added the cla: yes label Nov 6, 2020
@ditman
Copy link
Member

ditman commented Nov 7, 2020

Before I go into any detail, I normally like to just do the first move (from camera to camera/camera) as a proper PR and get that merged ASAP, so the development of the platform_interface can happen "in isolation".

Moving to camera/camera is a very simple PR (only "moved files without changes" or URL/link/pubspec path changes), and has the immediate benefit of being able to land any incoming fixes (if any) without having to worry about merge conflicts or git getting confused with changes + moves later on.

Then, the PR for the platform_interface will be quite smaller!

Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've dumped some of the things we discussed over email before, and some advice after federating the google maps plugin that might be useful here too!

I'm not a firm believer in any of my opinions, so discussions are welcome! (I'll also be available on VC for further clarifications, if needed!)

@mvanbeusekom
Copy link
Contributor Author

Before I go into any detail, I normally like to just do the first move (from camera to camera/camera) as a proper PR and get that merged ASAP, so the development of the platform_interface can happen "in isolation".

Moving to camera/camera is a very simple PR (only "moved files without changes" or URL/link/pubspec path changes), and has the immediate benefit of being able to land any incoming fixes (if any) without having to worry about merge conflicts or git getting confused with changes + moves later on.

Then, the PR for the platform_interface will be quite smaller!

Clear and perfect point, luckily I made a separate commit of the move so I could easily create a new branch based on this commit and make a new PR which is ready to be reviewed (and hopefully merged): #3258.

@ditman
Copy link
Member

ditman commented Nov 9, 2020

make a new PR which is ready to be reviewed (and hopefully merged): #3258.

@mvanbeusekom yes, I left a couple of silly comments there (pls update the changelog and pubspec version) but I think that one can be merged pretty quickly.

@google-cla
Copy link

google-cla bot commented Nov 13, 2020

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added cla: no and removed cla: yes labels Nov 13, 2020
@BeMacized
Copy link
Member

@googlebot I fixed it.

@google-cla
Copy link

google-cla bot commented Nov 13, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@mvanbeusekom
Copy link
Contributor Author

@googlebot I consent.

@google-cla
Copy link

google-cla bot commented Nov 13, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@BeMacized
Copy link
Member

@googlebot I consent.

@google-cla google-cla bot added cla: yes and removed cla: no labels Nov 13, 2020
Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really cool, I'm starting to run out of comments :P

Comment on lines 83 to 84
/// The file can be read as soon as [stopVideoRecording] returns.
Future<XFile> startVideoRecording(int cameraId) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file can be read as soon as [stopVideoRecording] returns. Should stopVideoRecording return the XFile instead? (It doesn't really matter much, but since this is a Future, it's a little bit more clunky to use. For example, I don't think we could use await with this future, because that'd probably block the program (so stopVideoRecording would never be called))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having stopVideoRecording return the XFile indeed sounds like the more logical approach to me.

The only case I could argue for startVideoRecording to return the XFile as well, is if there is any reason for users to access the file before stopping the recording. Currently I cannot seem to come up with any though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only case I could argue for startVideoRecording to return the XFile as well, is if there is any reason for users to access the file before stopping the recording. Currently I cannot seem to come up with any though.

I think the case where we'd want to be able to have a future returned from startVideoRecording is if we wanted to use some sort of UI widget, with a FutureBuilder or similar; but in the example app that is not done at all.

packages/camera/camera_platform_interface/pubspec.yaml Outdated Show resolved Hide resolved
}

/// Returns a widget showing a live camera preview.
Widget buildView(int cameraId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think buildPreview or buildWidget would be more appropriate since they aren't Views in Flutter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch, I agree buildPreview is a much better name, as such I renamed the method to buildPreview.

@ditman
Copy link
Member

ditman commented Nov 19, 2020

Quick comment: package: cross_file is now a thing:

https://pub.dev/packages/cross_file

@mvanbeusekom
Copy link
Contributor Author

Quick comment: package: cross_file is now a thing:

https://pub.dev/packages/cross_file

Awesome, I will create a quick PR to update the file_selector plugin.

@google-cla
Copy link

google-cla bot commented Nov 27, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added cla: no and removed cla: yes labels Nov 27, 2020
@google-cla
Copy link

google-cla bot commented Nov 27, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

1 similar comment
@google-cla
Copy link

google-cla bot commented Nov 27, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@BeMacized
Copy link
Member

@googlebot I consent.

@google-cla
Copy link

google-cla bot commented Nov 30, 2020

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@danielroek
Copy link
Contributor

@googlebot i consent

@google-cla google-cla bot added cla: yes and removed cla: no labels Nov 30, 2020
@mvanbeusekom mvanbeusekom marked this pull request as ready for review November 30, 2020 17:26
@mvanbeusekom
Copy link
Contributor Author

@ditman, @bparrishMines, I just removed the draft label from this PR.

I this I have processed all earlier feedback and we (me and the team) migrated the Android and iOS implementations as well as the App Facing interface package to work with the new camera_platform_interface.

One open "to do" is to update the dependency on the camera_platform_interface in the camera package to a reference from pub.dev. This is not yet possible since the camera_platform_interface package is not yet published. For now I have marked this version of the camera package with the publish_to: none attribute and left a comment in the pubspec.yaml file to remind us to update the dependency.

Would love to hear your feedback.

Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great. The biggest issue that this PR has now, is that it contains changes both to camera and camera_platform_interface, so it's not publishable (we should push only the platform_interface, and then do the backwards incompatible change to the core plugin).

Anyway, minor things. TL;DR:

  • Should the camera_image.dart file live in the platform_interface? If so, can it have Constructors that don't rely in a JSON/Map data structure to create them? Web is not going to have those maps handy!
  • Do we need to use part directives to structure the library? Can we use import/export?
  • Can we make the MethodChannel implementation class API simpler, by moving helper methods to outside helper functions, instead of having methods within the class?

Comment on lines 17 to 19
return controller.value.isInitialized
? Texture(textureId: controller._cameraId)
: Container();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, this is the trick. For this to work across platforms, the implementation must be:

return controller.value.isInitialized ? platform.buildPreview(cameraId: controller._cameraId) : Container();

The Texture implementation should be defined in the MethodChannel implementation (mobile version), and the web can return something based in HtmlViewElements or similar :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done ;)

I do wonder if the CameraPreview widget can actually become a cross platform widget since it relies on the CameraController which is a Android / iOS implementation of the camera_platform_interface. I think we can also make the CameraController cross platform but not sure if this will work for the web (looking at the google_maps_flutter I also see separate controllers and widgets). What do you think @ditman?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything that is exposed in the camera/camera must be completely cross-platform, and if it needs to do calls to the native side, it needs to use a platform interface call. I thought the controller was already doing that? Re-checking!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation of the camera controller is using a method channel directly, but I think all the methods called there are already represented in the platform_interface?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current camera controller is using the method channel directly because I reverted the changes in the camera/camera plugin. Changes for the camera/camera plugin are now part of PR #3302, here all calls to the native side go through the platform_interface (except for the startImageStream and stopImageStream).

packages/camera/camera/lib/src/camera_image.dart Outdated Show resolved Hide resolved
packages/camera/camera/lib/camera.dart Outdated Show resolved Hide resolved
Comment on lines 367 to 363
await controller.startVideoRecording(filePath);
await controller.startVideoRecording();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we didn't care much about the start recording future before either :/


part of camera;

final MethodChannel _channel = const MethodChannel('plugins.flutter.io/camera');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be calling the methdos from the interface, but I guess this is a similar case to the CameraWidget that hasn't been migrated yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This channel is used by the startImageStream and stopImageStream methods. As it is the Google team is not very happy with these methods and their implementation, because they don't perform very well. So we decided in an offline meeting (between Amir, Maurice, Chris and myself) that for now we will keep these methods only available for the Android and iOS so not to break existing users until we have a better alternative. Meaning we don't add them to the platform_interface as of yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh, ok, those methods would need some assert(!kIsWeb) or similar so people are aware that the web implementation will not handle them (at all), instead of getting a runtime error of "method channel not registered for message blah" which is more cryptic, and sounds like a bug!

packages/camera/camera/lib/src/camera_image.dart Outdated Show resolved Hide resolved
@mvanbeusekom
Copy link
Contributor Author

mvanbeusekom commented Dec 3, 2020

This is looking great. The biggest issue that this PR has now, is that it contains changes both to camera and camera_platform_interface, so it's not publishable (we should push only the platform_interface, and then do the backwards incompatible change to the core plugin).

Anyway, minor things. TL;DR:

* Should the camera_image.dart file live in the platform_interface? If so, can it have Constructors that don't rely in a JSON/Map `data` structure to create them? Web is not going to have those maps handy!

* Do we need to use `part` directives to structure the library? Can we use `import`/`export`?

* Can we make the MethodChannel implementation class API simpler, by moving helper methods to outside helper functions, instead of having methods within the class?

@ditman, thank you for this detailed review. I have gone through all of your remarks and made sure everything has been either fixed or I left explanation.

I have updated this PR to only include the addition off the camera_platform_interface and removed all changes to the camera plugin, so we can move this along. Currently CI is failing because of a deprecation warning (which is treated as error). A PR to fix this is already on it's way (see #3299).

A second PR (#3302) now contains the implementation of the camera_platform_interface for the camera package (by my colleague @BeMacized).

I did have two points I wanted your opinion on, maybe you could have a look at them:

  • One is regarding the CameraPreview widget, see comment here;
  • And the second one is regarding the handleMethodCall method, see comment here

@ditman
Copy link
Member

ditman commented Dec 3, 2020

It seems #3299 has been merged; do you mind rebasing this branch so all tests go green? I'll take a final quick look at the PR right after!

@mvanbeusekom
Copy link
Contributor Author

mvanbeusekom commented Dec 3, 2020

It seems #3299 has been merged; do you mind rebasing this branch so all tests go green? I'll take a final quick look at the PR right after!

I have just rebased, CI is running ;) Thanks David.

Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Maybe have @bparrishMines wants to take a look again, but I don't have much else to say! Thanks for the effort @mvanbeusekom!

@mvanbeusekom mvanbeusekom merged commit 9fef1c7 into flutter:master Dec 4, 2020
@mvanbeusekom mvanbeusekom deleted the camera_federated branch December 10, 2020 09:35
amantoux pushed a commit to amantoux/plugins that referenced this pull request Feb 8, 2021
* Make sure only camera_platform_interface has updates

* add dev dependency to async package

* refactored import to package import

* Fix formatting issues
adsonpleal pushed a commit to nubank/plugins that referenced this pull request Feb 26, 2021
* Make sure only camera_platform_interface has updates

* add dev dependency to async package

* refactored import to package import

* Fix formatting issues
samandmoore added a commit to Betterment/plugins that referenced this pull request Apr 21, 2021
…m-changes

* upstream-share-final-null-release: (233 commits)
  [q-w] Update Flutter SDK constraint (flutter#3323)
  [i-p] Update Flutter SDK constraint (flutter#3322)
  [d-g] Update Flutter SDK constraint (flutter#3321)
  [a-c] Update Flutter SDK constraint (flutter#3320)
  [image_picker_platform_interface] Pass Uri to package:http APIs (flutter#3309)
  Exclude null-safe plugins from testing on stable (flutter#3318)
  [documentation] [url_launcher] fix for readme code sample (flutter#3308)
  [camera] Add zoom support to platform interface (flutter#3312)
  update analysis options for nnbd (flutter#3319)
  [camera] Suppress unchecked cast warning in java test (flutter#3316)
  [image_picker] [integration_test] Fixes to make the tree green (flutter#3317)
  [camera] Expanded platform interface to support setting flash mode (flutter#3313)
  [Espresso] Android Code Inspection and Clean up (flutter#3111)
  [camera] Add `camera_platform_interface` package (flutter#3253)
  [camera] Support Android 30 (flutter#3299)
  bump integration test to 1.0.0 (flutter#3295)
  [android_alarm_manager] fix AndroidManifest.xml for android lint issue "XML tag has empty body" (flutter#3288)
  Use testWidgets instead of test to fix failures not surfacing on CI (flutter#3279)
  [file_selector_platform_interface] Migrate to cross_file package (flutter#3286)
  Fix broken link (flutter#3280)
  ...
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
5 participants