Android Setup
Barbelic Android 앱은 iOS 앱과 같은 구조의 Capacitor 셸이다. WebView는 번들 대신 원격 정규 origin https://www.barbelic.com을 열고, Kakao·Google·Apple 로그인은 iOS와 동일한 native bridge v1 계약으로 처리한다. 네이티브 셸은 Kotlin(android/app/src/main/java/com/dekerd/barbelic/)이다.
준비 및 실행
- Android Studio(2025.2.1 이상)와 SDK Platform 36, Build-Tools 36, Platform-Tools. 헤드리스로는
cmdline-tools의sdkmanager "platforms;android-36" "build-tools;36.0.0" "platform-tools". - JDK 21 (Android Studio 번들 JBR 또는 Microsoft OpenJDK 21).
JAVA_HOME을 맞춘다. android/local.properties에sdk.dir=<SDK 경로>(슬래시 경로, git 제외).- 실기기는 USB 디버깅을 허용하고
adb devices에 보여야 한다.
npm ci
npm run build
npm run android:sync
npm run android:build # android/app/build/outputs/apk/debug/app-debug.apk
adb install -r android/app/build/outputs/apk/debug/app-debug.apknpm run android:open은 Android Studio에서 android/를 연다. android:sync는 capacitor.settings.gradle·app/capacitor.build.gradle· app/src/main/assets/{public,capacitor.config.json}을 다시 만든다(모두 git 제외). dist-vite/가 비어 있으면 cap sync가 실패하므로 npm run build가 먼저다 — 실제 화면은 원격 origin에서 오고 번들 자산은 자리만 채운다.
Build configuration
android/app/build.gradle이 iOS xcconfig와 같은 세 값을 BuildConfig로 주입한다.
BARBELIC_SERVER_ORIGIN: WebView가 여는 정규 originhttps://www.barbelic.comBARBELIC_SUPABASE_AUTH_ORIGIN: authorize URL을 허용할 정확한 Supabase originBARBELIC_CALLBACK_SCHEME: custom URL schemebarbelic(AndroidManifest.xml의barbelic://auth/callbackintent-filter에도 같은 값이 들어간다)
MainActivity는 CapConfig.Builder.setServerUrl로 원격 origin을 지정한다 — iOS MainViewController.instanceDescriptor()와 같은 역할이다. Supabase Dashboard의 Redirect URLs에 등록된 barbelic://auth/callback**은 iOS와 공유한다.
식별자: applicationId·namespace com.dekerd.barbelic, 표시명 Barbelic, 런처 아이콘은 iOS AppIcon 비트맵을 정사각 축소한 mipmap-*/ic_launcher.png와 검정 바탕 adaptive icon(mipmap-anydpi-v26/ic_launcher.xml)이다.
iOS와 다른 점
- 외부 인증 창:
ASWebAuthenticationSession대신 Chrome Custom Tabs. Google은 임베디드 WebView OAuth를 차단하므로 브라우저 탭이 필수다. - Apple 로그인: Android에는 시스템 시트가 없어 Supabase authorize 웹 플로우 (Services ID
com.dekerd.barbelic.web)로 처리한다. 웹 측 코드는 같다. - 보안 저장소: Keychain 대신 Android Keystore(AES-GCM) 키로 암호화한 값을 앱 전용 SharedPreferences에 둔다.
allowBackup=false. - 웹→네이티브 전송:
window.barbelicNative.postMessage(JSON.stringify(...))(androidx.webkitWebMessageListener, 허용 origin은 서버 origin 하나). 웹barbelicNav.notifyNative가 WebKit 핸들러가 없을 때 이 경로를 쓴다. - 세션 이미지 저장(
sessionDownloadImage)은 첫 출시 범위에서 제외한다(오너 D5). 네이티브는 메시지를 받으면 안내 토스트만 띄운다. - 시스템바: 테마
windowBackground·status/navigation bar 색이 검정이고 CapacitorSystemBars플러그인style: dark(밝은 아이콘). WebView 140+에서는 inset을 CSSenv(safe-area-inset-*)로 통과시키고(viewport-fit=cover), 그 이전 WebView는 Capacitor가 WebView에 패딩을 준다 — 어느 쪽이든 바 영역은 검정이다. - 시스템 뒤로가기: 웹
barbelicNav가 레이어마다history.pushState({ lg })를 쌓으므로history.state.lg가root가 아니면history.back()(웹 popstate가 레이어를 닫음), 루트면moveTaskToBack— 다른 문서로 되돌아가지 않는다. 키보드가 떠 있으면 IME가 먼저 뒤로가기를 소비한다. - 키보드:
windowSoftInputMode="adjustResize"+ Capacitor IME inset 처리로 WebView가 줄어든다(innerHeight감소). iOS처럼 덮지 않는다.
실기기 확인
- 앱 아이콘·스플래시(검정 바탕)가 뜨고 WebView가
https://www.barbelic.com/을 여는가 chrome://inspect(debug 빌드)에서window.barbelicNative와window.__barbelicNativeCapabilities가 보이는가- 로그인 화면 세 버튼이 Custom Tabs를 열고, 취소 시 pending 상태가 풀리는가
- 성공 callback이
barbelic://auth/callback으로 앱에 돌아와 홈이 다시 뜨는가 - 앱을 완전히 종료 후 다시 열어도 로그인이 복원되는가
- 시스템 뒤로가기가 웹 레이어(메뉴·세션·운동)를 닫고, 루트에서는 앱을 내리는가
- 운동 진행 중 화면이 꺼지지 않는가(
workoutActive) - 키보드가 입력란을 가리지 않는가(
adjustResize+ edge-to-edge)
Windows에서 Gradle 빌드·에뮬레이터·실기기 설치가 모두 가능하다(iOS와 달리 Mac 불필요). 서명·번들·Play 등록은 android-release.md를 따른다.