Files
ts-mobile-go/AGENTS.md
T
2026-07-20 19:01:03 +08:00

4.4 KiB

AGENTS.md

This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.

Project Overview

TeamSpeak Android native client with a two-layer architecture:

  • Protocol layer: Go + teamspeak-go → compiled to .aar via gomobile
  • UI layer: Kotlin + Jetpack Compose + Material Design 3

Build Commands

# Windows
build.bat

# Linux/macOS
./build.sh

Manual Build (Two Steps Required)

Step 1: Compile Go → AAR

cd go
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8  # Windows only
gomobile bind -target=android -androidapi=26 -ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both" -o ../android/app/libs/teamspeak.aar ./teamspeak

Step 2: Build Android APK

cd android
gradlew.bat assembleDebug  # Windows
./gradlew assembleDebug     # Linux/macOS

Development Workflow

  • Modified Go code (go/): Re-run Step 1, then run from IDE
  • Modified Kotlin code (android/): Just run from IDE (IntelliJ/Android Studio)

Open the android/ directory (not root) in IntelliJ IDEA or Android Studio.

Architecture

Go ↔ Kotlin Bridge

Communication flows through two bridge layers:

  1. Go side (go/teamspeak/bridge.go): Exports TSClient class via gomobile
  2. Kotlin side (android/app/src/main/java/com/tsmobile/app/TSBridge.kt): Wraps gomobile API

Key constraints (gomobile limitations):

  • Cannot export []string, []*T, or Go error types
  • Complex data passed as JSON strings (channels, clients)
  • Events delivered via callback interfaces
  • All JNI callbacks serialized through an event queue to avoid threading issues

Event flow: Go library → event queue → single consumer goroutine → JNI callback → Kotlin callback → ViewModel

Android Layer Structure

android/app/src/main/java/com/tsmobile/app/
├── MainActivity.kt              # Entry point
├── TSBridge.kt                  # Go bridge wrapper
├── ui/
│   ├── components/              # Reusable UI components
│   ├── screens/                 # Top-level screens
│   ├── navigation/NavGraph.kt   # App navigation
│   └── theme/                   # Material Design 3 theme
└── viewmodel/                   # State management
    ├── ChannelViewModel.kt      # Channel list & navigation
    ├── ChatViewModel.kt         # Text messaging
    ├── ServerViewModel.kt       # Connection & server info
    └── VoiceViewModel.kt        # Voice communication

State flows from ViewModels → Screens via StateFlow. User actions flow back via ViewModel methods.

Critical Build Details

Required Flags for gomobile

The -ldflags are mandatory to avoid runtime crashes:

  1. -linkmode=external: Use NDK's external linker instead of Go's built-in linker

    • Why: Prevents SIGSEGV crashes due to signal handling conflicts between Go runtime and Android
    • Go uses SIGSEGV for GC and goroutine scheduling; Android's memory protection blocks this
  2. -extldflags=-Wl,--hash-style=both: Generate compatible ELF hash tables

    • Why: Go 1.24+ uses DT_SUNW_HASH by default; Android requires DT_HASH or DT_GNU_HASH
    • Without this: dlopen failed: empty/missing DT_HASH/DT_GNU_HASH error

Local Patches

The go/_patches/github.com/honeybbq/teamspeak-go/ directory contains modified upstream code:

  • Fixes 32-bit integer overflow issues (math.MaxUint32 → platform-specific limits)
  • Applied via go.mod replace directive: replace github.com/honeybbq/teamspeak-go => ./_patches/github.com/honeybbq/teamspeak-go

Do not remove this directory or the replace directive.

Common Issues

"javac: 非法字符" or "GBK unmappable character"

Set encoding before running gomobile on Windows:

set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8

App crashes with "SIGSEGV" on startup

Missing -linkmode=external flag. Rebuild AAR with correct flags.

App crashes with "empty/missing DT_HASH"

Missing -Wl,--hash-style=both flag. Rebuild AAR with correct flags.

"Unresolved reference: teamspeak"

AAR not compiled or not in android/app/libs/teamspeak.aar. Run Step 1 of manual build.

Testing

Run from IDE with connected device or emulator. Check Logcat in IDE for runtime logs.

No automated test suite currently exists.