v3.4.0: 서버사이드 Android 에뮬레이터 (코드 에디터 내장)

Docker(budtmo/docker-android) + noVNC로 코드 에디터 하단 패널에 실제
조작 가능한 Android 에뮬레이터 화면을 띄운다. 세션 생명주기(생성/유휴
타임아웃/정리)는 기존 Arduino QEMU 라우트 패턴을 따르고, noVNC 화면은
Stirling-PDF 프록시와 같은 방식으로 게이트웨이를 통해 리버스 프록시한다.

- src/gateway/routes-android.ts: Docker 세션 관리 + noVNC HTTP/WS 프록시
- web-ui/android-emulator.html: 부팅 폴링 + noVNC 임베드 페이지
- code.js/code.html: "🤖 Android" 버튼, 기존 에뮬레이터 패널 재사용

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
kim
2026-07-08 00:41:54 +09:00
co-authored by Claude Sonnet 5
parent 186dc4cb23
commit 94caf1c4da
9 changed files with 556 additions and 19 deletions
+22
View File
@@ -1143,6 +1143,28 @@ function openArduinoEmulator() {
}
}
function openAndroidEmulator() {
const btn = document.getElementById('code-android-btn');
if (btn) { btn.textContent = '⏳ 부팅 중…'; btn.disabled = true; }
_emuPanelLoad('/android-emulator.html?loading=1', 'Android');
codeAiAppend('system', '🤖 Android 에뮬레이터 부팅 중... (최대 90초)');
api('/api/android/start', { method: 'POST' })
.then(d => {
if (btn) { btn.textContent = '🤖 Android'; btn.disabled = false; }
if (d.error) {
codeAiAppend('system', '⚠️ ' + d.error);
toggleEmuPanel();
return;
}
_emuPanelLoad('/android-emulator.html?session=' + d.id, 'Android');
codeAiAppend('system', '✅ Android 에뮬레이터 실행 중.');
}).catch(e => {
if (btn) { btn.textContent = '🤖 Android'; btn.disabled = false; }
codeAiAppend('system', '⚠️ ' + e.message);
toggleEmuPanel();
});
}
// ── Arduino 업로드 페이지 열기 ────────────────────────────────────────────────
function csbUploadToBoard() {
const file = codeFiles.find(f => f.id === activeCodeFileId);