每个人!我正在开发一个 Android 应用程序,允许与附近已安装此应用程序的设备聊天。为了实现这一点,我正在使用 Wi-Fi P2P API 和网络服务发现来搜索附近的此类设备。我已经编写了用于在服务启动的线程中搜索附近设备的代码。当检测到设备时,Service 将其(通过广播意图)发送到显示目前检测到的设备的 Activity。检测到的设备被添加到 recyclerView 中,当用户按下其中一个时,必须建立与此类设备的连接。Wi-Fi Direct 连接建立成功(即 WifiP2pManager.connect() 方法成功)并捕获 WIFI_P2P_CONNECTION_CHANGED_ACTION。在广播接收器中,当这样的广播意图被捕获时,
NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected()) {
mManager.requestConnectionInfo(mChannel, connectionInfoListener); }
使用 requestConnectionInfo() 方法,我可以获得有关连接的更多信息,例如我尝试连接的设备的 IP 地址。为了获取此类信息,我为该方法提供了 WifiP2pManager.ConnectionInfoListener 的实现,由 connectionInfoListener 变量表示。这是我实现 WifiP2pManager.ConnectionInfoListener 的代码:
private WifiP2pManager.ConnectionInfoListener connectionInfoListener = new WifiP2pManager.ConnectionInfoListener() {
@Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
InetAddress deviceIP = info.groupOwnerAddress;
int port = servicesConnectionInfo.get(device);
ConnectThread connectThread = new ConnectThread(deviceIP, port, device);
connectThread.start();
“设备”是我的 BroadcastReceiver 实现的一个实例变量,现在并不重要。相反,重要的是 ConnectThread 线程。这是处理连接两个设备之间的套接字所需代码的线程。当我尝试连接到检测到的设备时,ConnectThread 在其 run() 方法中创建一个新的 ChatConnection 实例,将先前获得的 IP 地址和端口号传递给此构造函数:
public ChatConnection(InetAddress srvAddress, int srvPort, String macAddress) throws IOException {
...
connSocket = new Socket(srvAddress, srvPort);
...
}
这就是问题发生的地方。当我在我的物理设备上测试我的应用程序时,我得到的只是这个异常:
W/System.err: java.net.ConnectException: failed to connect to /192.168.49.1 (port 6770): connect failed: ECONNREFUSED (Connection refused)
当然,我也在第二个物理设备上安装了我的应用程序,它被成功检测到并且 Wi-Fi Direct 连接成功建立。但是,当谈到这行代码时:
connSocket = new Socket(srvAddress, srvPort);
抛出异常......我为这个问题的长度道歉,但我想尽可能清楚。我真的提前感谢您的帮助。
编辑:我忘了提及初始化 ServerSocket 的代码。
ServerSocket 在启用 Wi-Fi 后立即启动的线程中进行初始化。
也就是说,当 WifiP2pBroadcastReceiver(扩展 BroadcastReceiver 的应用服务的内部类)捕获 WIFI_P2P_STATE_CHANGED_ACTION 意图时,它会检查 Wi-Fi 是否启用,如果启用,它会启动 ServerSocket 所在的线程:
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) {
int statoWiFi = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (statoWiFi == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
mNsdService = new NsdProviderThread();
mNsdService.start();
}
ServerSocket 在 NsdProviderThread 的 run() 方法中初始化:
public void run() {
...
try {
server = new ServerSocket(0);
} catch (IOException ex) {
return;
}
...
while (!Thread.currentThread().isInterrupted()) {
Socket clientSocket = null;
try {
clientSocket = server.accept();
} catch (IOException ex) {
break;
}
try {
ChatConnection chatConn = new ChatConnection(clientSocket);
synchronized (connections) {
connections.add(chatConn);
}
} catch (IOException ex) {
continue;
}
}
“server”是 NsdProviderThread 的一个实例变量,声明为 ServerSocket。