feat: Add Android build support

This commit is contained in:
Forte11Cuba
2026-02-06 17:32:57 -06:00
parent 9691dda1bc
commit db2f393ff0
10 changed files with 161 additions and 86 deletions
+86 -14
View File
@@ -69,7 +69,7 @@ Cashu is an ecash protocol that enables Bitcoin transactions with maximum privac
## 🔧 Technologies
### Frontend
- **Flutter 3.3+**: Cross-platform framework
- **Flutter 3.27+**: Cross-platform framework
- **Dart**: Programming language
- **Provider**: State management
- **QR Flutter**: QR code generation
@@ -90,10 +90,11 @@ Cashu is an ecash protocol that enables Bitcoin transactions with maximum privac
### Prerequisites
- Flutter SDK (>=3.3.0)
- Dart SDK
- Android Studio / Xcode (for native builds)
- Rust toolchain (to compile cdk-flutter)
- Flutter SDK (>=3.27.0)
- Dart SDK (>=3.6.0)
- Android Studio with Android SDK
- Android NDK 26.3+ (install via Android Studio > SDK Manager > SDK Tools)
- Rust toolchain (>=1.85.0)
### Clone the Repository
@@ -108,19 +109,74 @@ cd elcaju
flutter pub get
```
### Configure Rust (Ubuntu/Linux)
### Configure Rust for Android (Linux/macOS)
```bash
# Install Android targets
rustup target add armv7-linux-androideabi
rustup target add aarch64-linux-android
rustup target add i686-linux-android
rustup target add x86_64-linux-android
# Install Rust if not already installed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Create ~/.cargo/config.toml
# Update to latest stable (requires >= 1.85.0)
rustup update stable
# Install Android targets
rustup target add aarch64-linux-android # arm64-v8a (modern devices)
rustup target add armv7-linux-androideabi # armeabi-v7a (older devices)
rustup target add x86_64-linux-android # x86_64 (emulators)
```
### Configure Android NDK Linkers
Create or edit `~/.cargo/config.toml` with your NDK path:
```toml
[target.x86_64-unknown-linux-gnu]
linker = "gcc"
rustflags = ["-C", "link-arg=-fuse-ld=bfd"]
[target.aarch64-linux-android]
linker = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"
[target.armv7-linux-androideabi]
linker = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang"
[target.x86_64-linux-android]
linker = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang"
[env]
CC_armv7-linux-androideabi = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang"
AR_armv7-linux-androideabi = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
CC_x86_64-linux-android = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android24-clang"
AR_x86_64-linux-android = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
CC_aarch64-linux-android = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"
AR_aarch64-linux-android = "/path/to/Android/Sdk/ndk/26.3.11579264/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
```
> **Note**: Replace `/path/to/Android/Sdk` with your actual Android SDK path (usually `~/Android/Sdk` on Linux or `~/Library/Android/sdk` on macOS).
### Compile Native Libraries
The cdk_flutter native libraries must be compiled manually:
```bash
# Navigate to cdk_flutter rust directory
cd ~/.pub-cache/git/cdk_flutter-*/rust
# Build for each architecture
cargo build --release --target aarch64-linux-android
cargo build --release --target armv7-linux-androideabi
cargo build --release --target x86_64-linux-android
# Copy libraries to project
mkdir -p /path/to/elcaju/android/app/src/main/jniLibs/{arm64-v8a,armeabi-v7a,x86_64}
cp target/aarch64-linux-android/release/libcdk_flutter.so \
/path/to/elcaju/android/app/src/main/jniLibs/arm64-v8a/
cp target/armv7-linux-androideabi/release/libcdk_flutter.so \
/path/to/elcaju/android/app/src/main/jniLibs/armeabi-v7a/
cp target/x86_64-linux-android/release/libcdk_flutter.so \
/path/to/elcaju/android/app/src/main/jniLibs/x86_64/
```
### Run in Development
@@ -132,13 +188,29 @@ flutter run
### Build for Production
```bash
# Android APK
# Android APK (includes all architectures, ~55MB)
flutter build apk --release
# Android App Bundle
# Android App Bundle (recommended for Play Store)
flutter build appbundle --release
```
### Quick Build (arm64 only)
For faster builds targeting only modern devices:
```bash
# Build only arm64 library
cargo build --release --target aarch64-linux-android
# Copy to project
cp target/aarch64-linux-android/release/libcdk_flutter.so \
android/app/src/main/jniLibs/arm64-v8a/
# Build APK (~40MB)
flutter build apk --release
```
---
## 🏗️ Architecture
+41
View File
@@ -0,0 +1,41 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
android {
namespace "me.elcaju"
compileSdk flutter.compileSdkVersion
ndkVersion "27.0.12077973"
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
applicationId "me.elcaju"
minSdk flutter.minSdkVersion
targetSdk flutter.targetSdkVersion
versionCode flutter.versionCode
versionName flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source "../.."
}
-43
View File
@@ -1,43 +0,0 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "me.elcaju"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
defaultConfig {
applicationId = "me.elcaju"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}
+4
View File
@@ -1,4 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Permisos de red requeridos para conectar con mints Cashu -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:label="ElCaju"
android:name="${applicationName}"
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,17 +5,18 @@ allprojects {
}
}
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
def newBuildDir = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
def newSubprojectBuildDir = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
tasks.register("clean", Delete) {
delete rootProject.layout.buildDirectory
}
+25
View File
@@ -0,0 +1,25 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.3" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}
include ":app"
-25
View File
@@ -1,25 +0,0 @@
pluginManagement {
val flutterSdkPath = run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.3" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
}
include(":app")