pubspec.yaml
dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^2.0.0 webview_flutter: ^4.2.2 flutter_inappwebview: ^5.3.2 hex: ^0.2.0
main.dart
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:webview_flutter/src/webview_controller.dart'; import 'SocketManager.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'InAppWebView Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late InAppWebViewController _webViewController; final socketManager = SocketManager(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('InAppWebView Example'), ), body: InAppWebView( initialUrlRequest: URLRequest(url: Uri.parse('http://192.168.0.6:5173/')), initialOptions: InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( javaScriptCanOpenWindowsAutomatically: true, javaScriptEnabled: true, useOnDownloadStart: true, useOnLoadResource: true, useShouldOverrideUrlLoading: true, mediaPlaybackRequiresUserGesture: true, allowFileAccessFromFileURLs: true, allowUniversalAccessFromFileURLs: true, verticalScrollBarEnabled: true, userAgent: 'agent-> naya moblie_wv', ), android: AndroidInAppWebViewOptions( ), ios: IOSInAppWebViewOptions( ), ), onWebViewCreated: (controller) { _webViewController = controller; // JavaScript 채널 추가 _webViewController.addJavaScriptHandler( handlerName: 'JsChannel', // 채널 이름 callback: (message) { // 자바스크립트 채널로부터 받은 데이터 처리 print('Received data from JavaScript: ${message[0]}'); _web2flutter(message[0]); }, ); }, onConsoleMessage: (webViewController, consoleMessage) { print("JavaScript Console Message: ${consoleMessage.message}"); }, ), floatingActionButton: FloatingActionButton( child: Icon(Icons.refresh), onPressed: () { _webViewController.reload(); }, ), ); } _web2flutter(message) async { print('_web2flutter(message) start'); /* * json 형태를 객체로 변경 */ Map<String, dynamic> parsedJson = jsonDecode(message); var action = parsedJson['action']; var inputHexString = parsedJson['hexString']; print('acton:'+action); print('inputHexString:'+inputHexString); var receivedHexString = ''; print(action); switch(action) { case 'connect': connect(); break; case 'sendTr' : sendTr(inputHexString); break; case 'bufferTest' : bufferTest(); break; } } Future<void> connect() async { await socketManager.connectToSocket(_webViewController); // 소켓 접속한다. var receivedConnected = 'connected : ${socketManager.connected}'; print(receivedConnected); //_webViewController.runJavaScript("flutter2web('$receivedConnected')"); } Future<void> sendTr(sendHexString) async { socketManager.sendTr(sendHexString); // 접속된 소켓에 데이터를 전송한다. input } void bufferTest() { List<int> buffer = [0x00, 0x00, 0x07, 0x04]; // 예시 데이터 int length = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; print(buffer[0]); print(buffer[1]); print(buffer[2]); print(buffer[3]); int part1 = buffer[0] << 24; // 24비트(3byte) 왼쪽으로 이동 -> 0x 00 00 00 00 (32bit - 4byte) int part2 = buffer[1] << 16; // 16비트(2byte) 왼쪽으로 이동 -> 0x 00 00 00 (24bit - 3byte) int part3 = buffer[2] << 8; // 8비트(1byte) 왼쪽으로 이동 -> 0x 07 00 (16bit - 2byte) int part4 = buffer[3]; // 그대로 사용 -> 0x 04 (8bit - 1byte) /** * 그럼 0x03 을 24비트 좌측 쉬프트 하면 ? 0x03 이진수로 표현 00000000 00000000 00000000 00000011 0x03 << 24 0x00 00 00 03 그럼 0x03 을 16비트 좌측 쉬프트 하면 ? 0x03 << 16 0x00 03 00 00 그럼 0x03 을 8비트 좌측 쉬프트 하면 ? 0x03 << 8 0x00 00 03 00 ------------------------------------------------------- 0x00 << 24 0x00 00 00 00 0x00 << 16 0x00 00 00 00 0x07 << 8 0x00 00 07 00 0x04 그대로 사용 0x00 00 00 04 ==> | or 연산하면 0x00 00 00 00 0x00 00 00 00 0x00 00 07 00 0x00 00 00 04 ------------- 0x00 00 07 04 결론 0x00000704 16진수 704 10진수로 변환하면 1796 */ // 10진수 값을 16진수 문자열로 변환 print('Part 1: ${part1}'); print('Part 1: ${part1.toRadixString(16)}'); print('Part 2: ${part2.toRadixString(16)}'); print('Part 3: ${part3.toRadixString(16)}'); print('Part 4: ${part4.toRadixString(16)}'); print('Length1: ${length.toRadixString(16)}'); print('Length2: $length'); } }
SocketManager.dart
import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; import 'dart:typed_data'; import 'package:hex/hex.dart'; import 'package:webview_flutter/src/webview_controller.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; class SocketManager { late Socket _socket; bool _connected = false; late String _hexString = ''; late InAppWebViewController _controller; /* static const String host = "220.72.212."; // php server static const int port = 25003;*/ static const String host = "13.125.57."; // mymq static const int port = 900; Future<void> connectToSocket(InAppWebViewController controller) async { try { _socket = await Socket.connect(host, port); print('Socket connected'); _controller = controller; _connected = true; _listenToSocket(); } catch (e) { print('Failed to connect to socket: $e'); _connected = false; } } Future<void> _listenToSocket() async { // 데이터를 받을 버퍼를 초기화 List<int> buffer = []; _socket.listen( (List<int> data) async { // 받은 데이터를 버퍼에 추가 buffer.addAll(data); // 전체 데이터 길이 정보가 도착한 경우 if (buffer.length >= 4) { /** * 전체 데이터 길이를 얻음 * buffer[0], buffer[1], buffer[2], buffer[3] 각각은 1바이트 크기의 정수 값입니다. buffer 배열의 첫 4바이트를 나타냅니다. << 연산자는 비트를 왼쪽으로 이동시키는 연산입니다. buffer[0] << 24는 buffer[0]의 비트를 왼쪽으로 24비트 이동시킨 값을 의미합니다. 마찬가지로 buffer[1] << 16, buffer[2] << 8, buffer[3]은 각각 비트를 왼쪽으로 16, 8, 0비트 이동시킨 값을 나타냅니다. | 연산자는 비트별 OR 연산을 수행합니다. 위의 네 개의 이동 연산을 수행한 결과를 비트별 OR 연산하여 하나의 정수 값으로 합쳐줍니다. */ int length = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; print('Lengthaaa: $length'); // 버퍼에 모든 데이터가 도착한 경우 if (buffer.length >= length + 4) { // 데이터를 추출하고 사용 List<int> receivedData = buffer.sublist(0, length + 4); _hexString = HEX.encode(receivedData); print('flutter 에서 데이터 수신'); print(_hexString); // 사용한 데이터는 버퍼에서 삭제 buffer.removeRange(0, length + 4); // 비동기 작업을 수행하고자 하는 경우, await 키워드로 Future를 기다릴 수 있습니다. await someAsyncTask(); // 비동기 작업 후 추가적인 코드 } } }, onError: (e) { print('Socket error: $e'); _disconnect(); }, onDone: () { print('Socket disconnected'); _disconnect(); }, cancelOnError: false, ); } /* Future<void> _listenToSocket() async { _socket.listen( (List<int> data) async { // 데이터 수신 처리 _hexString = HEX.encode(data); print('flutter 에서 데이터 수신'); print(_hexString); // 비동기 작업을 수행하고자 하는 경우, await 키워드로 Future를 기다릴 수 있습니다. await someAsyncTask(); // 비동기 작업 후 추가적인 코드 }, onError: (e) { print('Socket error: $e'); _disconnect(); }, onDone: () { print('Socket disconnected'); _disconnect(); }, cancelOnError: false, ); }*/ Future<void> someAsyncTask() async { // 비동기 작업을 수행하는 함수 Map<String, dynamic> jsonObject = { 'action': 'flutter', 'resHexString': _hexString, }; String jsonString = json.encode(jsonObject); print('jsonString'); print(jsonString); //##_controller.runJavaScript("flutter2web('$jsonString')"); _controller.evaluateJavascript(source: "flutter2web('$jsonString')"); } Future<void> sendData(String message) async { if (!_connected) { print('Socket is not connected'); return; } try { _socket.write(message); await _socket.flush(); print('Sent: $message'); } catch (e) { print('Failed to send data: $e'); _disconnect(); } } Future<void> sendTr(String message) async { if (!_connected) { print('Socket is not connected'); return; } List<int> bytes = HEX.decode(message); try { _socket.add(bytes); await _socket.flush(); print('Sent: $message'); } catch (e) { print('Failed to send data: $e'); _disconnect(); } } void _disconnect() { _socket?.close(); _connected = false; } String get hexString { return _hexString; } bool get connected { return _connected; } }
javascript
const connect =_=>{ Common.debugApp('connecting....'); const message = { key: 'value', action: 'connect', hexString: 'aa', }; window.flutter_inappwebview.callHandler('JsChannel', JSON.stringify(message)); }; const bufferTest =_=>{ alert(11) const message = { action:'bufferTest', hexString: 'zz', }; window.flutter_inappwebview.callHandler('JsChannel', JSON.stringify(message)); };
flutter.js
/** * flutter socket 에서 응답받은 hexString 을 받는다. * @param {*} data */ export const flutter2web = data => { $Worker.receiveFlutterApp(data); };
'프로그래밍 > flutter' 카테고리의 다른 글
[flutter] 스플래쉬(splash) 화면 추가 (0) | 2023.08.16 |
---|---|
[flutter] 백버튼(뒤로가기) 클릭시 "종료하시겠습니까?" 다이얼로그 추가 (0) | 2023.08.16 |
소켓통신 첫 4byte 길이 구하기 (비트연산) (0) | 2023.08.10 |
[flutter] 소켓 통신 응답받을때 데이터 짤리는 문제 (0) | 2023.08.08 |
[flutter] native(앱) 의 웹뷰(vue3) 양방향 통신 방법 webview_flutter 사용 (0) | 2023.08.08 |