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 |