306 lines
8.0 KiB
Markdown
306 lines
8.0 KiB
Markdown
|
|
# Building Release APK
|
||
|
|
|
||
|
|
Guide for building and distributing the Alfred Mobile app for testing on multiple devices.
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
- Android SDK installed: `~/android-dev/android-sdk`
|
||
|
|
- JDK 17: `~/android-dev/jdk-17.0.2`
|
||
|
|
- Keystore for signing (or create new one)
|
||
|
|
|
||
|
|
## Quick Build (Debug APK)
|
||
|
|
|
||
|
|
For testing on your own devices without Play Store distribution:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd ~/.openclaw/workspace/alfred-mobile
|
||
|
|
|
||
|
|
# Build debug APK
|
||
|
|
JAVA_HOME=~/android-dev/jdk-17.0.2 \
|
||
|
|
ANDROID_HOME=~/android-dev/android-sdk \
|
||
|
|
./gradlew assembleDebug
|
||
|
|
|
||
|
|
# APK location:
|
||
|
|
ls -lh app/build/outputs/apk/debug/app-debug.apk
|
||
|
|
```
|
||
|
|
|
||
|
|
**Install on device via ADB:**
|
||
|
|
```bash
|
||
|
|
# Wireless ADB (if already paired)
|
||
|
|
~/android-dev/android-sdk/platform-tools/adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||
|
|
|
||
|
|
# USB ADB (if connected via USB)
|
||
|
|
~/android-dev/android-sdk/platform-tools/adb devices
|
||
|
|
~/android-dev/android-sdk/platform-tools/adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||
|
|
```
|
||
|
|
|
||
|
|
**Transfer APK to another device:**
|
||
|
|
```bash
|
||
|
|
# Copy to accessible location
|
||
|
|
cp app/build/outputs/apk/debug/app-debug.apk ~/app-debug.apk
|
||
|
|
|
||
|
|
# Transfer to phone via:
|
||
|
|
# - USB cable (file transfer)
|
||
|
|
# - Email attachment
|
||
|
|
# - Cloud storage (Dropbox, Google Drive)
|
||
|
|
# - Local HTTP server (python -m http.server)
|
||
|
|
# - ADB over network (if phone and computer on same WiFi)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Release APK (Signed)
|
||
|
|
|
||
|
|
For distribution outside development devices:
|
||
|
|
|
||
|
|
### 1. Create Keystore (One-time)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
keytool -genkey -v \
|
||
|
|
-keystore ~/alfred-mobile-release.keystore \
|
||
|
|
-alias alfred-mobile \
|
||
|
|
-keyalg RSA \
|
||
|
|
-keysize 2048 \
|
||
|
|
-validity 10000
|
||
|
|
|
||
|
|
# Enter password when prompted (save it!)
|
||
|
|
# Fill in organizational details
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Create keystore.properties
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cat > ~/.openclaw/workspace/alfred-mobile/keystore.properties << 'EOF'
|
||
|
|
storePassword=YOUR_KEYSTORE_PASSWORD
|
||
|
|
keyPassword=YOUR_KEY_PASSWORD
|
||
|
|
keyAlias=alfred-mobile
|
||
|
|
storeFile=/home/jknapp/alfred-mobile-release.keystore
|
||
|
|
EOF
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Update build.gradle (if needed)
|
||
|
|
|
||
|
|
The `app/build.gradle.kts` should already have release signing config:
|
||
|
|
|
||
|
|
```kotlin
|
||
|
|
signingConfigs {
|
||
|
|
create("release") {
|
||
|
|
// Read from keystore.properties
|
||
|
|
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||
|
|
if (keystorePropertiesFile.exists()) {
|
||
|
|
val keystoreProperties = Properties()
|
||
|
|
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||
|
|
|
||
|
|
storeFile = file(keystoreProperties["storeFile"] as String)
|
||
|
|
storePassword = keystoreProperties["storePassword"] as String
|
||
|
|
keyAlias = keystoreProperties["keyAlias"] as String
|
||
|
|
keyPassword = keystoreProperties["keyPassword"] as String
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
buildTypes {
|
||
|
|
release {
|
||
|
|
isMinifyEnabled = true
|
||
|
|
proguardFiles(/* ... */)
|
||
|
|
signingConfig = signingConfigs.getByName("release")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Build Release APK
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd ~/.openclaw/workspace/alfred-mobile
|
||
|
|
|
||
|
|
# Build signed release APK
|
||
|
|
JAVA_HOME=~/android-dev/jdk-17.0.2 \
|
||
|
|
ANDROID_HOME=~/android-dev/android-sdk \
|
||
|
|
./gradlew assembleRelease
|
||
|
|
|
||
|
|
# APK location:
|
||
|
|
ls -lh app/build/outputs/apk/release/app-release.apk
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. Verify Signature
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Check if APK is signed
|
||
|
|
~/android-dev/android-sdk/build-tools/*/apksigner verify \
|
||
|
|
--print-certs \
|
||
|
|
app/build/outputs/apk/release/app-release.apk
|
||
|
|
|
||
|
|
# Should show certificate details (not "unsigned")
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing Cross-Device Alarm Dismissal
|
||
|
|
|
||
|
|
### Setup
|
||
|
|
1. **Build APK** (debug or release)
|
||
|
|
2. **Install on tablet**:
|
||
|
|
```bash
|
||
|
|
adb -s adb-R52R30ASB4Y-BIkpas install -r app-debug.apk
|
||
|
|
```
|
||
|
|
3. **Install on phone**:
|
||
|
|
- Transfer APK to phone
|
||
|
|
- Enable "Install from unknown sources" in phone settings
|
||
|
|
- Open APK file and install
|
||
|
|
- OR use `adb install` if phone has ADB enabled
|
||
|
|
|
||
|
|
### Testing Procedure
|
||
|
|
|
||
|
|
See `CROSS_DEVICE_ALARMS.md` for full testing procedure.
|
||
|
|
|
||
|
|
**Quick test:**
|
||
|
|
1. Open Alfred app on both devices
|
||
|
|
2. Authenticate on both (same account)
|
||
|
|
3. Send test alarm:
|
||
|
|
```bash
|
||
|
|
curl -X POST http://localhost:18790/api/notify \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d '{"notificationType":"alarm","title":"Cross-Device Test","message":"Testing sync","priority":"high","sound":true,"vibrate":true}'
|
||
|
|
```
|
||
|
|
4. Verify alarm triggers on both devices
|
||
|
|
5. Dismiss on ONE device
|
||
|
|
6. Verify alarm stops on BOTH devices
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### "Unsigned APK" Error
|
||
|
|
- Make sure keystore.properties exists and has correct paths
|
||
|
|
- Verify keystore file exists at specified location
|
||
|
|
- Check passwords are correct in keystore.properties
|
||
|
|
|
||
|
|
### "Install Failed" on Phone
|
||
|
|
- Enable "Install from unknown sources" or "Allow from this source"
|
||
|
|
- Check Android version compatibility (app requires Android 8.0+)
|
||
|
|
- Uninstall old version first if upgrading
|
||
|
|
|
||
|
|
### ADB Not Detecting Phone
|
||
|
|
- Enable Developer Options on phone (tap Build Number 7 times)
|
||
|
|
- Enable USB Debugging in Developer Options
|
||
|
|
- Accept "Allow USB debugging" prompt on phone
|
||
|
|
- Try `adb kill-server && adb start-server`
|
||
|
|
|
||
|
|
### Different Account/OAuth Issues
|
||
|
|
- Both devices must authenticate with same Authentik account
|
||
|
|
- Check auth.dnspegasus.net is accessible from both devices
|
||
|
|
- Verify OAuth callback is working (alfredmobile://oauth/callback)
|
||
|
|
|
||
|
|
### Alarm Doesn't Sync
|
||
|
|
- Check proxy logs: `tail -f /tmp/alfred-proxy-new.log`
|
||
|
|
- Verify both devices connected: look for "Client WebSocket state: 1"
|
||
|
|
- Check broadcast count matches device count
|
||
|
|
- Test WebSocket with: `adb logcat | grep GatewayClient`
|
||
|
|
|
||
|
|
## Distribution Options
|
||
|
|
|
||
|
|
### For Personal Use (Recommended)
|
||
|
|
- **Debug APK** - No signing needed, install directly on your devices
|
||
|
|
- Works for testing and personal use
|
||
|
|
- Cannot publish to Play Store
|
||
|
|
- Shows "Debug" in app version
|
||
|
|
|
||
|
|
### For Beta Testing
|
||
|
|
- **Release APK (signed)** - Proper signing, can distribute to testers
|
||
|
|
- Upload to Google Play Console (Internal Testing track)
|
||
|
|
- Or distribute directly via email/download link
|
||
|
|
- Users need to enable "Install from unknown sources"
|
||
|
|
|
||
|
|
### For Public Distribution
|
||
|
|
- **Play Store** - Requires Google Play Console account ($25 one-time fee)
|
||
|
|
- Upload signed release APK
|
||
|
|
- Fill in app listing details
|
||
|
|
- Submit for review
|
||
|
|
- Can use internal/alpha/beta/production tracks
|
||
|
|
|
||
|
|
## Build Variants
|
||
|
|
|
||
|
|
### Debug vs Release
|
||
|
|
|
||
|
|
**Debug:**
|
||
|
|
- Faster builds (no minification)
|
||
|
|
- Includes debug symbols
|
||
|
|
- Larger APK size (~25MB)
|
||
|
|
- Shows debug logs
|
||
|
|
- No signing required
|
||
|
|
|
||
|
|
**Release:**
|
||
|
|
- Slower builds (ProGuard minification)
|
||
|
|
- Optimized code
|
||
|
|
- Smaller APK size (~15MB)
|
||
|
|
- No debug logs
|
||
|
|
- Requires signing
|
||
|
|
|
||
|
|
### Build Flavors (if added)
|
||
|
|
|
||
|
|
Could add build flavors for:
|
||
|
|
- `dev` - Development (points to localhost)
|
||
|
|
- `staging` - Staging environment
|
||
|
|
- `production` - Production (alfred-app.dnspegasus.net)
|
||
|
|
|
||
|
|
Currently using single flavor with environment-based config.
|
||
|
|
|
||
|
|
## Version Management
|
||
|
|
|
||
|
|
Update version in `app/build.gradle.kts`:
|
||
|
|
|
||
|
|
```kotlin
|
||
|
|
android {
|
||
|
|
defaultConfig {
|
||
|
|
versionCode = 2 // Increment for each release
|
||
|
|
versionName = "1.0.1" // User-visible version
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Version naming:**
|
||
|
|
- Major.Minor.Patch (e.g., 1.0.1)
|
||
|
|
- versionCode must increment for Play Store updates
|
||
|
|
- versionName is display-only
|
||
|
|
|
||
|
|
## Useful Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Clean build
|
||
|
|
./gradlew clean
|
||
|
|
|
||
|
|
# Build all variants
|
||
|
|
./gradlew build
|
||
|
|
|
||
|
|
# Run tests
|
||
|
|
./gradlew test
|
||
|
|
|
||
|
|
# Check for outdated dependencies
|
||
|
|
./gradlew dependencyUpdates
|
||
|
|
|
||
|
|
# List all tasks
|
||
|
|
./gradlew tasks
|
||
|
|
|
||
|
|
# Analyze APK size
|
||
|
|
~/android-dev/android-sdk/build-tools/*/apkanalyzer apk summary app-debug.apk
|
||
|
|
```
|
||
|
|
|
||
|
|
## Security Notes
|
||
|
|
|
||
|
|
- **Never commit keystore or keystore.properties to git**
|
||
|
|
- Add to `.gitignore`: `*.keystore`, `keystore.properties`
|
||
|
|
- Back up keystore securely (losing it means no updates to app)
|
||
|
|
- Use strong passwords for keystore
|
||
|
|
- Keep keystore password in password manager
|
||
|
|
|
||
|
|
## Next Steps After Building
|
||
|
|
|
||
|
|
1. Install on multiple devices
|
||
|
|
2. Test cross-device alarm dismissal
|
||
|
|
3. Test in different network conditions (WiFi, mobile data)
|
||
|
|
4. Verify OAuth flow works on all devices
|
||
|
|
5. Check battery usage over extended period
|
||
|
|
6. Test alarm reliability overnight
|
||
|
|
|
||
|
|
## Support
|
||
|
|
|
||
|
|
See also:
|
||
|
|
- `CROSS_DEVICE_ALARMS.md` - Cross-device testing guide
|
||
|
|
- `ARCHITECTURE.md` - System architecture overview
|
||
|
|
- `README.md` - General app documentation
|
||
|
|
- Official Android docs: https://developer.android.com/studio/publish
|