wifidirectplugin 1.2.9 → 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.*;
@@ -27,6 +29,15 @@ public class WifiDirectPlugin extends Plugin {
27
29
  private List<WifiP2pDevice> peerWifiDirDevices = new ArrayList<>();
28
30
  private static final String TAG = "WifiDirectPlugin";
29
31
 
32
+ private PluginCall pendingConnectCall = null;
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
+
30
41
  private final BroadcastReceiver wifiP2pReceiver = new BroadcastReceiver() {
31
42
  @Override
32
43
  public void onReceive(Context context, Intent intent) {
@@ -36,11 +47,23 @@ public class WifiDirectPlugin extends Plugin {
36
47
  NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
37
48
  if (networkInfo != null && networkInfo.isConnected()) {
38
49
  Log.d(TAG, "Wi-Fi Direct connected");
39
- // 필요한 경우 연결된 상태를 Flutter/Ionic에 전달하는 코드를 여기서 실행
40
- // 예: call JavaScript 이벤트 전송 또는 콜백 호출
50
+ if (pendingConnectCall != null) {
51
+ cancelConnectTimeout();
52
+ manager.requestConnectionInfo(channel, info -> {
53
+ if (info != null && info.groupFormed) {
54
+ Log.d(TAG, "Group formed, resolving connectToDevice");
55
+ pendingConnectCall.resolve();
56
+ pendingConnectCall = null;
57
+ }
58
+ });
59
+ }
41
60
  } else {
42
61
  Log.d(TAG, "Wi-Fi Direct disconnected");
43
- // 연결 해제 상태 처리
62
+ if (pendingConnectCall != null) {
63
+ cancelConnectTimeout();
64
+ pendingConnectCall.reject("Wi-Fi Direct connection lost before group formed");
65
+ pendingConnectCall = null;
66
+ }
44
67
  }
45
68
  }
46
69
  }
@@ -143,21 +166,31 @@ public class WifiDirectPlugin extends Plugin {
143
166
 
144
167
  manager.requestConnectionInfo(channel, info -> {
145
168
  if(info != null && info.groupFormed) {
146
- // 기존 그룹 해제
147
- Log.d(TAG, "Existing Wi-Fi Direct group found. Removing group.");
148
- manager.removeGroup(channel, new WifiP2pManager.ActionListener() {
149
- @Override
150
- public void onSuccess() {
151
- Log.d(TAG, "removeGroup success, proceed to connect.");
152
- // 그룹 해제 성공 시 연결 계속 진행
153
- initiateConnect(deviceAddress, pin, call);
154
- }
155
- @Override
156
- public void onFailure(int reason) {
157
- Log.w(TAG, "removeGroup failed: " + reason + ". Proceed anyway.");
158
- // 그룹 해제 실패 시에도 연결 시도(혹은 call.reject로 실패 처리 가능)
159
- 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;
160
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
+ });
161
194
  });
162
195
  } else {
163
196
  Log.d(TAG, "No existing group, proceed to connect directly.");
@@ -165,6 +198,23 @@ public class WifiDirectPlugin extends Plugin {
165
198
  }
166
199
  });
167
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
+
168
218
  private void initiateConnect(String deviceAddress, String pin, PluginCall call) {
169
219
  WifiP2pConfig config = new WifiP2pConfig();
170
220
  config.deviceAddress = deviceAddress;
@@ -178,26 +228,86 @@ public class WifiDirectPlugin extends Plugin {
178
228
  Log.w(TAG, "Invalid Pin");
179
229
  }
180
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) {
181
254
  try {
182
255
  manager.connect(channel, config, new WifiP2pManager.ActionListener() {
183
256
  @Override
184
257
  public void onSuccess() {
185
- Log.d(TAG, "connect onSuccess Called");
186
- call.resolve();
258
+ // connect request accepted — group formation is async
259
+ // resolve will be called from BroadcastReceiver once group is formed
260
+ Log.d(TAG, "connect onSuccess Called, waiting for group formation (timeout " + CONNECT_TIMEOUT_MS + "ms)");
261
+ pendingConnectCall = call;
262
+ scheduleConnectTimeout();
187
263
  }
188
264
 
189
265
  @Override
190
266
  public void onFailure(int reason) {
191
- Log.e(TAG, "connect onFailure Called");
192
- call.reject("Connection failed: " + reason);
267
+ Log.e(TAG, "connect onFailure: " + reasonName(reason));
268
+ pendingConnectCall = null;
269
+ cancelConnectTimeout();
270
+ call.reject("Connection failed: " + reasonName(reason));
193
271
  }
194
272
  });
195
273
  } catch (Exception e) {
196
274
  Log.e(TAG, "connect exception", e);
275
+ pendingConnectCall = null;
276
+ cancelConnectTimeout();
197
277
  call.reject("Connection exception: " + e.getMessage());
198
278
  }
199
279
  }
200
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
+
201
311
  @PluginMethod
202
312
  public void getGroupOwnerAddress(PluginCall call) {
203
313
  manager.requestConnectionInfo(channel, wifiP2pInfo -> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wifidirectplugin",
3
- "version": "1.2.9",
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",