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
- Log.d(TAG, "Existing Wi-Fi Direct group found. Removing group.");
160
- manager.removeGroup(channel, new WifiP2pManager.ActionListener() {
161
- @Override
162
- public void onSuccess() {
163
- Log.d(TAG, "removeGroup success, proceed to connect.");
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 Called");
267
+ Log.e(TAG, "connect onFailure: " + reasonName(reason));
206
268
  pendingConnectCall = null;
207
- call.reject("Connection failed: " + reason);
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 -> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wifidirectplugin",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "HT-Installer Wifi Direct Plugin",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",