preface
This article describes how to develop a Flutter plugin to listen for changes in the state of a mobile phone network. Note that this plugin is currently only available on Android.
use
Whenever the network state changes, the Builder method of NetworkListener is called to call back the network state through status.
NetworkListener(
builder: (_,status){
var networkStatuds = "";
if (status == ConnectivityResult.none) {
networkStatuds = "Network unavailable";
}
if (status == ConnectivityResult.has) {
networkStatuds = "Network available";
}
returnText(networkStatuds); },)Copy the code
The effect
The principle of
Using StreamBuilder
The NetworkListener encapsulates a StreamBuilder that receives the Stream returned by the Native end to call back the network state. The code is as follows:
class NetworkListener extends StatelessWidget {
const NetworkListener({
required this.builder,
Key? key}) : super(key: key);
final Widget Function(BuildContext context, ConnectivityResult connectivityResult) builder;
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: NetworkStatusNotifier.getNetworkStatus(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.connectionState == ConnectionState.active && snapshot.hasData){
return builder(context,snapshot.data);
}
returnbuilder(context,ConnectivityResult.none); }); }}Copy the code
How to make native return Stream
How do YOU make the Native end return Strea? First, you need to create an EventChannel in the onAttachedToEngine of the Native FlutterPlugin and use its setStreamHandler method to set what to call back to the DART side. The code is as follows, notice network_status_notifier_EC, which needs to correspond to the DART end.
// ...
private EventChannel eventChannel;
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),"network_status_notifier_ec");
ConnectivityBroadcastReceiver connectivityBroadcastReceiver = new ConnectivityBroadcastReceiver(flutterPluginBinding.getApplicationContext());
eventChannel.setStreamHandler(connectivityBroadcastReceiver);
}
// ...
Copy the code
On the DART side, an EventChannel is also created to receive the stream returned by Native
/// Connection status check result.
enum ConnectivityResult {
/// has network.
has,
/// None: Device not connected to any network
none
}
class NetworkStatusNotifier {
static const EventChannel _eventChannel = EventChannel("network_status_notifier_ec");
static Stream<ConnectivityResult>? _networkStatus;
staticStream<ConnectivityResult> getNetworkStatus(){ _networkStatus ?? = _eventChannel.receiveBroadcastStream().map((satues) => parseResult(satues));return_networkStatus! ; }static ConnectivityResult parseResult(int i){
switch(i){
case 0:
return ConnectivityResult.none;
case 1:
return ConnectivityResult.has;
default:
returnConnectivityResult.none; }}}Copy the code
How to Listen to the Network
The monitoring network has different implementations in different Android versions. This project uses the mode of monitoring broadcast to monitor the network status under Android N, while the mode of registration callback is used when the network status is larger than Android N. The code is as follows:
public class ConnectivityBroadcastReceiver extends BroadcastReceiver
implements EventChannel.StreamHandler{
public ConnectivityBroadcastReceiver(Context context) {
this.context = context;
connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private Context context;
private ConnectivityManager connectivityManager;
// Callback result
private EventChannel.EventSink events;
public static final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";
private Handler mainHandler = new Handler(Looper.getMainLooper());
private ConnectivityManager.NetworkCallback networkCallback;
@Override
public void onReceive(Context context, Intent intent) {
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//
if(networkInfo ! =null && networkInfo.isAvailable()) {
// network is available.
callbackNetworkStatus(1);
} else {
// network is unavailable.
callbackNetworkStatus(0); }}}@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
this.events = events;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
networkCallback =
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
sendEvent(1);
}
@Override
public void onUnavailable(a) {
sendEvent(0);
}
@Override
public void onLost(Network network) {
sendEvent(0); }}; connectivityManager.registerDefaultNetworkCallback(networkCallback); }else {
context.registerReceiver(this.newIntentFilter(CONNECTIVITY_CHANGE)); }}@Override
public void onCancel(Object arguments) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if(networkCallback ! =null) { connectivityManager.unregisterNetworkCallback(networkCallback); }}else {
context.unregisterReceiver(this); }}private void callbackNetworkStatus(int status){
if(events ! =null){ events.success(status); }}private void sendEvent(final int status) {
Runnable runnable =
new Runnable() {
@Override
public void run(a) { events.success(status); }}; mainHandler.post(runnable); }}Copy the code
The complete code
Github.com/obweix/flut…