102 lines
3.6 KiB
Markdown
102 lines
3.6 KiB
Markdown
# Upload Android App to Local App Store
|
|
|
|
Follow these steps to add a new Android app to the Local App Store.
|
|
|
|
## Prerequisites
|
|
|
|
- Java 17: `export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64`
|
|
- Android SDK: `export ANDROID_HOME=/home/jarian/android-sdk`
|
|
- Gradle wrapper in your app project (run `gradle wrapper` if missing)
|
|
- Signing keystore: `/home/jarian/playground/app-store/signing/localstore.keystore` (alias `localstore`, password `localstore123`)
|
|
- Server running on port 9800
|
|
|
|
## Step 1: Build the APK
|
|
|
|
```bash
|
|
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
|
|
export ANDROID_HOME=/home/jarian/android-sdk
|
|
cd /path/to/your/app/project
|
|
./gradlew :app:assembleRelease
|
|
```
|
|
|
|
The signed release APK will be at `app/build/outputs/apk/release/app-release.apk`.
|
|
|
|
## Step 2: Copy APK to repos
|
|
|
|
```bash
|
|
cp app/build/outputs/apk/release/app-release.apk /home/jarian/playground/app-store/server/repos/<app_id>.apk
|
|
```
|
|
|
|
Use a lowercase, hyphen-separated ID (e.g., `myapp`, `hello-world`).
|
|
|
|
## Step 3: Create metadata JSON
|
|
|
|
Create `<app_id>.json` in the repos directory alongside the APK:
|
|
|
|
```json
|
|
{
|
|
"name": "App Display Name",
|
|
"description": "One or two sentences describing the app.",
|
|
"icon": null,
|
|
"screenshots": [],
|
|
"package_name": "com.your.package",
|
|
"version_name": "1.0",
|
|
"version_code": "1",
|
|
"min_sdk": "26",
|
|
"target_sdk": "34",
|
|
"permissions": ["android.permission.INTERNET"]
|
|
}
|
|
```
|
|
|
|
**Field notes:**
|
|
- `name`: Human-readable display name
|
|
- `description`: Short description shown in the store
|
|
- `icon`: `null` if no PNG icon in the APK, otherwise the resource path (e.g., `res/drawable-mdpi/ic_launcher.png`)
|
|
- `screenshots`: Array of screenshot filenames, or `[]` if none
|
|
- `package_name`: From `AndroidManifest.xml` or `build.gradle`
|
|
- `version_name` / `version_code`: From `build.gradle` `defaultConfig`
|
|
- `min_sdk` / `target_sdk`: From `build.gradle` `defaultConfig`
|
|
- `permissions`: Array of `<uses-permission>` entries from `AndroidManifest.xml`
|
|
|
|
## Step 4: Trigger server scan
|
|
|
|
```bash
|
|
curl -X POST http://localhost:9800/api/scan
|
|
```
|
|
|
|
Or restart the server if preferred:
|
|
|
|
```bash
|
|
screen -S appstore -X quit 2>/dev/null
|
|
sleep 1
|
|
screen -dmS appstore bash -c "cd /home/jarian/playground/app-store/server && source venv/bin/activate && python -c 'import uvicorn, sys; sys.path.insert(0, \".\"); from main import app; uvicorn.run(app, host=\"0.0.0.0\", port=9800)'"
|
|
```
|
|
|
|
## Step 5: Verify
|
|
|
|
```bash
|
|
curl -s http://localhost:9800/api/apps | python3 -c "
|
|
import json, sys
|
|
data = json.load(sys.stdin)
|
|
print(f'Total: {data[\"total\"]} apps')
|
|
for app in data['apps']:
|
|
print(f' - {app[\"name\"]} (v{app[\"version_name\"]}, pkg={app[\"package_name\"]})')
|
|
"
|
|
```
|
|
|
|
## Optional: Add to downloads directory
|
|
|
|
For easy browser download via `/dl/` endpoint:
|
|
|
|
```bash
|
|
cp app/build/outputs/apk/release/app-release.apk /home/jarian/playground/app-store/server/downloads/<app_id>.apk
|
|
```
|
|
|
|
## Common Issues
|
|
|
|
- **Binary XML manifest parsing**: The scanner reads APKs directly without `aapt`. Fields like `version_name` may show `unknown` if the string parser misses them — always set them in the JSON override.
|
|
- **No PNG icon**: If the APK only has XML vector drawables, set `"icon": null` in the JSON.
|
|
- **KSP plugin**: Required for Room. Keep only in `app/build.gradle`, not root `build.gradle`.
|
|
- **Navigation**: Use `<fragment>` tag (not `FrameLayout`) with `android:name="androidx.navigation.fragment.NavHostFragment"`, or add NavHostFragment programmatically in MainActivity.
|
|
- **Data binding**: Cannot create typed properties for `<fragment>` tags. Use programmatic NavHostFragment instead.
|
|
- **Lint**: Set `checkReleaseBuilds false` to avoid blocking builds. |