wifidirectplugin 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -8,6 +8,8 @@ import android.net.wifi.WpsInfo;
|
|
|
8
8
|
import android.net.wifi.p2p.*;
|
|
9
9
|
import android.net.NetworkInfo;
|
|
10
10
|
import android.os.Build;
|
|
11
|
+
import android.os.Handler;
|
|
12
|
+
import android.os.Looper;
|
|
11
13
|
import android.util.Log;
|
|
12
14
|
|
|
13
15
|
import com.getcapacitor.*;
|
|
@@ -29,6 +31,13 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
29
31
|
|
|
30
32
|
private PluginCall pendingConnectCall = null;
|
|
31
33
|
|
|
34
|
+
// Group 형성 broadcast가 안 올 경우 대비한 timeout과 메인 핸들러
|
|
35
|
+
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
36
|
+
private Runnable pendingConnectTimeout = null;
|
|
37
|
+
private static final long CONNECT_TIMEOUT_MS = 20000L;
|
|
38
|
+
// removeGroup 직후 framework가 안정될 때까지 대기 시간
|
|
39
|
+
private static final long REMOVE_GROUP_SETTLE_MS = 500L;
|
|
40
|
+
|
|
32
41
|
private final BroadcastReceiver wifiP2pReceiver = new BroadcastReceiver() {
|
|
33
42
|
@Override
|
|
34
43
|
public void onReceive(Context context, Intent intent) {
|
|
@@ -39,6 +48,7 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
39
48
|
if (networkInfo != null && networkInfo.isConnected()) {
|
|
40
49
|
Log.d(TAG, "Wi-Fi Direct connected");
|
|
41
50
|
if (pendingConnectCall != null) {
|
|
51
|
+
cancelConnectTimeout();
|
|
42
52
|
manager.requestConnectionInfo(channel, info -> {
|
|
43
53
|
if (info != null && info.groupFormed) {
|
|
44
54
|
Log.d(TAG, "Group formed, resolving connectToDevice");
|
|
@@ -50,6 +60,7 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
50
60
|
} else {
|
|
51
61
|
Log.d(TAG, "Wi-Fi Direct disconnected");
|
|
52
62
|
if (pendingConnectCall != null) {
|
|
63
|
+
cancelConnectTimeout();
|
|
53
64
|
pendingConnectCall.reject("Wi-Fi Direct connection lost before group formed");
|
|
54
65
|
pendingConnectCall = null;
|
|
55
66
|
}
|
|
@@ -155,21 +166,31 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
155
166
|
|
|
156
167
|
manager.requestConnectionInfo(channel, info -> {
|
|
157
168
|
if(info != null && info.groupFormed) {
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
// 그룹 해제 성공 시 연결 계속 진행
|
|
165
|
-
initiateConnect(deviceAddress, pin, call);
|
|
166
|
-
}
|
|
167
|
-
@Override
|
|
168
|
-
public void onFailure(int reason) {
|
|
169
|
-
Log.w(TAG, "removeGroup failed: " + reason + ". Proceed anyway.");
|
|
170
|
-
// 그룹 해제 실패 시에도 연결 시도(혹은 call.reject로 실패 처리 가능)
|
|
171
|
-
initiateConnect(deviceAddress, pin, call);
|
|
169
|
+
// 이미 그룹이 형성된 경우, 대상 기기와의 그룹이면 그대로 사용
|
|
170
|
+
manager.requestGroupInfo(channel, group -> {
|
|
171
|
+
if (group != null && isTargetInGroup(group, deviceAddress)) {
|
|
172
|
+
Log.d(TAG, "Already in group with target device, resolving immediately");
|
|
173
|
+
call.resolve();
|
|
174
|
+
return;
|
|
172
175
|
}
|
|
176
|
+
Log.d(TAG, "Existing Wi-Fi Direct group is not the target. Removing group.");
|
|
177
|
+
manager.removeGroup(channel, new WifiP2pManager.ActionListener() {
|
|
178
|
+
@Override
|
|
179
|
+
public void onSuccess() {
|
|
180
|
+
Log.d(TAG, "removeGroup success, settle " + REMOVE_GROUP_SETTLE_MS + "ms before connect.");
|
|
181
|
+
// P2P framework가 BUSY 상태에서 빠져나올 시간 확보
|
|
182
|
+
mainHandler.postDelayed(
|
|
183
|
+
() -> initiateConnect(deviceAddress, pin, call),
|
|
184
|
+
REMOVE_GROUP_SETTLE_MS);
|
|
185
|
+
}
|
|
186
|
+
@Override
|
|
187
|
+
public void onFailure(int reason) {
|
|
188
|
+
Log.w(TAG, "removeGroup failed: " + reasonName(reason) + ". Proceed anyway after settle.");
|
|
189
|
+
mainHandler.postDelayed(
|
|
190
|
+
() -> initiateConnect(deviceAddress, pin, call),
|
|
191
|
+
REMOVE_GROUP_SETTLE_MS);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
173
194
|
});
|
|
174
195
|
} else {
|
|
175
196
|
Log.d(TAG, "No existing group, proceed to connect directly.");
|
|
@@ -177,6 +198,23 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
177
198
|
}
|
|
178
199
|
});
|
|
179
200
|
}
|
|
201
|
+
|
|
202
|
+
private boolean isTargetInGroup(WifiP2pGroup group, String deviceAddress) {
|
|
203
|
+
if (deviceAddress == null) return false;
|
|
204
|
+
WifiP2pDevice owner = group.getOwner();
|
|
205
|
+
if (owner != null && deviceAddress.equalsIgnoreCase(owner.deviceAddress)) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
if (group.getClientList() != null) {
|
|
209
|
+
for (WifiP2pDevice client : group.getClientList()) {
|
|
210
|
+
if (deviceAddress.equalsIgnoreCase(client.deviceAddress)) {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
|
|
180
218
|
private void initiateConnect(String deviceAddress, String pin, PluginCall call) {
|
|
181
219
|
WifiP2pConfig config = new WifiP2pConfig();
|
|
182
220
|
config.deviceAddress = deviceAddress;
|
|
@@ -190,30 +228,86 @@ public class WifiDirectPlugin extends Plugin {
|
|
|
190
228
|
Log.w(TAG, "Invalid Pin");
|
|
191
229
|
}
|
|
192
230
|
}
|
|
231
|
+
|
|
232
|
+
// 직전 시도에서 남았을 수 있는 pending negotiation을 명시적으로 정리.
|
|
233
|
+
// 실패해도 (보통 NO_SERVICE_REQUESTS 등) 그냥 무시하고 connect 진행.
|
|
234
|
+
try {
|
|
235
|
+
manager.cancelConnect(channel, new WifiP2pManager.ActionListener() {
|
|
236
|
+
@Override
|
|
237
|
+
public void onSuccess() {
|
|
238
|
+
Log.d(TAG, "cancelConnect success, performing connect");
|
|
239
|
+
performConnect(config, call);
|
|
240
|
+
}
|
|
241
|
+
@Override
|
|
242
|
+
public void onFailure(int reason) {
|
|
243
|
+
Log.d(TAG, "cancelConnect failed (ignored): " + reasonName(reason));
|
|
244
|
+
performConnect(config, call);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
} catch (Exception e) {
|
|
248
|
+
Log.w(TAG, "cancelConnect exception (ignored)", e);
|
|
249
|
+
performConnect(config, call);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private void performConnect(WifiP2pConfig config, PluginCall call) {
|
|
193
254
|
try {
|
|
194
255
|
manager.connect(channel, config, new WifiP2pManager.ActionListener() {
|
|
195
256
|
@Override
|
|
196
257
|
public void onSuccess() {
|
|
197
258
|
// connect request accepted — group formation is async
|
|
198
259
|
// resolve will be called from BroadcastReceiver once group is formed
|
|
199
|
-
Log.d(TAG, "connect onSuccess Called, waiting for group formation");
|
|
260
|
+
Log.d(TAG, "connect onSuccess Called, waiting for group formation (timeout " + CONNECT_TIMEOUT_MS + "ms)");
|
|
200
261
|
pendingConnectCall = call;
|
|
262
|
+
scheduleConnectTimeout();
|
|
201
263
|
}
|
|
202
264
|
|
|
203
265
|
@Override
|
|
204
266
|
public void onFailure(int reason) {
|
|
205
|
-
Log.e(TAG, "connect onFailure
|
|
267
|
+
Log.e(TAG, "connect onFailure: " + reasonName(reason));
|
|
206
268
|
pendingConnectCall = null;
|
|
207
|
-
|
|
269
|
+
cancelConnectTimeout();
|
|
270
|
+
call.reject("Connection failed: " + reasonName(reason));
|
|
208
271
|
}
|
|
209
272
|
});
|
|
210
273
|
} catch (Exception e) {
|
|
211
274
|
Log.e(TAG, "connect exception", e);
|
|
212
275
|
pendingConnectCall = null;
|
|
276
|
+
cancelConnectTimeout();
|
|
213
277
|
call.reject("Connection exception: " + e.getMessage());
|
|
214
278
|
}
|
|
215
279
|
}
|
|
216
280
|
|
|
281
|
+
private void scheduleConnectTimeout() {
|
|
282
|
+
cancelConnectTimeout();
|
|
283
|
+
pendingConnectTimeout = () -> {
|
|
284
|
+
if (pendingConnectCall != null) {
|
|
285
|
+
Log.w(TAG, "Group formation timed out after " + CONNECT_TIMEOUT_MS + "ms");
|
|
286
|
+
pendingConnectCall.reject("Group formation timed out");
|
|
287
|
+
pendingConnectCall = null;
|
|
288
|
+
}
|
|
289
|
+
pendingConnectTimeout = null;
|
|
290
|
+
};
|
|
291
|
+
mainHandler.postDelayed(pendingConnectTimeout, CONNECT_TIMEOUT_MS);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private void cancelConnectTimeout() {
|
|
295
|
+
if (pendingConnectTimeout != null) {
|
|
296
|
+
mainHandler.removeCallbacks(pendingConnectTimeout);
|
|
297
|
+
pendingConnectTimeout = null;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private String reasonName(int reason) {
|
|
302
|
+
switch (reason) {
|
|
303
|
+
case WifiP2pManager.ERROR: return "ERROR(0)";
|
|
304
|
+
case WifiP2pManager.P2P_UNSUPPORTED: return "P2P_UNSUPPORTED(1)";
|
|
305
|
+
case WifiP2pManager.BUSY: return "BUSY(2)";
|
|
306
|
+
case WifiP2pManager.NO_SERVICE_REQUESTS: return "NO_SERVICE_REQUESTS(3)";
|
|
307
|
+
default: return String.valueOf(reason);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
217
311
|
@PluginMethod
|
|
218
312
|
public void getGroupOwnerAddress(PluginCall call) {
|
|
219
313
|
manager.requestConnectionInfo(channel, wifiP2pInfo -> {
|