Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/connectivity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.4.5

* Support the v2 Android embedder.

## 0.4.4+1

* Update and migrate iOS example project.
Expand Down
25 changes: 25 additions & 0 deletions packages/connectivity/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,28 @@ android {
disable 'InvalidPackage'
}
}

// TODO(amirh): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
afterEvaluate {
def containsEmbeddingDependencies = false
for (def configuration : configurations.all) {
for (def dependency : configuration.dependencies) {
if (dependency.group == 'io.flutter' &&
dependency.name.startsWith('flutter_embedding') &&
dependency.isTransitive())
{
containsEmbeddingDependencies = true
break
}
}
}
if (!containsEmbeddingDependencies) {
android {
dependencies {
def lifecycle_version = "2.1.0"
api "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
api "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.connectivity;

import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/** Reports connectivity related information such as connectivity type and wifi information. */
class Connectivity {
private ConnectivityManager connectivityManager;
private WifiManager wifiManager;

Connectivity(ConnectivityManager connectivityManager, WifiManager wifiManager) {
this.connectivityManager = connectivityManager;
this.wifiManager = wifiManager;
}

@NonNull
String getNetworkType() {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Network network = connectivityManager.getActiveNetwork();
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
if (capabilities == null) {
return "none";
}
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return "wifi";
}
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return "mobile";
}
}

return getNetworkTypeLegacy();
}

@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.

WifiInfo wifiInfo = getWifiInfo();
String ssid = null;
if (wifiInfo != null) ssid = wifiInfo.getSSID();
if (ssid != null) ssid = ssid.replaceAll("\"", ""); // Android returns "SSID"
return ssid;
}

@Nullable
String getWifiBSSID() {
WifiInfo wifiInfo = getWifiInfo();
String bssid = null;
if (wifiInfo != null) {
bssid = wifiInfo.getBSSID();
}
return bssid;
}

@Nullable
String getWifiIPAddress() {
WifiInfo wifiInfo = null;
if (wifiManager != null) wifiInfo = wifiManager.getConnectionInfo();

String ip = null;
int i_ip = 0;
if (wifiInfo != null) i_ip = wifiInfo.getIpAddress();

if (i_ip != 0)
ip =
String.format(
"%d.%d.%d.%d",
(i_ip & 0xff), (i_ip >> 8 & 0xff), (i_ip >> 16 & 0xff), (i_ip >> 24 & 0xff));

return ip;
}

@Nullable
private WifiInfo getWifiInfo() {
return wifiManager == null ? null : wifiManager.getConnectionInfo();
}

@SuppressWarnings("deprecation")
private String getNetworkTypeLegacy() {
// handle type for Android versions less than Android 9
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (info == null || !info.isConnected()) {
return "none";
}
int type = info.getType();
switch (type) {
case ConnectivityManager.TYPE_ETHERNET:
case ConnectivityManager.TYPE_WIFI:
case ConnectivityManager.TYPE_WIMAX:
return "wifi";
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
return "mobile";
default:
return "none";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.connectivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import androidx.annotation.NonNull;
import io.flutter.plugin.common.EventChannel;

/**
* The ConnectivityBroadcastReceiver receives the connectivity updates and send them to the UIThread
* through an {@link EventChannel.EventSink}
*
* <p>Use {@link
* io.flutter.plugin.common.EventChannel#setStreamHandler(io.flutter.plugin.common.EventChannel.StreamHandler)}
* to set up the receiver.
*/
class ConnectivityBroadcastReceiver extends BroadcastReceiver
implements EventChannel.StreamHandler {
private Context context;
private Connectivity connectivity;
private EventChannel.EventSink events;

ConnectivityBroadcastReceiver(@NonNull Context context, @NonNull Connectivity connectivity) {
this.context = context;
this.connectivity = connectivity;
}

@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
this.events = events;
context.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}

@Override
public void onCancel(Object arguments) {
context.unregisterReceiver(this);
}

@Override
public void onReceive(Context context, Intent intent) {
if (events != null) {
events.success(connectivity.getNetworkType());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.connectivity;

import androidx.annotation.NonNull;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

/**
* The handler receives {@link MethodCall}s from the UIThread, gets the related information from
* a @{@link Connectivity}, and then send the result back to the UIThread through the {@link
* MethodChannel.Result}.
*/
class ConnectivityMethodChannelHandler implements MethodChannel.MethodCallHandler {

private Connectivity connectivity;

/**
* Construct the ConnectivityMethodChannelHandler with a {@code connectivity}. The {@code
* connectivity} must not be null.
*/
ConnectivityMethodChannelHandler(@NonNull Connectivity connectivity) {
assert (connectivity != null);
this.connectivity = connectivity;
}

@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.

switch (call.method) {
case "check":
result.success(connectivity.getNetworkType());
break;
case "wifiName":
result.success(connectivity.getWifiName());
break;
case "wifiBSSID":
result.success(connectivity.getWifiBSSID());
break;
case "wifiIPAddress":
result.success(connectivity.getWifiIPAddress());
break;
default:
result.notImplemented();
break;
}
}
}
Loading