wifidirectplugin 1.3.1 → 1.3.3

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.
@@ -4,6 +4,10 @@ import android.content.BroadcastReceiver;
4
4
  import android.content.Context;
5
5
  import android.content.Intent;
6
6
  import android.content.IntentFilter;
7
+ import android.net.ConnectivityManager;
8
+ import android.net.Network;
9
+ import android.net.NetworkCapabilities;
10
+ import android.net.NetworkRequest;
7
11
  import android.net.wifi.WpsInfo;
8
12
  import android.net.wifi.p2p.*;
9
13
  import android.net.NetworkInfo;
@@ -38,6 +42,14 @@ public class WifiDirectPlugin extends Plugin {
38
42
  // removeGroup 직후 framework가 안정될 때까지 대기 시간
39
43
  private static final long REMOVE_GROUP_SETTLE_MS = 500L;
40
44
 
45
+ // P2P 네트워크에 앱 프로세스를 바인딩해 HTTP 요청을 P2P 인터페이스로 강제하기 위한 상태
46
+ private ConnectivityManager connectivityManager;
47
+ private ConnectivityManager.NetworkCallback p2pNetworkCallback = null;
48
+ private Network boundP2pNetwork = null;
49
+ // NetworkCapabilities.TRANSPORT_WIFI_P2P는 API 31에서 public으로 추가됐다.
50
+ // 그 이전 SDK로 컴파일해도 동작하도록 안정적인 정수 값 5를 직접 사용한다.
51
+ private static final int TRANSPORT_WIFI_P2P = 5;
52
+
41
53
  private final BroadcastReceiver wifiP2pReceiver = new BroadcastReceiver() {
42
54
  @Override
43
55
  public void onReceive(Context context, Intent intent) {
@@ -79,7 +91,7 @@ public class WifiDirectPlugin extends Plugin {
79
91
  Log.e(TAG, "P2P Channel disconnected");
80
92
  }
81
93
  });
82
-
94
+
83
95
  IntentFilter intentFilter = new IntentFilter();
84
96
  intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
85
97
  intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
@@ -87,6 +99,10 @@ public class WifiDirectPlugin extends Plugin {
87
99
  intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
88
100
 
89
101
  context.registerReceiver(wifiP2pReceiver, intentFilter);
102
+
103
+ // P2P 네트워크 가용성을 감시해 onAvailable 시점에 자동으로 프로세스를 바인딩
104
+ connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
105
+ registerP2pNetworkCallback();
90
106
  }
91
107
 
92
108
  public void unload() {
@@ -95,6 +111,7 @@ public class WifiDirectPlugin extends Plugin {
95
111
  } catch (IllegalArgumentException e) {
96
112
  Log.w(TAG, "Receiver not registered or already registered");
97
113
  }
114
+ unregisterP2pNetworkCallback();
98
115
  }
99
116
  @PluginMethod
100
117
  public void scanWifiPeers(PluginCall call) {
@@ -308,6 +325,125 @@ public class WifiDirectPlugin extends Plugin {
308
325
  }
309
326
  }
310
327
 
328
+ // ── P2P 네트워크 프로세스 바인딩 ──────────────────────────────────────────
329
+ // ECU 서버(192.168.X.1)는 P2P 인터페이스에서만 도달 가능하지만, Android의
330
+ // default network는 인터넷이 가능한 일반 Wi-Fi/셀룰러로 잡히기 때문에
331
+ // 앱의 HTTP 요청이 P2P가 아닌 곳으로 빠져 IOException이 발생한다.
332
+ // P2P 트랜스포트 네트워크 가용 시점에 명시적으로 프로세스를 바인딩한다.
333
+ private void registerP2pNetworkCallback() {
334
+ if (connectivityManager == null) return;
335
+ if (p2pNetworkCallback != null) return;
336
+
337
+ NetworkRequest req = new NetworkRequest.Builder()
338
+ .addTransportType(TRANSPORT_WIFI_P2P)
339
+ // P2P는 인터넷 capability가 없으므로 매칭을 위해 제거
340
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
341
+ .build();
342
+
343
+ p2pNetworkCallback = new ConnectivityManager.NetworkCallback() {
344
+ @Override
345
+ public void onAvailable(Network network) {
346
+ Log.d(TAG, "P2P network available, binding process to it");
347
+ boundP2pNetwork = network;
348
+ try {
349
+ connectivityManager.bindProcessToNetwork(network);
350
+ } catch (Exception e) {
351
+ Log.e(TAG, "bindProcessToNetwork failed", e);
352
+ }
353
+ }
354
+
355
+ @Override
356
+ public void onLost(Network network) {
357
+ Log.d(TAG, "P2P network lost: " + network);
358
+ if (network.equals(boundP2pNetwork)) {
359
+ try {
360
+ connectivityManager.bindProcessToNetwork(null);
361
+ } catch (Exception e) {
362
+ Log.w(TAG, "bindProcessToNetwork(null) failed", e);
363
+ }
364
+ boundP2pNetwork = null;
365
+ }
366
+ }
367
+ };
368
+
369
+ try {
370
+ connectivityManager.registerNetworkCallback(req, p2pNetworkCallback);
371
+ Log.d(TAG, "P2P NetworkCallback registered");
372
+ } catch (Exception e) {
373
+ Log.e(TAG, "registerNetworkCallback failed", e);
374
+ p2pNetworkCallback = null;
375
+ }
376
+ }
377
+
378
+ private void unregisterP2pNetworkCallback() {
379
+ if (connectivityManager == null) return;
380
+ if (p2pNetworkCallback != null) {
381
+ try {
382
+ connectivityManager.unregisterNetworkCallback(p2pNetworkCallback);
383
+ } catch (IllegalArgumentException e) {
384
+ Log.w(TAG, "P2P NetworkCallback already unregistered");
385
+ }
386
+ p2pNetworkCallback = null;
387
+ }
388
+ if (boundP2pNetwork != null) {
389
+ try {
390
+ connectivityManager.bindProcessToNetwork(null);
391
+ } catch (Exception ignored) {}
392
+ boundP2pNetwork = null;
393
+ }
394
+ }
395
+
396
+ // JS에서 강제로 인터넷 사용이 필요한 페이지로 갈 때 호출
397
+ // (예: 백엔드 API 호출 직전). 호출 후 P2P 그룹이 다시 형성되거나
398
+ // bindToP2p() 가 호출되면 다시 바인딩된다.
399
+ @PluginMethod
400
+ public void unbindFromP2p(PluginCall call) {
401
+ if (connectivityManager == null) {
402
+ call.reject("ConnectivityManager not initialized");
403
+ return;
404
+ }
405
+ try {
406
+ connectivityManager.bindProcessToNetwork(null);
407
+ boundP2pNetwork = null;
408
+ Log.d(TAG, "Process unbound from P2P network");
409
+ JSObject ret = new JSObject();
410
+ ret.put("unbound", true);
411
+ call.resolve(ret);
412
+ } catch (Exception e) {
413
+ call.reject("unbindFromP2p failed: " + e.getMessage());
414
+ }
415
+ }
416
+
417
+ // JS에서 명시적으로 다시 P2P에 바인딩해야 할 때 호출.
418
+ // 일반적으로는 NetworkCallback이 자동 처리하므로 필요 없지만, 콜백이
419
+ // 늦거나 누락된 환경을 위해 제공.
420
+ @PluginMethod
421
+ public void bindToP2p(PluginCall call) {
422
+ if (connectivityManager == null) {
423
+ call.reject("ConnectivityManager not initialized");
424
+ return;
425
+ }
426
+ Network[] networks = connectivityManager.getAllNetworks();
427
+ for (Network n : networks) {
428
+ NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(n);
429
+ if (caps != null && caps.hasTransport(TRANSPORT_WIFI_P2P)) {
430
+ try {
431
+ connectivityManager.bindProcessToNetwork(n);
432
+ boundP2pNetwork = n;
433
+ Log.d(TAG, "Process bound to P2P network (manual)");
434
+ JSObject ret = new JSObject();
435
+ ret.put("bound", true);
436
+ call.resolve(ret);
437
+ return;
438
+ } catch (Exception e) {
439
+ call.reject("bindProcessToNetwork failed: " + e.getMessage());
440
+ return;
441
+ }
442
+ }
443
+ }
444
+ call.reject("No P2P network available to bind");
445
+ }
446
+
311
447
  @PluginMethod
312
448
  public void getGroupOwnerAddress(PluginCall call) {
313
449
  manager.requestConnectionInfo(channel, wifiP2pInfo -> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wifidirectplugin",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "HT-Installer Wifi Direct Plugin",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",