Skip to main content

Prerequisites

Before building Deeztracker Mobile, ensure you have the following installed:

Required Software

  • Version: Android Studio Hedgehog (2023.1.1) or later
  • Download: developer.android.com/studio
  • Includes Android SDK, Build Tools, and emulator support
  • Version: JDK 8 or later (JDK 11 recommended)
  • Required for: Gradle builds and Android compilation
  • Java 8 compatibility is enforced via JavaVersion.VERSION_1_8 in build config
  • Required for: Building the rusteer native library
  • Installation: Install via rustup.rs
  • Target: Android NDK targets (aarch64, armv7, x86_64, i686)
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Add Android targets
rustup target add aarch64-linux-android
rustup target add armv7-linux-androideabi
rustup target add x86_64-linux-android
rustup target add i686-linux-android
  • Version: NDK r25c or later
  • Required for: Compiling Rust code to native Android libraries
  • Installation: Via Android Studio SDK Manager

SDK Configuration

The project requires:
  • Compile SDK: API 34 (Android 14)
  • Min SDK: API 24 (Android 7.0)
  • Target SDK: API 34
These are defined in app/build.gradle.kts:10-16:
android {
    namespace = "com.crowstar.deeztrackermobile"
    compileSdk = 34
    
    defaultConfig {
        applicationId = "com.crowstar.deeztrackermobile"
        minSdk = 24
        targetSdk = 34
        versionCode = 5
        versionName = "1.1.1"
    }
}

Cloning the Repository

1

Clone with Git

git clone https://github.com/xScherpschutter/deeztracker-mobile.git
cd deeztracker-mobile
2

Verify project structure

ls -la
# Expected output:
# app/          - Android application module
# rusteer/      - Rust library for Deezer integration
# gradle/       - Gradle wrapper files
# build.gradle.kts
# settings.gradle.kts
3

Sync project with Gradle

Open the project in Android Studio and let it sync dependencies automatically, or run:
./gradlew build --dry-run

Build Commands

Debug Build

Build a debug APK for testing and development:
./gradlew assembleDebug
Output location: app/build/outputs/apk/debug/Deeztracker-1.1.1.apk
Debug builds include debugging symbols and are not optimized. APK size will be larger than release builds.

Release Build

Build an optimized release APK:
./gradlew assembleRelease
Output location: app/build/outputs/apk/release/Deeztracker-1.1.1.apk
Release builds require signing configuration. See Signing Configuration below.

Running on Device/Emulator

Install Debug Build

./gradlew installDebug

Install Release Build

./gradlew installRelease

Run from Android Studio

  1. Open the project in Android Studio
  2. Select a device/emulator from the device dropdown
  3. Click Run (▶️) or press Shift + F10
  4. The app will build, install, and launch automatically

Signing Configuration

Development Signing

Debug builds are automatically signed with the debug keystore located at:
  • Linux/Mac: ~/.android/debug.keystore
  • Windows: C:\Users\<username>\.android\debug.keystore

Release Signing

Release builds require a custom keystore. The project is configured to use deeztracker.jks in the root directory.
1

Create a keystore

keytool -genkey -v -keystore deeztracker.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias deeztracker
Follow the prompts to set passwords and certificate details.
2

Create keystore.properties

Create a file named keystore.properties in the project root:
keystore.properties
storePassword=your_store_password
keyPassword=your_key_password
keyAlias=deeztracker
storeFile=../deeztracker.jks
Never commit keystore.properties or deeztracker.jks to version control!These files are already listed in .gitignore.
3

Build signed release

./gradlew assembleRelease
The signing configuration is automatically loaded from app/build.gradle.kts:26-39:
signingConfigs {
    create("release") {
        val keystorePropertiesFile = rootProject.file("keystore.properties")
        val keystoreProperties = Properties()
        if (keystorePropertiesFile.exists()) {
            keystoreProperties.load(FileInputStream(keystorePropertiesFile))
        }
        
        storeFile = file("../deeztracker.jks")
        storePassword = keystoreProperties["storePassword"] as String? 
            ?: System.getenv("KEYSTORE_PASSWORD")
        keyAlias = keystoreProperties["keyAlias"] as String? 
            ?: System.getenv("KEY_ALIAS")
        keyPassword = keystoreProperties["keyPassword"] as String? 
            ?: System.getenv("KEY_PASSWORD")
    }
}

CI/CD Signing

For automated builds (GitHub Actions, etc.), use environment variables instead of keystore.properties:
export KEYSTORE_PASSWORD="your_password"
export KEY_ALIAS="deeztracker"
export KEY_PASSWORD="your_key_password"
./gradlew assembleRelease

Build Configuration

ProGuard/R8

The project uses R8 for code shrinking and obfuscation in release builds:
app/build.gradle.kts:41-46
buildTypes {
    release {
        isMinifyEnabled = false  // Currently disabled
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"), 
            "proguard-rules.pro"
        )
        signingConfig = signingConfigs.getByName("release")
    }
}
ProGuard is currently disabled (isMinifyEnabled = false). To enable code shrinking, set this to true and configure proguard-rules.pro as needed.

Core Library Desugaring

The project uses desugaring to support Java 8+ APIs on older Android versions:
app/build.gradle.kts:48-52
compileOptions {
    isCoreLibraryDesugaringEnabled = true
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
}
This enables modern APIs like java.time on API 24+.

Troubleshooting

Common Issues

Solution: Set ANDROID_HOME environment variable:
# Linux/Mac
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools

# Windows
set ANDROID_HOME=C:\Users\<username>\AppData\Local\Android\Sdk
Add this to your .bashrc, .zshrc, or system environment variables.
Possible causes:
  1. Missing Rust toolchain: Install via rustup.rs
  2. Missing Android targets: Run:
    rustup target add aarch64-linux-android armv7-linux-androideabi
    
  3. NDK not configured: Set ANDROID_NDK_HOME:
    export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/<version>
    
The rusteer library uses UniFFI to generate Kotlin bindings from Rust code (rusteer/src/bindings.rs).
Error: Keystore file '.../deeztracker.jks' not found for signing config 'release'Solutions:
  1. Create keystore.properties with correct paths (see Signing Configuration)
  2. For CI/CD, use environment variables instead
  3. For debug builds, use ./gradlew assembleDebug (doesn’t require custom keystore)
Solution: Increase Gradle heap size in gradle.properties:
gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m
Or pass it via command line:
./gradlew assembleRelease -Dorg.gradle.jvmargs=-Xmx4096m
Error: Duplicate class ... found in modules ...Solution: Clean build cache and rebuild:
./gradlew clean
rm -rf .gradle build app/build
./gradlew assembleDebug
Check logs using Logcat:
adb logcat | grep -i deeztracker
Common issues:
  • Missing native libraries (rusteer .so files)
  • Permissions not granted (storage access)
  • Missing Deezer ARL token

Gradle Daemon Issues

If builds hang or behave unexpectedly:
# Stop Gradle daemon
./gradlew --stop

# Clean and rebuild
./gradlew clean assembleDebug

Cache Corruption

# Clear all caches
rm -rf ~/.gradle/caches/
rm -rf .gradle/
rm -rf app/build/

# Invalidate IDE caches (Android Studio)
# File → Invalidate Caches → Invalidate and Restart

Gradle Tasks Reference

Build Tasks

TaskDescription
./gradlew assembleDebugBuild debug APK
./gradlew assembleReleaseBuild release APK (requires signing)
./gradlew bundleReleaseBuild Android App Bundle (.aab)
./gradlew cleanDelete all build outputs

Installation Tasks

TaskDescription
./gradlew installDebugInstall debug APK to connected device
./gradlew installReleaseInstall release APK to connected device
./gradlew uninstallAllUninstall app from all connected devices

Testing Tasks

TaskDescription
./gradlew testRun unit tests
./gradlew connectedAndroidTestRun instrumented tests on device
./gradlew lintRun Android Lint checks

Utility Tasks

TaskDescription
./gradlew dependenciesShow dependency tree
./gradlew tasksList all available tasks
./gradlew --statusShow Gradle daemon status
./gradlew --stopStop Gradle daemon

Next Steps

Architecture

Understand the MVVM architecture and Rust FFI integration

Project Structure

Explore the codebase organization and key files

Build docs developers (and LLMs) love