Flutter 好用套件wifi_iot
wifi_iot | Flutter Package (pub.dev)
目前版本^0.3.8 Published Sep 22, 2021
Plugin Flutter which can handle WiFi connections (AP, STA)
Becareful, some commands as no effect on iOS because Apple don't let us to do whatever we want...
雖然功能有限,但是做基本的物聯網APP開發已足夠,以下範例取自https://pub.dev/packages/wifi_iot/example 並且我已刪除WIFI STA內容
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:wifi_iot/wifi_iot.dart';
import 'dart:io' show Platform;
const NetworkSecurity AP_DEFAULT_SECURITY = NetworkSecurity.WPA;
const String AP_DEFAULT_SSID = "AP_SSID";
const String AP_DEFAULT_PASSWORD = "AP_PASSWORD";
//父狀態主頁(樣式+Wifi ststus)
class FlutterWifiIoT extends StatefulWidget {
FlutterWifiIoT({
Key? key,
}) : super(key: key);
@override
_FlutterWifiIoTState createState() => _FlutterWifiIoTState();
//建立status
}
class _FlutterWifiIoTState extends State<FlutterWifiIoT> {
List<WifiNetwork?>? _htResultNetwork; //WIFI可連清單
Map<String, bool>? _htIsNetworkRegistered = Map(); //WIFI SSID儲存清單與狀態
bool _isEnabled = false; //WIFI是否開啟
bool _isConnected = false; //WIFI是否已連接
bool _isWifiEnableOpenSettings = false; //是否被動開啟(Android 10)
bool _isWifiDisableOpenSettings = false; //是否被動關閉(Android 10)
final TextStyle textStyle = TextStyle(color: Colors.white);
@override
initState() {
WiFiForIoTPlugin.isEnabled().then((val) {
_isEnabled = val;
});
WiFiForIoTPlugin.isConnected().then((val) {
_isConnected = val;
});
super.initState();
}
//使用函式庫載入WIFI列表
Future<List<WifiNetwork>> loadWifiList() async {
List<WifiNetwork> htResultNetwork;
try {
htResultNetwork = await WiFiForIoTPlugin.loadWifiList();
} on PlatformException {
htResultNetwork = <WifiNetwork>[];
}
return htResultNetwork;
}
//檢查是否已註冊SSID方法(存到Map ket,value)
isRegisteredWifiNetwork(String ssid) async {
bool bIsRegistered;
try {
bIsRegistered = await WiFiForIoTPlugin.isRegisteredWifiNetwork(ssid);
} on PlatformException {
bIsRegistered = false;
}
setState(() {
_htIsNetworkRegistered![ssid] = bIsRegistered;
});
}
///Main body
Widget getWidgets() {
WiFiForIoTPlugin.isConnected().then((val) {
setState(() {
_isConnected = val; //WIFI 為已連線狀態
});
});
// disable scanning for ios as not supported
//IOS手機無法支援WIFI清單功能
if (_isConnected || Platform.isIOS) {
_htResultNetwork = null;
}
//如果是Android, 且存在可連線網路, 否則不會載入WIFI清單
if (_htResultNetwork != null && _htResultNetwork!.length > 0) {
List<ListTile> htNetworks = <ListTile>[];
_htResultNetwork!.forEach((oNetwork) {
//將可連線網路跑一遍
PopupCommand oCmdConnect = PopupCommand("Connect", oNetwork!.ssid!);
PopupCommand oCmdRemove = PopupCommand("Remove", oNetwork.ssid!);
List<PopupMenuItem<PopupCommand>> htPopupMenuItems = [];
//加到popupMenu(選項為可連線)
htPopupMenuItems.add(
PopupMenuItem<PopupCommand>(
value: oCmdConnect,
child: const Text('Connect'),
),
);
setState(() {
isRegisteredWifiNetwork(oNetwork.ssid!);
//辨識這個SSID是否已儲存至系統,並在value中用布林表示
if (_htIsNetworkRegistered!.containsKey(oNetwork.ssid) &&
_htIsNetworkRegistered![oNetwork.ssid]!) {
htPopupMenuItems.add(
PopupMenuItem<PopupCommand>(
value: oCmdRemove,
child: const Text('Remove'),
),//已儲存就可以提供刪除選項
);
}
htNetworks.add(
ListTile(
title: Text("" +
oNetwork.ssid! +
((_htIsNetworkRegistered!.containsKey(oNetwork.ssid) &&
_htIsNetworkRegistered![oNetwork.ssid]!)
? " *"
: "")),//加入網路名稱,如果已註冊就標示*
trailing: PopupMenuButton<PopupCommand>(
padding: EdgeInsets.zero,
onSelected: (PopupCommand poCommand) {
//加入子元素(連線/刪除選項), 會判斷htPopupMenuItems傳進來的value
switch (poCommand.command) {
case "Connect":
WiFiForIoTPlugin.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: AP_DEFAULT_SECURITY);
break;
case "Remove":
WiFiForIoTPlugin.removeWifiNetwork(poCommand.argument);
break;
default:
break;
}
},
itemBuilder: (BuildContext context) => htPopupMenuItems,
),
),
);
});
});
return ListView(
padding: kMaterialListPadding,
children: htNetworks,
);
} else {
//如果是IOS, Android搜尋結果為0時進入這邊
return SingleChildScrollView(
child: SafeArea(
child: Column(
children: Platform.isIOS
? getButtonWidgetsForiOS()
: getButtonWidgetsForAndroid(),
),
),
);
}
}
List<Widget> getButtonWidgetsForAndroid() {
List<Widget> htPrimaryWidgets = <Widget>[];
WiFiForIoTPlugin.isEnabled().then((val) {
setState(() {
_isEnabled = val;
});
});
if (_isEnabled) {
htPrimaryWidgets.addAll([
SizedBox(height: 10),
Text("Wifi Enabled"),
MaterialButton(
color: Colors.blue,
child: Text("Disable", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.setEnabled(false,
shouldOpenSettings: _isWifiDisableOpenSettings
);
},
),
]);
WiFiForIoTPlugin.isConnected().then((val) {
setState(() {
_isConnected = val;
});
});
if (_isConnected) {
//已經連上Wifi, 回傳連線資訊
htPrimaryWidgets.addAll(<Widget>[
Text("Connected"),
FutureBuilder(
future: WiFiForIoTPlugin.getSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ssid) {
return Text("SSID: ${ssid.data}");
}),
FutureBuilder(
future: WiFiForIoTPlugin.getBSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> bssid) {
return Text("BSSID: ${bssid.data}");
}),
FutureBuilder(
future: WiFiForIoTPlugin.getCurrentSignalStrength(),
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int?> signal) {
return Text("Signal: ${signal.data}");
}),
FutureBuilder(
future: WiFiForIoTPlugin.getFrequency(),
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int?> freq) {
return Text("Frequency : ${freq.data}");
}),
FutureBuilder(
future: WiFiForIoTPlugin.getIP(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ip) {
return Text("IP : ${ip.data}");
}),
MaterialButton(
color: Colors.blue,
child: Text("Disconnect", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.disconnect();
},
),
CheckboxListTile(
title: const Text("Disable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiDisableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiDisableOpenSettings = setting;
});
}
}
) //Android 在API29以上可以被動接收WIFI info
]);
} else {
//未連上WIFI, 顯示WIFI搜尋
htPrimaryWidgets.addAll(<Widget>[
Text("Disconnected"),
MaterialButton(
color: Colors.blue,
child: Text("Scan", style: textStyle),
onPressed: () async {
_htResultNetwork = await loadWifiList();
setState(() {});
},
),
CheckboxListTile(
title: const Text("Disable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiDisableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiDisableOpenSettings = setting;
});
}
}
)
]);
}
} else {
//WIFI設定未開啟
htPrimaryWidgets.addAll(<Widget>[
SizedBox(height: 10),
Text("Wifi Disabled"),
MaterialButton(
color: Colors.blue,
child: Text("Enable", style: textStyle),
onPressed: () {
setState(() {
WiFiForIoTPlugin.setEnabled(true,
shouldOpenSettings: _isWifiEnableOpenSettings
);
});
},
),
CheckboxListTile(
title: const Text("Enable WiFi on settings"),
subtitle: const Text("Available only on android API level >= 29"),
value: _isWifiEnableOpenSettings,
onChanged: (bool? setting) {
if (setting != null) {
setState(() {
_isWifiEnableOpenSettings = setting;
});
}
}
)
]);
}
return htPrimaryWidgets;
}
List<Widget> getButtonWidgetsForiOS() {
List<Widget> htPrimaryWidgets = <Widget>[];
WiFiForIoTPlugin.isEnabled().then((val) => setState(() {
_isEnabled = val;
}));
if (_isEnabled) {
htPrimaryWidgets.add(Text("Wifi Enabled"));
WiFiForIoTPlugin.isConnected().then((val) => setState(() {
_isConnected = val;
}));
String? _sSSID;
if (_isConnected) {
//IOS 顯示連線(僅SSID)
htPrimaryWidgets.addAll(<Widget>[
Text("Connected"),
FutureBuilder(
future: WiFiForIoTPlugin.getSSID(),
initialData: "Loading..",
builder: (BuildContext context, AsyncSnapshot<String?> ssid) {
_sSSID = ssid.data;
return Text("SSID: ${ssid.data}");
}),
]);
if (_sSSID == AP_DEFAULT_SSID) {
//IOS連上指定SSID
htPrimaryWidgets.addAll(<Widget>[
MaterialButton(
color: Colors.blue,
child: Text("Disconnect", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.disconnect();
},
),
]);
} else {
//IOS未上指定SSID, 提供按鈕直接連
htPrimaryWidgets.addAll(<Widget>[
MaterialButton(
color: Colors.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}
} else {
//IOS未上網路, 一樣提供按鈕直接連
htPrimaryWidgets.addAll(<Widget>[
Text("Disconnected"),
MaterialButton(
color: Colors.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}
} else {
//IOS WIFI是關閉的, 給設定可以硬連
htPrimaryWidgets.addAll(<Widget>[
Text("Wifi Disabled?"),
MaterialButton(
color: Colors.blue,
child: Text("Connect to '$AP_DEFAULT_SSID'", style: textStyle),
onPressed: () {
WiFiForIoTPlugin.connect(AP_DEFAULT_SSID,
password: AP_DEFAULT_PASSWORD,
joinOnce: true,
security: NetworkSecurity.WPA);
},
),
]);
}
return htPrimaryWidgets;
}
@override
Widget build(BuildContext poContext) {
return MaterialApp(
title: Platform.isIOS ?
"WifiFlutter Example iOS" : "WifiFlutter Example Android",
home: Scaffold(
appBar: AppBar(
title: Platform.isIOS
? Text('WifiFlutter Example iOS')
: Text('WifiFlutter Example Android'),
actions: _isConnected
? <Widget>[
PopupMenuButton<String>(
onSelected: (value) {
switch (value) {
case "disconnect":
WiFiForIoTPlugin.disconnect();
break;
case "remove":
WiFiForIoTPlugin.getSSID().then(
(val) => WiFiForIoTPlugin.removeWifiNetwork(val!));
break;
default:
break;
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuItem<String>>[
PopupMenuItem<String>(
value: "disconnect",
child: const Text('Disconnect'),
),
PopupMenuItem<String>(
value: "remove",
child: const Text('Remove'),
),
],
),
]
: null,
),
body: getWidgets(),
),
);
}
}
class PopupCommand {
String command;
String argument;
PopupCommand(this.command, this.argument);
}
//頁面樣式(無狀態)
class CardDemo extends StatelessWidget {
final TextEditingController _textFieldController = TextEditingController();
final List listData = [
{
"title": "物料站 1 ",
"context": "相關編號....",
},
{
"title": "物料站 2 ",
"context": "相關編號....",
}
];
@override
Widget build(BuildContext context) {
return ListView(
children: listData.map((value) {
return Card(
margin: EdgeInsets.all(10), //外邊距
child: Column(
//縱向排列元件
children: <Widget>[
ListTile(
title: Text(value["title"], style: TextStyle(fontSize: 28)),
subtitle: Text(value["context"],
overflow: TextOverflow.ellipsis,
maxLines: 2, //文字溢位
style: TextStyle(fontSize: 18, color: Colors.black)),
onTap: () => _displayDialog(context),
),
],
),
);
}).toList(),
);
}
_displayDialog(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Material Password'),
content: TextField(
controller: _textFieldController,
textInputAction: TextInputAction.go,
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(hintText: "Password"),
),
actions: <Widget>[
new FlatButton(
child: new Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text('Comfirm'),
onPressed: () {
_displayDialog2(context);
},
)
],
);
});
}
_displayDialog2(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Material Name'),
content: TextField(
controller: _textFieldController,
textInputAction: TextInputAction.go,
keyboardType: TextInputType.numberWithOptions(),
decoration: InputDecoration(hintText: "Password"),
),
actions: <Widget>[
new FlatButton(
child: new Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text('Comfirm'),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => XDChooseWifi()));
},
)
],
);
});
}
}
沒有留言:
張貼留言