diff --git a/README.md b/README.md index 46bb172..ce62a90 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,11 @@ We actively welcome contributions! Whether you're fixing a bug, optimizing perfo #### 📱 Android App 1. **Prerequisites:** Install the latest **Android Studio**. 2. **Import:** Open the `android/` directory as a project. -3. **Build:** Let Gradle sync and download dependencies. +3. **Build:** Let Gradle sync and download dependencies, then build the release APK: + ```cmd + cd android + gradlew.bat clean assembleRelease + ``` * *Core Dependency:* [RootEncoder](https://github.com/pedroSG94/RootEncoder) (handles RTSP/RTP packets). 4. **Run:** Connect a physical Android device (emulators often lack necessary encoder hardware) and run the `app` module. @@ -175,6 +179,13 @@ We actively welcome contributions! Whether you're fixing a bug, optimizing perfo regsvr32 softcam.dll ``` +#### 📦 Building the distributable package +Run `package.bat` from the repository root after building the Windows client into `dist/`. +The packaging script runs Gradle's `:app:copyApk` task, which builds the Android +release from the current source tree before copying it into `dist/apk/`. It removes +the previous destination APK first and stops if the build does not recreate it, +preventing an old APK from being shipped with a newer desktop client. + ### 📬 Submitting a Pull Request 1. Fork the project. 2. Create your feature branch (`git checkout -b feature/AmazingFeature`). @@ -200,6 +211,27 @@ If the Android app cannot connect to the Windows client: * Open a terminal in the VCamdroid folder and run: `adb shell ping -c 4 ` * If you see "100% packet loss" or "unreachable," your PC's firewall or router settings (AP Isolation) are blocking the connection. +### Phone connects but the device and video do not appear +The TCP connection on port `6969` is only the first pairing step. The Android app +must next send its `DeviceDescriptor`; only then can the Windows client list the +device. Select the phone in the Windows source list to request streaming and open +the RTSP video on port `8554`. + +If `vcamdroid.log` contains `Device connected` but the device never appears: +1. Make sure the desktop client and Android APK came from the same release package. +2. When building from source, run `package.bat` instead of reusing an APK from an + older `dist/` directory. +3. Reinstall the packaged APK with `scripts\install_apk.bat`. If ADB reports + `INSTALL_FAILED_UPDATE_INCOMPATIBLE`, uninstall the existing + `com.darusc.vcamdroid` package first; this removes its local app data. +4. Pair again, select the listed phone as the source, and verify that streaming + starts and live video appears in the desktop client. + +The QR dialog remaining visible by itself does not prove that pairing failed; use +the device list, video preview, and logs as the success criteria. See +[Device registration troubleshooting](docs/troubleshooting-device-registration.md) +for the complete diagnostic flow. + ### USB Connection not working If the app does not detect your phone: 1. **Check ADB Devices:** diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 65acca0..96ee9db 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -41,8 +41,9 @@ android { } tasks.register("copyApk") { - from("release/") - into("../../dist/apk") + dependsOn("assembleRelease") + from(layout.buildDirectory.file("outputs/apk/release/app-release.apk")) + into(rootProject.file("../dist/apk")) } dependencies { diff --git a/docs/troubleshooting-device-registration.md b/docs/troubleshooting-device-registration.md new file mode 100644 index 0000000..6e667af --- /dev/null +++ b/docs/troubleshooting-device-registration.md @@ -0,0 +1,124 @@ +# Device registration and video troubleshooting + +This guide covers the failure mode where the Android camera opens and the phone +reaches the Windows client, but no device or video appears in the desktop app. + +## Pairing sequence + +A successful Wi-Fi pairing has five separate gates: + +1. The QR code gives the Android client the Windows host and control port (`6969`). +2. Android opens the TCP control connection. +3. Android sends a `DeviceDescriptor` containing the device name, RTSP URL, + camera resolutions, and supported filters. +4. Windows registers the descriptor and adds the phone to the source list. +5. The user selects the phone in that source list; Windows then sends the stream + options and opens the RTSP stream (normally on port `8554`). + +A TCP connection alone is not enough. If gate 2 succeeds but gate 3 fails, the +server can log `Device connected` while the device list and video remain empty. +The QR dialog may also remain visible, so the device list, logs, and live preview +are the reliable success criteria. + +## Confirmed failure mode: mismatched release artifacts + +The Android and Windows clients must use the same protocol version. A package +containing a current desktop executable and an older APK can connect on port +`6969`, but the old Android client may not send the `DeviceDescriptor` expected +by Windows. Without that descriptor, Windows cannot register the device or +request the RTSP stream. + +Historically, the Gradle `copyApk` task copied from `android/app/release/`, a +manually populated location, and did not depend on `assembleRelease`. +`package.bat` then reused the contents of `dist/` without building Android. This +allowed a stale APK to be distributed with a newer desktop client. + +The packaging flow now prevents that combination: + +- `:app:copyApk` depends on `assembleRelease`. +- It copies the exact Gradle output from + `android/app/build/outputs/apk/release/app-release.apk`. +- `package.bat` removes the previous destination APK, invokes that task, and stops + if the Android build does not recreate the APK. + +## Diagnosis + +### 1. Confirm ADB access (USB) + +```cmd +adb devices -l +``` + +The device state must be `device`, not `unauthorized` or `offline`. + +### 2. Confirm the Windows control listener + +```cmd +netstat -ano | findstr :6969 +``` + +The desktop client should have a `LISTENING` socket on port `6969`. + +### 3. Check both sides of the protocol + +- Windows: inspect `vcamdroid.log` beside `VCamdroid.exe`. +- Android: use the in-app log screen when available, or collect Logcat: + +```cmd +adb logcat | findstr /i VCamdroid +``` + +If Windows logs `Device connected` but never lists the phone, reinstall an APK +built from the same source/release as the desktop client before changing network +or firewall settings. + +### 4. Handle Android signature mismatch + +The installer first uses `adb install -r` to preserve app data. If ADB reports: + +```text +INSTALL_FAILED_UPDATE_INCOMPATIBLE +``` + +the installed package was signed with a different key. Back up anything needed, +then uninstall `com.darusc.vcamdroid` and install the packaged APK again. Android +removes the application's local data during uninstall. + +## Build and package a matching release + +From the repository root on Windows: + +```cmd +android\gradlew.bat -p android clean :app:copyApk +package.bat +``` + +`package.bat` expects the Windows release files to already exist in `dist/`. The +resulting Android package is: + +```text +VCamdroid\apk\app-release.apk +``` + +To verify artifact identity, compare the SHA-256 values: + +```cmd +certutil -hashfile android\app\build\outputs\apk\release\app-release.apk SHA256 +certutil -hashfile dist\apk\app-release.apk SHA256 +certutil -hashfile VCamdroid\apk\app-release.apk SHA256 +``` + +All three hashes must match. + +## End-to-end success criteria + +After installing the packaged APK and pairing again, verify all of the following: + +- the phone reaches the control server on port `6969`; +- the phone appears in the Windows device list; +- the phone is selected in the Windows source list; +- Windows requests streaming after that selection; +- the RTSP stream is reachable (normally port `8554`); +- live camera video appears in the desktop preview. + +Treat the test as failed if only the TCP connection or camera preview works. diff --git a/install_apk.bat b/install_apk.bat index b8ce7d2..2d85a4d 100644 --- a/install_apk.bat +++ b/install_apk.bat @@ -1,4 +1,27 @@ @echo off +setlocal echo Installing VCamdroid apk to android device -..\adb\adb.exe install -r ..\apk\app-release.apk \ No newline at end of file +set "ADB=%~dp0..\adb\adb.exe" +set "APK=%~dp0..\apk\app-release.apk" + +if not exist "%ADB%" ( + echo [ERROR] adb.exe was not found at: %ADB% + exit /b 1 +) + +if not exist "%APK%" ( + echo [ERROR] Android APK was not found at: %APK% + exit /b 1 +) + +"%ADB%" install -r "%APK%" +if errorlevel 1 ( + echo [ERROR] APK installation failed. + echo If adb reported INSTALL_FAILED_UPDATE_INCOMPATIBLE, uninstall the old + echo com.darusc.vcamdroid package first. This removes its local app data. + exit /b 1 +) + +echo [SUCCESS] VCamdroid Android client installed. +exit /b 0 \ No newline at end of file diff --git a/package.bat b/package.bat index b8c975f..c652da0 100644 --- a/package.bat +++ b/package.bat @@ -1,66 +1,144 @@ @echo off -setlocal enabledelayedexpansion +setlocal +pushd "%~dp0" :: --- Configuration --- set "SOURCE_DIST=dist" set "SOURCE_ADB=windows\adb" set "OUTPUT_DIR=VCamdroid" +set "GRADLE_WRAPPER=android\gradlew.bat" +set "ANDROID_APK=%SOURCE_DIST%\apk\app-release.apk" +set "WINDOWS_APP=%SOURCE_DIST%\VCamdroid.exe" :: List of scripts to copy (located in the current root dir) set "SCRIPTS_TO_COPY=install.bat install_apk.bat uninstall.bat" echo [INFO] Starting Package Build... -:: 1. Clean previous build +:: 1. Verify the Windows release exists before Android creates dist/apk +if not exist "%WINDOWS_APP%" ( + echo [ERROR] Windows release not found at: %WINDOWS_APP% + goto :Error +) + +:: 2. Build and copy the Android client from the current source tree +if not exist "%GRADLE_WRAPPER%" ( + echo [ERROR] Gradle wrapper not found at: %GRADLE_WRAPPER% + goto :Error +) + +if not exist "%SOURCE_ADB%\adb.exe" ( + echo [ERROR] ADB executable not found at: %SOURCE_ADB%\adb.exe + goto :Error +) + +for %%f in (%SCRIPTS_TO_COPY%) do ( + if not exist "%%f" ( + echo [ERROR] Required script not found: %%f + goto :Error + ) +) + +if exist "%ANDROID_APK%" ( + echo [INFO] Removing previous Android APK... + del /f /q "%ANDROID_APK%" + if exist "%ANDROID_APK%" ( + echo [ERROR] Could not remove the previous APK at: %ANDROID_APK% + goto :Error + ) +) + +echo [INFO] Building current Android release... +call "%GRADLE_WRAPPER%" -p android :app:copyApk --console=plain +if errorlevel 1 ( + echo [ERROR] Android release build failed. + goto :Error +) + +if not exist "%ANDROID_APK%" ( + echo [ERROR] Android APK was not created at: %ANDROID_APK% + goto :Error +) + +:: 3. Clean previous build if exist "%OUTPUT_DIR%" ( echo [INFO] Cleaning old output directory... rmdir /s /q "%OUTPUT_DIR%" + if exist "%OUTPUT_DIR%" ( + echo [ERROR] Could not clean output directory: %OUTPUT_DIR% + goto :Error + ) ) -:: 2. Create new directory structure +:: 4. Create new directory structure echo [INFO] Creating directory structure... mkdir "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%\scripts" mkdir "%OUTPUT_DIR%\adb" +if not exist "%OUTPUT_DIR%\scripts" ( + echo [ERROR] Could not create scripts directory. + goto :Error +) +if not exist "%OUTPUT_DIR%\adb" ( + echo [ERROR] Could not create ADB directory. + goto :Error +) -:: 3. Copy App Executables (contents of /dist -> /vcamdroid) +:: 5. Copy App Executables (contents of /dist -> /vcamdroid) if exist "%SOURCE_DIST%" ( echo [INFO] Copying application executables... xcopy /s /e /y /q "%SOURCE_DIST%\*" "%OUTPUT_DIR%\" + if errorlevel 1 goto :Error ) else ( echo [ERROR] Dist folder not found at: %SOURCE_DIST% goto :Error ) -:: 4. Copy ADB folder (/windows/adb -> /vcamdroid/adb) +:: 6. Copy ADB folder (/windows/adb -> /vcamdroid/adb) if exist "%SOURCE_ADB%" ( echo [INFO] Copying ADB binaries... xcopy /s /e /y /q "%SOURCE_ADB%\*" "%OUTPUT_DIR%\adb\" + if errorlevel 1 goto :Error ) else ( echo [ERROR] ADB folder not found at: %SOURCE_ADB% goto :Error ) -:: 5. Copy Batch Scripts (root -> /vcamdroid/scripts/) +:: 7. Copy Batch Scripts (root -> /vcamdroid/scripts/) echo [INFO] Copying batch scripts... for %%f in (%SCRIPTS_TO_COPY%) do ( - if exist "%%f" ( - copy /y "%%f" "%OUTPUT_DIR%\scripts\%%f" >nul - echo - Copied %%f - ) else ( - echo [WARNING] Script not found: %%f + copy /y "%%f" "%OUTPUT_DIR%\scripts\%%f" >nul + if errorlevel 1 ( + echo [ERROR] Failed to copy script: %%f + goto :Error ) + echo - Copied %%f +) + +if not exist "%OUTPUT_DIR%\VCamdroid.exe" ( + echo [ERROR] Packaged Windows executable is missing. + goto :Error +) +if not exist "%OUTPUT_DIR%\apk\app-release.apk" ( + echo [ERROR] Packaged Android APK is missing. + goto :Error +) +if not exist "%OUTPUT_DIR%\adb\adb.exe" ( + echo [ERROR] Packaged ADB executable is missing. + goto :Error ) echo. echo =================================================== echo [SUCCESS] Package created successfully in: %OUTPUT_DIR% echo =================================================== +popd pause exit /b 0 :Error echo. echo [FAIL] An error occurred during packaging. +popd pause exit /b 1 \ No newline at end of file