There are several functions in my application that require Internet access. For these purposes, I did the following:
Alert Dialog and connection check are in a separate file:
//Alert Dialog about Internet connection
class InternetDialogHandler {
showInternetDialog(BuildContext context) {
// set up the button
Widget okButton = Center(
child: TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
},
),
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
// title: Text("My title"),
content: Text("Internet connection required"),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
//Check User Connection
class CheckUserConnection {
Future checkInternetAvailability() async {
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
}
On the main page, I check the Internet access when the application starts and when the button is tapped:
class _MainWidgetState extends State<MainWidget> {
CheckUserConnection _checkUserConnection = CheckUserConnection();
InternetDialogHandler _internetDialogHandler = InternetDialogHandler();
bool? _internetAvailable;
@override
void initState(){
super.initState();
checkNet();
}
void checkNet() async{
_internetAvailable = await
_checkUserConnection.checkInternetAvailability();
setState((){});
}
...
@override
Widget build(BuildContext context) {
return Container(
...
GradientButton(label: 'New Game', onTap: () {
return _internetAvailable == true ?
{Navigator.push(
context,
MaterialPageRoute(builder: (context) => Game(
listCount: 0, assetPath: "assets/images/01.jpg"
)),
)}
:
_internetDialogHandler.showInternetDialog(context);
}),
...
If there is no Internet connection when starting the application, a corresponding message pops up. And it is right. But if my user turns on Internet access in a smartphone (or in an emulator, as I do for testing), then nothing changes when the button is tapped. The app still thinks that there is no Internet access.
Where is the error in this code? And how to fix it?
Thanks in advance for your reply.
CodePudding user response:
There are multiple packages for this already on pub.dev, so using connectivity_plus that as an example on the receiving end you need to subscribe to a stream like this:
import 'package:connectivity_plus/connectivity_plus.dart';
@override
initState() {
super.initState();
subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
// Got a new connectivity status!
})
}
// Be sure to cancel subscription after you are done
@override
dispose() {
super.dispose();
subscription.cancel();
}
Your own version could maybe start from this to check every 15 seconds:
var onConnectivityChanged =
Stream<bool>.periodic(const Duration(seconds: 15),
(x) => _checkUserConnection.checkInternetAvailability());
But the good thing about using an existing package like connectivity_plus is that it will use the device APIs to figure out the connectivity, instead of a homebrewn solution! :)
There are whole articles about creating streams!