1

My app makes local network calls. Is there a way, with flutter/dart, to force http.get() over WiFi (even if internet is not available) rather than 3G/4G?

tomerpacific
  • 4,704
  • 13
  • 34
  • 52
Eric
  • 477
  • 3
  • 17

4 Answers4

4

Core Flutter framework has not that feature yet(and won't have at least for a long time imo).

When it comes hardware related things, you can almost say that native code is only way to go. Good thing is there many official & third party packages that already done the job for you.

For example this package is popular one for connection related features: https://pub.dev/packages/connectivity

This is the example code you need:

import 'package:connectivity/connectivity.dart';

var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
  // I am connected to a mobile network.
} else if (connectivityResult == ConnectivityResult.wifi) {
  // I am connected to a wifi network.
}
Mehmet Esen
  • 6,156
  • 3
  • 25
  • 44
3

There is a plugin that helps you to solve the problem.

You need to add this https://github.com/alternadom/WiFiFlutter plugin to your project like so:

wifi_iot:
    git: https://github.com/alternadom/WiFiFlutter.git

and then to force wifi usage you call

  WiFiForIoTPlugin.forceWifiUsage(true);

I made it safe and added a platform check

import 'dart:io' show Platform;
if(Platform.isAndroid) {
   WiFiForIoTPlugin.forceWifiUsage(true);
}

The downside is, that at the first time you do this in your app, the user will be redirected to allow the app to change system settings (and from there the "back" navigation button doesn't work at the moment).

kilian eller
  • 184
  • 2
  • 16
1

This is not currently possible with flutter. The only way is to use platform native code via paltform-channels.

https://flutter.dev/docs/development/platform-integration/platform-channels

Eric
  • 477
  • 3
  • 17
0

This the issue only for android devices (you won't face this in iOS devices). Eric is right. You can achieve this using platform channels. In your project you can find MainActivity.kt file which is usually located in android -> app -> src -> main -> kotlin

I came up with this solution where you have to bind your network using Connectivity Manager and create channel to call it in your flutter app

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import androidx.annotation.NonNull
import android.net.NetworkRequest
import android.content.Context
import android.net.Network
import android.os.Build
import android.util.Log

class MainActivity: FlutterActivity() {
    private val channel = "ru.myPackageName.mobile/bindNetworkToWifi"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
                _, _ ->
                bindNetworkToWifi()
        }
    }

  private fun bindNetworkToWifi() {
      val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
      val builder = NetworkRequest.Builder()
      builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
      builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
      builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
      connectivityManager.requestNetwork(builder.build(), object : ConnectivityManager.NetworkCallback() {
          override fun onAvailable(network: Network) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                  connectivityManager.bindProcessToNetwork(network)
                  Log.d("Forced wifi usage", "onAvailable: true")
              }
          }
      })
  }
}

flutter code which I call in splash screen

final platform = MethodChannel('ru.myPackageName.mobile/bindNetworkToWifi');

  Future<void> _bindNetworkToWifi() async {
    try {
      platform.invokeMethod('bindNetworkToWifi');
      debugPrint("seems to be working: 'bindNetworkToWifi'.");
    } on PlatformException catch (e) {
      debugPrint("Failed to force wifi usage: '${e.message}'.");
    }
  }

More info can be found in here

CaypoH23
  • 21
  • 3