如何在Flutter应用及Android Things设备中集成Google Nearby API实现WiFi相关操作?
嘿,我来分享下这两个场景的具体实现方案,都是我实际项目里踩过坑后总结的经验~
因为Flutter官方没有直接封装Nearby API,所以咱们得通过Platform Channel对接Android原生的Nearby Connections API(iOS端WiFi凭证共享限制较多,这里重点讲Android):
步骤1:配置Android项目依赖
打开android/app/build.gradle,添加Nearby Connections的依赖:
dependencies { // 其他依赖... implementation 'com.google.android.gms:play-services-nearby:18.0.0' // 选最新稳定版 }
步骤2:申请必要权限
在AndroidManifest.xml里声明权限,注意Android版本差异:
<!-- 基础权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- Android 12+ 新增蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
别忘了在Flutter端或者原生端动态申请权限,因为位置、蓝牙权限需要用户手动授权。
步骤3:原生Android端实现核心逻辑
创建一个NearbyWifiSharePlugin类,通过MethodChannel和Flutter通信:
关键代码片段:
public class NearbyWifiSharePlugin implements MethodCallHandler { private final Context context; private NearbyConnectionsClient nearbyClient; private WifiManager wifiManager; private NearbyWifiSharePlugin(Context context) { this.context = context; nearbyClient = Nearby.getConnectionsClient(context); wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); } // 注册MethodChannel public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "nearby_wifi_share"); channel.setMethodCallHandler(new NearbyWifiSharePlugin(registrar.context())); } @Override public void onMethodCall(MethodCall call, Result result) { switch (call.method) { case "shareWifi": shareCurrentWifiCredentials(); result.success("开始共享WiFi凭证"); break; case "receiveWifi": startReceivingWifiCredentials(); result.success("开始监听WiFi凭证"); break; default: result.notImplemented(); } } // 共享当前WiFi凭证 private void shareCurrentWifiCredentials() { // 获取当前连接的WiFi信息(Android 10+需要位置权限开启才能拿到SSID) WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String ssid = wifiInfo.getSSID().replace("\"", ""); // 注意:普通APP无法直接读取系统保存的WiFi密码,这里建议用用户输入的凭证或应用自身存储的密码 String password = "user_input_password"; String encryptionType = "WPA2"; // 根据实际网络类型调整 // 打包成JSON发送 String credentials = "{\"ssid\":\"" + ssid + "\",\"password\":\"" + password + "\",\"type\":\"" + encryptionType + "\"}"; // 初始化Nearby广播,等待接收方连接 nearbyClient.startAdvertising( "WiFi共享发起方", "com.your.package.wifi_share", connectionLifecycleCallback, new AdvertisingOptions.Builder().setStrategy(Strategy.P2P_STAR).build() ); } // 接收WiFi凭证并连接 private void startReceivingWifiCredentials() { nearbyClient.startDiscovery( "com.your.package.wifi_share", endpointDiscoveryCallback, new DiscoveryOptions.Builder().setStrategy(Strategy.P2P_STAR).build() ); } // 连接生命周期回调 private final ConnectionLifecycleCallback connectionLifecycleCallback = new ConnectionLifecycleCallback() { @Override public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) { // 接受连接请求 nearbyClient.acceptConnection(endpointId, payloadCallback); } @Override public void onConnectionResult(String endpointId, ConnectionResolution result) { if (result.getStatus().isSuccess()) { // 连接成功,发送WiFi凭证 nearbyClient.sendPayload(endpointId, Payload.fromBytes(credentials.getBytes())); } } @Override public void onDisconnected(String endpointId) {} }; // 数据接收回调 private final PayloadCallback payloadCallback = new PayloadCallback() { @Override public void onPayloadReceived(String endpointId, Payload payload) { if (payload.getType() == Payload.Type.BYTES) { String credentials = new String(payload.asBytes()); // 解析JSON获取SSID和密码 try { JSONObject json = new JSONObject(credentials); String ssid = json.getString("ssid"); String password = json.getString("password"); // 配置并连接WiFi WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"" + ssid + "\""; config.preSharedKey = "\"" + password + "\""; int networkId = wifiManager.addNetwork(config); wifiManager.enableNetwork(networkId, true); } catch (JSONException e) { e.printStackTrace(); } } } @Override public void onPayloadTransferUpdate(String endpointId, PayloadTransferUpdate update) {} }; // 端点发现回调 private final EndpointDiscoveryCallback endpointDiscoveryCallback = new EndpointDiscoveryCallback() { @Override public void onEndpointFound(String endpointId, DiscoveredEndpointInfo info) { // 请求连接到发起方 nearbyClient.requestConnection( "WiFi接收方", endpointId, connectionLifecycleCallback ); } @Override public void onEndpointLost(String endpointId) {} }; }
步骤4:Flutter端调用原生方法
创建MethodChannel,调用原生的共享和接收方法:
import 'package:flutter/services.dart'; import 'dart:convert'; class NearbyWifiShare { static const MethodChannel _channel = MethodChannel('nearby_wifi_share'); static Future<String> shareWifi() async { final String result = await _channel.invokeMethod('shareWifi'); return result; } static Future<String> receiveWifi() async { final String result = await _channel.invokeMethod('receiveWifi'); return result; } }
之后在UI里添加按钮调用这两个方法即可完成交互。
Android Things本质上是简化版的Android系统,所以同样可以集成Nearby Connections API,和Flutter应用(通过Platform Channel对接的Nearby)实现跨设备通信,进而搭建本地WiFi网络。
核心场景
分两种常见使用方式:
- Android Things创建WiFi热点:Flutter应用发送热点配置给设备,设备创建热点后,Flutter应用连接形成本地网络。
- Android Things连接现有WiFi:Flutter应用共享当前WiFi凭证给设备,设备连接到同一局域网。
步骤1:Android Things端配置
- 创建Android Things项目,添加和之前一致的Nearby Connections依赖。
- 在
AndroidManifest.xml里声明相同的权限(Android Things可能默认开启部分权限,但仍需显式声明)。 - 确保开发板(比如Raspberry Pi 3/4)支持蓝牙和WiFi硬件。
步骤2:Android Things端实现通信与WiFi控制
创建一个后台Service处理Nearby通信和WiFi操作:
public class NearbyIotService extends Service { private NearbyConnectionsClient nearbyClient; private WifiManager wifiManager; @Override public void onCreate() { super.onCreate(); nearbyClient = Nearby.getConnectionsClient(this); wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); startDiscovery(); // 启动发现Flutter应用的端点 } private void startDiscovery() { nearbyClient.startDiscovery( "com.your.package.iot_comm", new EndpointDiscoveryCallback() { @Override public void onEndpointFound(String endpointId, DiscoveredEndpointInfo info) { // 请求连接到Flutter应用 nearbyClient.requestConnection( "Android Things设备", endpointId, connectionLifecycleCallback ); } @Override public void onEndpointLost(String endpointId) {} }, new DiscoveryOptions.Builder().setStrategy(Strategy.P2P_STAR).build() ); } private final ConnectionLifecycleCallback connectionLifecycleCallback = new ConnectionLifecycleCallback() { @Override public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) { nearbyClient.acceptConnection(endpointId, payloadCallback); } @Override public void onConnectionResult(String endpointId, ConnectionResolution result) { if (result.getStatus().isSuccess()) { // 连接成功,等待接收指令 } } @Override public void onDisconnected(String endpointId) {} }; private final PayloadCallback payloadCallback = new PayloadCallback() { @Override public void onPayloadReceived(String endpointId, Payload payload) { if (payload.getType() == Payload.Type.BYTES) { String command = new String(payload.asBytes()); try { JSONObject json = new JSONObject(command); String action = json.getString("action"); switch (action) { case "CREATE_HOTSPOT": String ssid = json.getString("ssid"); String password = json.getString("password"); createWifiHotspot(ssid, password); break; case "CONNECT_WIFI": String wifiSsid = json.getString("ssid"); String wifiPassword = json.getString("password"); connectToWifi(wifiSsid, wifiPassword); break; } } catch (JSONException e) { e.printStackTrace(); } } } @Override public void onPayloadTransferUpdate(String endpointId, PayloadTransferUpdate update) {} }; // 创建WiFi热点 private void createWifiHotspot(String ssid, String password) { WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"" + ssid + "\""; config.preSharedKey = "\"" + password + "\""; config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); config.allowedProtocols.set(WifiConfiguration.Protocol.RSN); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); wifiManager.setWifiEnabled(false); wifiManager.setWifiApEnabled(config, true); } // 连接到指定WiFi private void connectToWifi(String ssid, String password) { WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"" + ssid + "\""; config.preSharedKey = "\"" + password + "\""; int networkId = wifiManager.addNetwork(config); wifiManager.enableNetwork(networkId, true); wifiManager.setWifiEnabled(true); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
记得在AndroidManifest.xml里注册这个Service。
步骤3:Flutter端发送控制指令
通过MethodChannel调用原生发送方法,传递控制指令:
import 'package:flutter/services.dart'; import 'dart:convert'; class NearbyIotComm { static const MethodChannel _channel = MethodChannel('nearby_iot_comm'); static Future<void> sendCreateHotspot(String ssid, String password) async { final String command = jsonEncode({ "action": "CREATE_HOTSPOT", "ssid": ssid, "password": password }); await _channel.invokeMethod('sendCommand', command); } static Future<void> sendConnectWifi(String ssid, String password) async { final String command = jsonEncode({ "action": "CONNECT_WIFI", "ssid": ssid, "password": password }); await _channel.invokeMethod('sendCommand', command); } }
原生端只需实现sendCommand方法,通过Nearby的sendPayload把指令发送给Android Things设备即可。
注意事项
- 选择合适的Nearby策略:
Strategy.P2P_STAR适合一对多控制(一个Flutter应用管理多个IoT设备),Strategy.P2P_CLUSTER适合多设备间互相通信。 - 添加重连逻辑:处理连接断开的情况,确保通信稳定性。
- 硬件兼容性:部分开发板可能需要手动开启蓝牙/WiFi硬件开关,提前测试确认。
内容的提问来源于stack exchange,提问作者Loran

