rnww-plugin-wifi 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/README.md +221 -693
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # RNWW Plugin Background
1
+ # RNWW Plugin WiFi
2
2
 
3
- React Native WebView 백그라운드 실행 제어 플러그인
3
+ React Native WebView WiFi 정보 조회 및 연결 관리 플러그인
4
4
 
5
5
  ## 설치
6
6
 
7
7
  ```bash
8
- npm install rnww-plugin-background
8
+ npm install rnww-plugin-wifi
9
9
  ```
10
10
 
11
11
  ## 빠른 시작
12
12
 
13
13
  ```typescript
14
- import { registerBackgroundHandlers } from 'rnww-plugin-background';
14
+ import { registerWifiHandlers } from 'rnww-plugin-wifi';
15
15
 
16
- registerBackgroundHandlers({
16
+ registerWifiHandlers({
17
17
  bridge: yourBridgeImplementation,
18
18
  platform: { OS: Platform.OS },
19
19
  });
@@ -23,815 +23,343 @@ registerBackgroundHandlers({
23
23
 
24
24
  ## Bridge Handlers
25
25
 
26
- ### registerTask
26
+ ### getCurrentWifiInfo
27
27
 
28
- 백그라운드 작업을 등록합니다.
28
+ 현재 연결된 WiFi 정보를 조회합니다.
29
29
 
30
30
  ```typescript
31
- bridge.call('registerTask', {
32
- taskId: 'sync-task',
33
- mode: 'persistent',
34
- interval: 60000,
35
- triggers: ['network_change', 'battery_low'],
36
- callbackId: 'my-callback',
37
- callback: (event) => {
38
- console.log('Task event:', event);
39
- },
40
- notification: {
41
- title: '백그라운드 실행 중',
42
- body: '동기화 진행 중...',
43
- color: '#4CAF50',
44
- priority: 'high',
45
- ongoing: true,
46
- progress: { current: 0, max: 100 },
47
- actions: [
48
- {
49
- id: 'pause',
50
- title: '일시정지',
51
- onPress: (actionId, taskId) => {
52
- console.log(`Action ${actionId} clicked for task ${taskId}`);
53
- }
54
- }
55
- ]
56
- }
57
- });
31
+ const result = await bridge.call('getCurrentWifiInfo');
32
+ // {
33
+ // success: true,
34
+ // data: {
35
+ // ssid: 'MyWiFi',
36
+ // bssid: 'AA:BB:CC:DD:EE:FF',
37
+ // rssi: -45,
38
+ // signalLevel: 80,
39
+ // frequency: 5180,
40
+ // linkSpeed: 433,
41
+ // ipAddress: '192.168.1.100',
42
+ // isConnected: true,
43
+ // networkId: 1,
44
+ // security: 'WPA2'
45
+ // }
46
+ // }
58
47
  ```
59
48
 
60
- ### startTask / stopTask
49
+ ### getWifiList
61
50
 
62
- 작업을 시작하거나 중지합니다.
51
+ 사용 가능한 WiFi 네트워크 목록을 스캔합니다. (Android only)
63
52
 
64
53
  ```typescript
65
- bridge.call('startTask', { taskId: 'sync-task' });
66
- bridge.call('stopTask', { taskId: 'sync-task' });
67
- bridge.call('stopAllTasks');
54
+ const result = await bridge.call('getWifiList');
55
+ // {
56
+ // success: true,
57
+ // data: [
58
+ // {
59
+ // ssid: 'MyWiFi',
60
+ // bssid: 'AA:BB:CC:DD:EE:FF',
61
+ // rssi: -45,
62
+ // signalLevel: 80,
63
+ // frequency: 5180,
64
+ // security: 'WPA2',
65
+ // channel: 36
66
+ // },
67
+ // ...
68
+ // ]
69
+ // }
68
70
  ```
69
71
 
70
- ### unregisterTask
72
+ ### isWifiEnabled
71
73
 
72
- 등록된 작업을 해제합니다.
74
+ WiFi 활성화 상태를 확인합니다.
73
75
 
74
76
  ```typescript
75
- bridge.call('unregisterTask', { taskId: 'sync-task' });
77
+ const result = await bridge.call('isWifiEnabled');
78
+ // {
79
+ // success: true,
80
+ // isEnabled: true,
81
+ // wifiState: 'ENABLED'
82
+ // }
76
83
  ```
77
84
 
78
- ### updateNotification
85
+ ### connectToWifi
79
86
 
80
- 알림 내용을 동적으로 업데이트합니다.
87
+ WiFi 네트워크에 연결합니다.
81
88
 
82
89
  ```typescript
83
- bridge.call('updateNotification', {
84
- taskId: 'sync-task',
85
- title: '동기화 중',
86
- body: '50% 완료',
87
- progress: { current: 50, max: 100 },
88
- actions: [
89
- {
90
- id: 'cancel',
91
- title: '취소',
92
- onPress: (actionId, taskId) => {
93
- bridge.call('stopTask', { taskId });
94
- }
95
- }
96
- ]
90
+ const result = await bridge.call('connectToWifi', {
91
+ ssid: 'MyWiFi',
92
+ password: 'mypassword',
93
+ isHidden: false
97
94
  });
95
+ // {
96
+ // success: true,
97
+ // wifiInfo: { ssid: 'MyWiFi', ... }
98
+ // }
98
99
  ```
99
100
 
100
- ### getTaskStatus / getAllTasksStatus
101
+ ### disconnect
101
102
 
102
- 작업 상태를 조회합니다.
103
+ 현재 WiFi 연결을 해제합니다.
103
104
 
104
105
  ```typescript
105
- const status = await bridge.call('getTaskStatus', { taskId: 'sync-task' });
106
- const allStatus = await bridge.call('getAllTasksStatus');
106
+ const result = await bridge.call('disconnect');
107
+ // { success: true }
107
108
  ```
108
109
 
109
- ### checkBackgroundPermission / requestBackgroundPermission
110
+ ### checkWifiPermission
110
111
 
111
- 백그라운드 권한을 확인하고 요청합니다.
112
+ WiFi 관련 권한 상태를 확인합니다.
112
113
 
113
114
  ```typescript
114
- const permission = await bridge.call('checkBackgroundPermission');
115
- if (!permission.canRunBackground) {
116
- await bridge.call('requestBackgroundPermission');
117
- }
115
+ const result = await bridge.call('checkWifiPermission');
116
+ // {
117
+ // locationGranted: true,
118
+ // canAccessWifiInfo: true,
119
+ // requiredPermissions: [],
120
+ // details: {
121
+ // fineLocation: true,
122
+ // coarseLocation: true
123
+ // }
124
+ // }
118
125
  ```
119
126
 
120
- ### disposeBackgroundHandlers
127
+ ### requestWifiPermission
121
128
 
122
- 브릿지 핸들러와 리소스를 정리합니다.
129
+ WiFi 관련 권한을 요청합니다.
123
130
 
124
131
  ```typescript
125
- bridge.call('disposeBackgroundHandlers');
132
+ const result = await bridge.call('requestWifiPermission');
133
+ // {
134
+ // locationGranted: true,
135
+ // canAccessWifiInfo: true,
136
+ // requiredPermissions: []
137
+ // }
126
138
  ```
127
139
 
128
140
  ---
129
141
 
130
- ## 콜백 시스템
131
-
132
- ### Task Callback
133
-
134
- 작업 등록 시 `callback` 함수를 지정하면 해당 작업의 모든 이벤트를 수신합니다.
135
-
136
- ```typescript
137
- bridge.call('registerTask', {
138
- taskId: 'my-task',
139
- mode: 'persistent',
140
- callback: (event) => {
141
- switch (event.type) {
142
- case 'started':
143
- console.log('작업 시작됨');
144
- break;
145
- case 'stopped':
146
- console.log('작업 중지됨');
147
- break;
148
- case 'trigger':
149
- console.log(`트리거 발생: ${event.trigger}`, event.data);
150
- break;
151
- case 'action':
152
- console.log(`액션 클릭: ${event.actionId}`);
153
- break;
154
- case 'error':
155
- console.error('에러 발생:', event.error);
156
- break;
157
- }
158
- },
159
- notification: { title: 'Task', body: 'Running...' }
160
- });
161
- ```
162
-
163
- ### Action Callback
164
-
165
- 각 알림 액션 버튼에 `onPress` 콜백을 개별 지정할 수 있습니다.
166
-
167
- ```typescript
168
- bridge.call('registerTask', {
169
- taskId: 'download-task',
170
- mode: 'persistent',
171
- notification: {
172
- title: '다운로드 중',
173
- body: '파일 다운로드...',
174
- actions: [
175
- {
176
- id: 'pause',
177
- title: '일시정지',
178
- icon: 'ic_pause',
179
- dismissOnPress: false,
180
- onPress: async (actionId, taskId) => {
181
- await pauseDownload();
182
- bridge.call('updateNotification', {
183
- taskId,
184
- title: '일시정지됨',
185
- body: '다운로드가 일시정지되었습니다'
186
- });
187
- }
188
- },
189
- {
190
- id: 'cancel',
191
- title: '취소',
192
- dismissOnPress: true,
193
- bringToForeground: false,
194
- onPress: async (actionId, taskId) => {
195
- await cancelDownload();
196
- bridge.call('stopTask', { taskId });
197
- }
198
- }
199
- ]
200
- }
201
- });
202
- ```
203
-
204
- ### Callback ID
205
-
206
- `callbackId`를 지정하면 이벤트 수신 시 해당 ID가 함께 전달되어 여러 작업의 이벤트를 구분할 수 있습니다.
207
-
208
- ```typescript
209
- // 작업 등록
210
- bridge.call('registerTask', {
211
- taskId: 'task-1',
212
- callbackId: 'sync-callback',
213
- // ...
214
- });
215
-
216
- bridge.call('registerTask', {
217
- taskId: 'task-2',
218
- callbackId: 'upload-callback',
219
- // ...
220
- });
221
-
222
- // 이벤트 수신
223
- bridge.on('onTaskEvent', (event) => {
224
- if (event.callbackId === 'sync-callback') {
225
- // task-1의 이벤트 처리
226
- } else if (event.callbackId === 'upload-callback') {
227
- // task-2의 이벤트 처리
228
- }
229
- });
230
- ```
231
-
232
- ---
233
-
234
- ## 트리거 시스템
235
-
236
- ### 트리거 종류
237
-
238
- | 트리거 | 설명 |
239
- |--------|------|
240
- | `interval` | 주기적 실행 (interval 옵션 사용) |
241
- | `network_change` | 네트워크 상태 변경 (연결/해제) |
242
- | `location_change` | 위치 변경 (significant location change) |
243
- | `time_trigger` | 예약된 시간에 실행 |
244
- | `battery_low` | 배터리 부족 (기본 15% 이하) |
245
- | `battery_okay` | 배터리 정상 복귀 |
246
- | `battery_charging` | 충전 시작 |
247
- | `battery_discharging` | 충전 해제 |
248
- | `app_foreground` | 앱이 포그라운드로 전환 |
249
- | `app_background` | 앱이 백그라운드로 전환 |
250
- | `app_terminate` | 앱 종료 시 |
251
- | `custom` | 사용자 정의 트리거 |
252
-
253
- ### 간단한 사용법
254
-
255
- 문자열로 트리거 타입만 지정:
256
-
257
- ```typescript
258
- bridge.call('registerTask', {
259
- taskId: 'my-task',
260
- mode: 'persistent',
261
- triggers: ['network_change', 'battery_low', 'app_background'],
262
- // ...
263
- });
264
- ```
265
-
266
- ### 상세 설정
267
-
268
- 객체로 트리거별 옵션 지정:
269
-
270
- ```typescript
271
- bridge.call('registerTask', {
272
- taskId: 'my-task',
273
- mode: 'persistent',
274
- triggers: [
275
- // 배터리 30% 이하일 때 트리거
276
- {
277
- type: 'battery_low',
278
- options: { threshold: 30 }
279
- },
280
- // WiFi 연결 변경만 감지
281
- {
282
- type: 'network_change',
283
- options: { networkTypes: ['wifi'] }
284
- },
285
- // 100m 이상 이동 시 트리거
286
- {
287
- type: 'location_change',
288
- options: { minDistance: 100 }
289
- },
290
- // 사용자 정의 트리거
291
- {
292
- type: 'custom',
293
- customId: 'my-custom-trigger'
294
- }
295
- ],
296
- callback: (event) => {
297
- if (event.type === 'trigger') {
298
- switch (event.trigger) {
299
- case 'battery_low':
300
- console.log('배터리 레벨:', event.data?.batteryLevel);
301
- break;
302
- case 'network_change':
303
- console.log('네트워크:', event.data?.networkType, event.data?.isConnected);
304
- break;
305
- case 'location_change':
306
- console.log('위치:', event.data?.location);
307
- break;
308
- case 'custom':
309
- console.log('커스텀 트리거:', event.customTriggerId);
310
- break;
311
- }
312
- }
313
- },
314
- // ...
315
- });
316
- ```
317
-
318
- ### 트리거 옵션 상세
319
-
320
- #### battery_low / battery_okay
321
-
322
- ```typescript
323
- {
324
- type: 'battery_low',
325
- options: {
326
- threshold: 20 // 배터리 임계값 % (기본: 15)
327
- }
328
- }
329
- ```
330
-
331
- 이벤트 데이터:
332
- ```typescript
333
- event.data?.batteryLevel // 현재 배터리 레벨 (%)
334
- ```
335
-
336
- #### network_change
337
-
338
- ```typescript
339
- {
340
- type: 'network_change',
341
- options: {
342
- networkTypes: ['wifi', 'cellular'] // 감지할 네트워크 타입
343
- }
344
- }
345
- ```
346
-
347
- 이벤트 데이터:
348
- ```typescript
349
- event.data?.networkType // 'wifi' | 'cellular' | 'ethernet' | 'none'
350
- event.data?.isConnected // 연결 상태 (boolean)
351
- ```
352
-
353
- #### location_change
354
-
355
- ```typescript
356
- {
357
- type: 'location_change',
358
- options: {
359
- minDistance: 50 // 최소 이동 거리 (미터)
360
- }
361
- }
362
- ```
363
-
364
- 이벤트 데이터:
365
- ```typescript
366
- event.data?.location // { latitude: number, longitude: number }
367
- ```
142
+ ## 이벤트
368
143
 
369
- #### time_trigger
144
+ ### onWifiStateChange
370
145
 
371
- 예약 시간에 트리거. `scheduledTime` 필드와 함께 사용:
146
+ WiFi 상태 변경 이벤트를 수신합니다.
372
147
 
373
148
  ```typescript
374
- bridge.call('registerTask', {
375
- taskId: 'scheduled-task',
376
- mode: 'efficient',
377
- triggers: ['time_trigger'],
378
- scheduledTime: Date.now() + 3600000, // 1시간 후
379
- // ...
149
+ bridge.on('onWifiStateChange', (event) => {
150
+ console.log('WiFi state changed:', event);
380
151
  });
381
152
  ```
382
153
 
383
- #### custom
384
-
385
- 사용자 정의 트리거. 네이티브 측에서 직접 발생시킬 수 있음:
154
+ #### WifiStateChangeEvent 구조
386
155
 
387
156
  ```typescript
388
- {
389
- type: 'custom',
390
- customId: 'my-sync-trigger' // 고유 식별자
157
+ interface WifiStateChangeEvent {
158
+ type: 'WIFI_STATE_CHANGED' | 'CONNECTION_STATE_CHANGED' | 'NETWORK_INFO_CHANGED';
159
+ wifiState?: 'DISABLED' | 'DISABLING' | 'ENABLED' | 'ENABLING' | 'UNKNOWN';
160
+ connectionState?: 'DISCONNECTED' | 'CONNECTING' | 'CONNECTED' | 'DISCONNECTING' | 'UNKNOWN';
161
+ wifiInfo?: WifiInfo;
162
+ timestamp: number;
391
163
  }
392
164
  ```
393
165
 
394
- 이벤트에서 `event.customTriggerId`로 식별 가능.
395
-
396
166
  ---
397
167
 
398
- ## 알림 설정
168
+ ## 타입 정의
399
169
 
400
- ### 기본 알림
170
+ ### WifiInfo
401
171
 
402
172
  ```typescript
403
- notification: {
404
- title: '백그라운드 작업',
405
- body: '작업이 실행 중입니다',
406
- icon: 'ic_notification', // Android drawable 리소스명
173
+ interface WifiInfo {
174
+ ssid: string | null;
175
+ bssid: string | null;
176
+ rssi: number | null; // 신호 강도 (dBm)
177
+ signalLevel: number | null; // 신호 레벨 (0-100)
178
+ frequency: number | null; // 주파수 (MHz)
179
+ linkSpeed: number | null; // 링크 속도 (Mbps)
180
+ ipAddress: string | null;
181
+ isConnected: boolean;
182
+ networkId?: number;
183
+ security?: WifiSecurityType;
407
184
  }
408
185
  ```
409
186
 
410
- ### 스타일 옵션
187
+ ### WifiNetwork
411
188
 
412
189
  ```typescript
413
- notification: {
414
- title: '동기화',
415
- body: '데이터 동기화 중...',
416
-
417
- // 아이콘/강조 색상 (hex)
418
- color: '#4CAF50',
419
-
420
- // 우선순위
421
- // 'min': 최소 (무음, 상태바만)
422
- // 'low': 낮음 (무음)
423
- // 'default': 기본
424
- // 'high': 높음 (헤드업 알림)
425
- // 'max': 최대 (긴급)
426
- priority: 'high',
427
-
428
- // 지속 알림 (사용자가 스와이프로 닫을 수 없음)
429
- // persistent 모드에서는 항상 true
430
- ongoing: true,
190
+ interface WifiNetwork {
191
+ ssid: string;
192
+ bssid: string;
193
+ rssi: number;
194
+ signalLevel: number;
195
+ frequency: number;
196
+ security: WifiSecurityType;
197
+ channel?: number;
431
198
  }
432
199
  ```
433
200
 
434
- ### 진행 상태바
201
+ ### WifiSecurityType
435
202
 
436
203
  ```typescript
437
- notification: {
438
- title: '다운로드 중',
439
- body: '50% 완료',
440
- progress: {
441
- current: 50,
442
- max: 100,
443
- indeterminate: false // true면 무한 진행 표시
444
- }
445
- }
204
+ type WifiSecurityType =
205
+ | 'OPEN'
206
+ | 'WEP'
207
+ | 'WPA'
208
+ | 'WPA2'
209
+ | 'WPA3'
210
+ | 'WPA_WPA2'
211
+ | 'WPA2_WPA3'
212
+ | 'UNKNOWN';
446
213
  ```
447
214
 
448
- 무한 진행 표시 (로딩):
215
+ ### ConnectOptions
449
216
 
450
217
  ```typescript
451
- progress: {
452
- current: 0,
453
- max: 100,
454
- indeterminate: true
218
+ interface ConnectOptions {
219
+ ssid: string;
220
+ password?: string;
221
+ security?: WifiSecurityType;
222
+ isHidden?: boolean;
223
+ timeout?: number;
455
224
  }
456
225
  ```
457
226
 
458
- ### 액션 버튼
459
-
460
- 최대 3개까지 지원:
227
+ ### PermissionStatus
461
228
 
462
229
  ```typescript
463
- notification: {
464
- title: '음악 재생 중',
465
- body: 'Now Playing...',
466
- actions: [
467
- {
468
- id: 'prev',
469
- title: '이전',
470
- icon: 'ic_prev', // Android drawable (선택)
471
- dismissOnPress: false, // 클릭 시 알림 유지
472
- bringToForeground: false, // 앱을 포그라운드로 가져오지 않음
473
- onPress: (actionId, taskId) => {
474
- playPrevious();
475
- }
476
- },
477
- {
478
- id: 'pause',
479
- title: '일시정지',
480
- icon: 'ic_pause',
481
- onPress: (actionId, taskId) => {
482
- togglePlayPause();
483
- }
484
- },
485
- {
486
- id: 'next',
487
- title: '다음',
488
- icon: 'ic_next',
489
- onPress: (actionId, taskId) => {
490
- playNext();
491
- }
492
- }
493
- ]
230
+ interface PermissionStatus {
231
+ locationGranted: boolean;
232
+ canAccessWifiInfo: boolean;
233
+ requiredPermissions: string[];
234
+ details?: {
235
+ fineLocation?: boolean;
236
+ coarseLocation?: boolean;
237
+ backgroundLocation?: boolean;
238
+ };
494
239
  }
495
240
  ```
496
241
 
497
- ### 채널 설정 (Android 8.0+)
242
+ ### WifiErrorCode
498
243
 
499
244
  ```typescript
500
- notification: {
501
- title: '알림',
502
- body: '내용',
503
- channelId: 'sync_channel',
504
- channelName: '동기화 알림',
505
- channelDescription: '백그라운드 동기화 알림을 표시합니다'
506
- }
245
+ type WifiErrorCode =
246
+ | 'PERMISSION_DENIED'
247
+ | 'WIFI_DISABLED'
248
+ | 'NETWORK_NOT_FOUND'
249
+ | 'AUTHENTICATION_FAILED'
250
+ | 'CONNECTION_FAILED'
251
+ | 'TIMEOUT'
252
+ | 'INVALID_SSID'
253
+ | 'INVALID_PASSWORD'
254
+ | 'NOT_SUPPORTED'
255
+ | 'MODULE_NOT_AVAILABLE'
256
+ | 'UNKNOWN';
507
257
  ```
508
258
 
509
259
  ---
510
260
 
511
- ## 실행 모드
261
+ ## 권한 설정
512
262
 
513
- ### persistent 모드
263
+ ### Android
514
264
 
515
- 포그라운드 서비스로 항상 실행됩니다. 알림이 필수입니다.
265
+ `AndroidManifest.xml`에 자동 추가:
516
266
 
517
- ```typescript
518
- bridge.call('registerTask', {
519
- taskId: 'always-on',
520
- mode: 'persistent',
521
- interval: 10000, // 최소 1초 (1000ms)
522
- notification: { // 필수
523
- title: '실행 중',
524
- body: '백그라운드 서비스 동작 중'
525
- }
526
- });
267
+ ```xml
268
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
269
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
270
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
271
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
272
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
527
273
  ```
528
274
 
529
- **특징:**
530
- - 시스템에 의해 종료되지 않음 (높은 우선순위)
531
- - 항상 알림 표시 (ongoing: true 강제)
532
- - interval 최소값: 1000ms (1초)
533
- - 배터리 사용량 높음
275
+ > **Note:** Android 8.0 이상에서 WiFi SSID를 가져오려면 위치 권한이 필요합니다.
534
276
 
535
- ### efficient 모드
277
+ ### iOS
536
278
 
537
- 시스템이 관리하는 효율적 실행입니다. (WorkManager/BGTaskScheduler)
279
+ `Info.plist`에 추가:
538
280
 
539
- ```typescript
540
- bridge.call('registerTask', {
541
- taskId: 'periodic-sync',
542
- mode: 'efficient',
543
- interval: 900000, // 최소 15분 (900000ms)
544
- triggers: ['network_change'],
545
- notification: { // 선택
546
- title: '동기화',
547
- body: '대기 중...'
548
- }
549
- });
281
+ ```xml
282
+ <key>NSLocationWhenInUseUsageDescription</key>
283
+ <string>WiFi 정보를 가져오기 위해 위치 권한이 필요합니다.</string>
550
284
  ```
551
285
 
552
- **특징:**
553
- - 시스템이 배터리/리소스에 따라 실행 시점 조정
554
- - interval 최소값: 900000ms (15분, 시스템 제한)
555
- - 정확한 타이밍 보장 안됨
556
- - 배터리 효율적
286
+ Xcode에서 **Signing & Capabilities**에 다음 추가:
287
+ - **Access WiFi Information** capability
557
288
 
558
289
  ---
559
290
 
560
- ## 이벤트
291
+ ## 플랫폼별 제한사항
561
292
 
562
- ### onTaskEvent
293
+ ### Android
563
294
 
564
- 모든 작업 이벤트를 수신합니다.
295
+ - WiFi 스캔 (`getWifiList`)은 Android에서만 지원됩니다.
296
+ - Android 10 이상에서는 WiFi 연결 시 시스템 UI가 표시됩니다.
297
+ - Android 10 미만에서는 레거시 방식으로 연결됩니다.
565
298
 
566
- ```typescript
567
- bridge.on('onTaskEvent', (event) => {
568
- console.log('Event:', event);
569
- });
570
- ```
299
+ ### iOS
571
300
 
572
- ### TaskEvent 구조
573
-
574
- ```typescript
575
- interface TaskEvent {
576
- taskId: string; // 작업 ID
577
- callbackId?: string; // 등록 시 지정한 콜백 ID
578
- type: 'started' | 'stopped' | 'restart' | 'error' | 'trigger' | 'action';
579
- trigger?: TriggerType; // 트리거 종류 (type이 'trigger'일 때)
580
- customTriggerId?: string; // custom 트리거 식별자
581
- actionId?: string; // 액션 버튼 ID (type이 'action'일 때)
582
- error?: string; // 에러 메시지 (type이 'error'일 때)
583
- data?: { // 트리거 관련 데이터
584
- batteryLevel?: number;
585
- networkType?: 'wifi' | 'cellular' | 'ethernet' | 'none';
586
- isConnected?: boolean;
587
- location?: { latitude: number; longitude: number };
588
- [key: string]: unknown;
589
- };
590
- timestamp: number; // 타임스탬프
591
- }
592
- ```
301
+ - WiFi 스캔 (`getWifiList`)은 iOS에서 지원되지 않습니다.
302
+ - WiFi 연결은 iOS 11 이상에서만 지원됩니다.
303
+ - RSSI, frequency, linkSpeed 등 일부 정보는 iOS에서 제공되지 않습니다.
304
+ - WiFi 정보 접근을 위해 **Access WiFi Information** entitlement가 필요합니다.
593
305
 
594
306
  ---
595
307
 
596
- ## 타입 정의
308
+ ## 예제
597
309
 
598
- ### BackgroundTask
310
+ ### WiFi 정보 표시
599
311
 
600
312
  ```typescript
601
- interface BackgroundTask {
602
- taskId: string;
603
- mode: 'persistent' | 'efficient';
604
- interval?: number;
605
- triggers?: TriggerConfig[];
606
- scheduledTime?: number;
607
- callbackId?: string;
608
- callback?: (event: TaskEvent) => void | Promise<void>;
609
- notification?: NotificationConfig;
610
- }
611
- ```
612
-
613
- ### TriggerConfig
614
-
615
- ```typescript
616
- type TriggerType =
617
- | 'interval'
618
- | 'network_change'
619
- | 'location_change'
620
- | 'time_trigger'
621
- | 'battery_low'
622
- | 'battery_okay'
623
- | 'battery_charging'
624
- | 'battery_discharging'
625
- | 'app_foreground'
626
- | 'app_background'
627
- | 'app_terminate'
628
- | 'custom';
629
-
630
- type TriggerConfig = TriggerType | {
631
- type: TriggerType;
632
- customId?: string;
633
- options?: {
634
- threshold?: number;
635
- minDistance?: number;
636
- networkTypes?: Array<'wifi' | 'cellular' | 'ethernet'>;
637
- };
638
- };
639
- ```
640
-
641
- ### NotificationConfig
642
-
643
- ```typescript
644
- interface NotificationConfig {
645
- taskId?: string;
646
- title: string;
647
- body: string;
648
- icon?: string;
649
- color?: string;
650
- priority?: 'min' | 'low' | 'default' | 'high' | 'max';
651
- ongoing?: boolean;
652
- progress?: {
653
- current: number;
654
- max: number;
655
- indeterminate?: boolean;
656
- };
657
- actions?: NotificationAction[];
658
- channelId?: string;
659
- channelName?: string;
660
- channelDescription?: string;
661
- }
662
- ```
663
-
664
- ### NotificationAction
313
+ async function showWifiInfo() {
314
+ // 권한 확인
315
+ const permission = await bridge.call('checkWifiPermission');
316
+ if (!permission.canAccessWifiInfo) {
317
+ await bridge.call('requestWifiPermission');
318
+ }
665
319
 
666
- ```typescript
667
- interface NotificationAction {
668
- id: string;
669
- title: string;
670
- icon?: string;
671
- onPress?: (actionId: string, taskId: string) => void | Promise<void>;
672
- dismissOnPress?: boolean; // 기본: true
673
- bringToForeground?: boolean; // 기본: false
320
+ // WiFi 정보 조회
321
+ const result = await bridge.call('getCurrentWifiInfo');
322
+ if (result.success && result.data) {
323
+ console.log(`Connected to: ${result.data.ssid}`);
324
+ console.log(`Signal: ${result.data.signalLevel}%`);
325
+ console.log(`IP: ${result.data.ipAddress}`);
326
+ }
674
327
  }
675
328
  ```
676
329
 
677
- ### BackgroundError
330
+ ### WiFi 연결
678
331
 
679
332
  ```typescript
680
- type BackgroundError =
681
- | 'TASK_NOT_FOUND'
682
- | 'TASK_ALREADY_EXISTS'
683
- | 'TASK_ALREADY_RUNNING'
684
- | 'TASK_NOT_RUNNING'
685
- | 'PERMISSION_DENIED'
686
- | 'SYSTEM_RESTRICTED'
687
- | 'WEBVIEW_INIT_FAILED'
688
- | 'INVALID_INPUT'
689
- | 'INVALID_INTERVAL'
690
- | 'INVALID_TRIGGER'
691
- | 'NOTIFICATION_REQUIRED'
692
- | 'UNKNOWN';
693
- ```
694
-
695
- ---
696
-
697
- ## 권한 설정
698
-
699
- ### Android
700
-
701
- `AndroidManifest.xml`에 자동 추가:
702
-
703
- ```xml
704
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
705
- <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
706
- ```
707
-
708
- ### iOS
709
-
710
- `Info.plist`에 추가:
711
-
712
- ```xml
713
- <key>UIBackgroundModes</key>
714
- <array>
715
- <string>fetch</string>
716
- <string>processing</string>
717
- </array>
718
-
719
- <key>BGTaskSchedulerPermittedIdentifiers</key>
720
- <array>
721
- <string>$(PRODUCT_BUNDLE_IDENTIFIER).background</string>
722
- </array>
723
- ```
724
-
725
- ---
726
-
727
- ## 예제: 음악 플레이어
333
+ async function connectWifi(ssid: string, password: string) {
334
+ const result = await bridge.call('connectToWifi', {
335
+ ssid,
336
+ password
337
+ });
728
338
 
729
- ```typescript
730
- // 음악 재생 백그라운드 서비스
731
- bridge.call('registerTask', {
732
- taskId: 'music-player',
733
- mode: 'persistent',
734
- triggers: [
735
- 'app_background',
736
- { type: 'battery_low', options: { threshold: 10 } }
737
- ],
738
- callback: (event) => {
739
- if (event.type === 'trigger' && event.trigger === 'battery_low') {
740
- // 배터리 부족 시 품질 낮춤
741
- setStreamQuality('low');
742
- }
743
- },
744
- notification: {
745
- title: 'Now Playing',
746
- body: 'Artist - Song Title',
747
- color: '#1DB954',
748
- ongoing: true,
749
- actions: [
750
- {
751
- id: 'prev',
752
- title: '이전',
753
- icon: 'ic_skip_previous',
754
- dismissOnPress: false,
755
- onPress: () => skipToPrevious()
756
- },
757
- {
758
- id: 'play_pause',
759
- title: '재생/일시정지',
760
- icon: 'ic_play_pause',
761
- dismissOnPress: false,
762
- onPress: () => togglePlayPause()
763
- },
764
- {
765
- id: 'next',
766
- title: '다음',
767
- icon: 'ic_skip_next',
768
- dismissOnPress: false,
769
- onPress: () => skipToNext()
770
- }
771
- ]
339
+ if (result.success) {
340
+ console.log('Connected successfully!');
341
+ } else {
342
+ console.error(`Connection failed: ${result.error}`);
772
343
  }
773
- });
774
-
775
- // 트랙 변경 시 알림 업데이트
776
- function onTrackChange(track) {
777
- bridge.call('updateNotification', {
778
- taskId: 'music-player',
779
- title: track.title,
780
- body: `${track.artist} - ${track.album}`,
781
- });
782
344
  }
783
345
  ```
784
346
 
785
- ## 예제: 파일 동기화
347
+ ### 상태 변경 모니터링
786
348
 
787
349
  ```typescript
788
- // 효율적 주기 동기화
789
- bridge.call('registerTask', {
790
- taskId: 'file-sync',
791
- mode: 'efficient',
792
- interval: 1800000, // 30분
793
- triggers: [
794
- { type: 'network_change', options: { networkTypes: ['wifi'] } },
795
- 'battery_charging'
796
- ],
797
- callback: async (event) => {
798
- if (event.type === 'trigger') {
799
- // WiFi 연결되거나 충전 시작 시 동기화
800
- await syncFiles();
801
- }
802
- },
803
- notification: {
804
- title: '동기화 대기 중',
805
- body: '다음 동기화 예약됨',
806
- priority: 'low'
807
- }
808
- });
809
-
810
- // 동기화 진행 시 알림 업데이트
811
- async function syncFiles() {
812
- const files = await getFilesToSync();
813
-
814
- for (let i = 0; i < files.length; i++) {
815
- bridge.call('updateNotification', {
816
- taskId: 'file-sync',
817
- title: '동기화 중',
818
- body: `${files[i].name}`,
819
- progress: {
820
- current: i + 1,
821
- max: files.length
350
+ bridge.on('onWifiStateChange', (event) => {
351
+ switch (event.type) {
352
+ case 'WIFI_STATE_CHANGED':
353
+ console.log(`WiFi state: ${event.wifiState}`);
354
+ break;
355
+ case 'CONNECTION_STATE_CHANGED':
356
+ console.log(`Connection: ${event.connectionState}`);
357
+ if (event.wifiInfo) {
358
+ console.log(`SSID: ${event.wifiInfo.ssid}`);
822
359
  }
823
- });
824
-
825
- await uploadFile(files[i]);
360
+ break;
826
361
  }
827
-
828
- bridge.call('updateNotification', {
829
- taskId: 'file-sync',
830
- title: '동기화 완료',
831
- body: `${files.length}개 파일 동기화됨`,
832
- progress: undefined
833
- });
834
- }
362
+ });
835
363
  ```
836
364
 
837
365
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnww-plugin-wifi",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "React Native WebView WiFi Plugin with Expo support - Get WiFi information and manage connections",
5
5
  "main": "lib/bridge/index.js",
6
6
  "types": "lib/bridge/index.d.ts",