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

Conversation

@cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Oct 3, 2019

Description

Migrate connectivity to the new android embedding.

Related Issues

flutter/flutter#41835

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.

}

dependencies {
implementation 'androidx.lifecycle:lifecycle-runtime:2.1.0'
Copy link
Contributor

Choose a reason for hiding this comment

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

remove these deps, the engine POM makes sure these are pulled in (once flutter/flutter#41885 lands)

import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.connectivity.ConnectivityMethodChannelHandler;

public class ConnectivityPlugin implements FlutterPlugin {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would you mind add Javadocs to all public, non-trivial classes/methods/fields?

Copy link
Contributor

Choose a reason for hiding this comment

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

New classes members/methods added should definitely be added with Javadocs.

Regarding all existing code - this is definitely tech debt we should be paying, and is welcomed if the author is interested in doing it as part of this PR, though it shouldn't block it. For the purpose of supporting the v2 embedder in all plugins I suggest we focus PRs and reviews on that goal. Please do leave any improvement suggestions of existing code as non-blocking nits.

I think this fits with the spirit of the Flutter code review guidelines:

In general, reviewers should favor approving a PR once it is in a state where it definitely improves the overall code health of the system being worked on, even if the PR isn't perfect.


@Override
public void onAttachedToEngine(FlutterPluginBinding binding) {
this.pluginBinding = binding;
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to cache the binding if you only use it within these 2 methods.

private ConnectivityManager manager;
private BroadcastReceiver receiver;

public ConnectivityMethodChannelHandler(Context context) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommendation: If you explicitly pass a ConnectivityManager instance, and if you create an interface around broadcast registration, passing an instance of that interface, instead of passing a Context, then you'll be a much better position to test interactions in this class.

}

private void handleWifiIPAddress(MethodCall call, final MethodChannel.Result result) {
WifiManager wifiManager =
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommendation: passing this as a constructor argument allows you to mock for tests.

}
}

private BroadcastReceiver createReceiver(final EventChannel.EventSink events) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommendation: If I were migrating this, I would probably restructure such that this BroadcastReceiver is separated from this MethodCallHandler and then bring them together in a third class.

}

@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add nullability annotations to all input parameters and return values for each public and private method.

}

@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would you mind adding unit tests for this class to ensure that incoming messages are correctly parsed, and outgoing messages are correctly serialized?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that Dart e2e integration tests would be acceptable as an alternative to unit tests.

@cyanglaz
Copy link
Contributor Author

cyanglaz commented Oct 4, 2019

@matthew-carroll Updated the code per some of our recommendation. I didn't add any JUnit tests nor Nullability notation to the existing code. Could you take another look and let me know if the new refactoring looks good.

import io.flutter.plugins.connectivity.ConnectivityMethodChannelHandler;

/**
* Plugin implementation that uses the new {@code io.flutter.embedding} package.
Copy link
Contributor

Choose a reason for hiding this comment

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

The most important thing in this javadoc is probably what the plugin does, and possibly how to use it, rather than a reference to the new embedding.

Also, through this migration, we should probably avoid talking about "new" vs "old". That language makes sense to us right now, but it naturally becomes stale. Is this still the "new" embedding a year from now?

/**
* Plugin implementation that uses the new {@code io.flutter.embedding} package.
*
* <p>Instantiate this in an add to app scenario to gracefully handle activity and context changes.
Copy link
Contributor

Choose a reason for hiding this comment

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

How should one instantiate this in an add-to-app scenario? I would either omit this line, or I would refer people to some kind of centralized documentation that all plugins can point to for setup instructions.

import androidx.annotation.NonNull;
import io.flutter.plugin.common.EventChannel;

/** Responsible for constructing a BroadcastReceiver as well as registering and unregistering it. */
Copy link
Contributor

Choose a reason for hiding this comment

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

While this statement is true, it may not be useful for developers. When a developer reads this doc, what kinds of questions might that developer be attempting to answer?

Flutter style guide: Writing prompts for good documentation
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#writing-prompts-for-good-documentation

public interface BroadcastReceiverRegistrar {

/**
* Triggered when it is ready for the BroadcastReceiver to be registered. Register the receiver in
Copy link
Contributor

Choose a reason for hiding this comment

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

Triggered when what is ready? This method probably involves a broader context. Can you fill in the reader on what is happening when this method is called, or why it exists? @mklim might have some suggestions here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a little unclear because it's phrased using passive voice, so it's not obvious who is doing what. https://developers.google.com/style/voice

I'd rephrase the first sentence to <Object> triggers this when it's ready for the BroadcastReceiver to be registered. With how it is now I think the worry is that you the developer need to trigger it somehow in some other place. I think the second sentence is clear as-is.

void readyToRegisterBroadcastReceiver(@NonNull BroadcastReceiver receiver);

/**
* Triggered when it is ready for the BroadcastReceiver to be unregistered. Unregister the
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

}

@Nullable
String getWifiName() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should all of these methods being with "/* package */"? @mklim for style input

Copy link
Contributor

Choose a reason for hiding this comment

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

It's one of those totally subjective style things, like annotating primitive arguments with /*name=*/. It's fine either way IMHO. From what I can tell the existing code doesn't use it, so it probably makes more sense to leave it off to be consistent.

import androidx.annotation.NonNull;
import io.flutter.plugin.common.EventChannel;

/** Handles the event channel for the plugin. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Another candidate for "writing prompts for good documentation"

What does it mean to "handle"? What is "the event channel"?

private BroadcastReceiver broadcastReceiver;

/**
* Constructs a ConnectivityEventChannelHandler
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably "useless documentation"

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

/** Handles MethodChannel for the plugin. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as the other handler's documentation.

private Connectivity connectivity;

/**
* Construct the ConnectivityMethodChannelHandler
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably "useless documentation"

@cyanglaz
Copy link
Contributor Author

cyanglaz commented Oct 7, 2019

@matthew-carroll Updated per Friday's discussion.

android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
</activity>
<activity android:name="dev.flutter.plugins.connectivity_exmaple.MainActivity"
Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, in Java/Android, packages usually don't include underscores. You might choose plugins.connectivity.example or plugins.connectivityexample.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

using connectivityexample.

Copy link
Contributor

@matthew-carroll matthew-carroll left a comment

Choose a reason for hiding this comment

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

Still a few small comments, but generally LGTM.

@cyanglaz
Copy link
Contributor Author

@collinjackson Could you review the e2e bits in this PR? Although ./gradlew connectedAnroidTest still fails on my local.

Copy link
Contributor

@collinjackson collinjackson left a comment

Choose a reason for hiding this comment

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

lgtm!

@cyanglaz cyanglaz merged commit 67697ab into flutter:master Oct 15, 2019
@cyanglaz cyanglaz deleted the connectivity_migrate branch October 15, 2019 19:33
cyanglaz pushed a commit that referenced this pull request Oct 18, 2019
mormih pushed a commit to mormih/plugins that referenced this pull request Nov 17, 2019
sungmin-park pushed a commit to sungmin-park/flutter-plugins that referenced this pull request Dec 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants