mirror of
git://f0xx.org/android_cast
synced 2026-07-29 04:57:40 +03:00
crash handler snapshot, unverified
This commit is contained in:
26
docs/CRASH_REPORTER.md
Normal file
26
docs/CRASH_REPORTER.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Anonymous crash reporter
|
||||
|
||||
## Android
|
||||
|
||||
- **Main process:** `CrashReporter.install()` — Java uncaught exceptions → JSON under `files/crash_reports/pending/`, session stats flushed with `globals.reason: "crash"`.
|
||||
- **Watcher process:** `CrashWatcherService` in `:crashwatcher` — reads `settings.json` → `crash`, uploads pending reports, ingests native stub files.
|
||||
- **Native:** `crash_hook.c` (unwind + `dladdr`) writes stubs to `crash_reports/native/`; watcher converts to schema v1 JSON.
|
||||
- **User toggle:** Settings drawer → **Send anonymous crash logs** (`AppPreferences.send_anonymous_crash_logs`, default on).
|
||||
|
||||
Deploy tuning via app-private `files/settings.json` (see `examples/settings.json`):
|
||||
|
||||
```json
|
||||
"crash": {
|
||||
"enabled": "true",
|
||||
"upload_url": "https://f0xx.org/app/androidcast_project/crashes/api/upload.php",
|
||||
"prune_after_upload": "true",
|
||||
"upload_interval": "5m",
|
||||
"max_pending": 32
|
||||
}
|
||||
```
|
||||
|
||||
## Backend
|
||||
|
||||
PHP console and ingest API: `examples/crash_reporter/backend/` — see [README](../examples/crash_reporter/backend/README.md).
|
||||
|
||||
Roadmap: `examples/crash_reporter/ROADMAP.md`.
|
||||
118
docs/OTA.md
Normal file
118
docs/OTA.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Over-the-air (OTA) updates — deployment schema **v0**
|
||||
|
||||
The app checks a **stable channel URL**, follows it to a per-build manifest, then downloads the APK. Version comparison uses **`major.minor.build`** (packed into Android `versionCode` at build time). Deploy never computes `versionCode` by hand.
|
||||
|
||||
The client runs checks and downloads in **`OtaUpdateService`** (a standalone `Service`, not embedded in cast/receiver services). Launch checks enqueue work there; APK download uses a **foreground service** (`dataSync`) with a progress notification.
|
||||
|
||||
MQTT is fully supported for OTA sources using retained topic payloads (`mqtt://...` / `mqtts://...`). The URI path is treated as the exact topic to subscribe.
|
||||
|
||||
## URL layout
|
||||
|
||||
```text
|
||||
https://host/v0/ota/channel/stable.json
|
||||
https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}.otapkg
|
||||
https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}_sign.json
|
||||
https://host/v0/ota/00/00.{major}/00.{major}.{minor}/android_cast_00.{major}.{minor}.{build}_manifest.json
|
||||
```
|
||||
|
||||
- **`v0`** — deployment schema version (default channel).
|
||||
- **`00`** after `ota/` — OTA payload format revision within v0.
|
||||
- Components are **zero-padded to 2 digits** in paths and filenames (`00.01.05`).
|
||||
|
||||
## Versioning
|
||||
|
||||
In `app/build.gradle` (overridable via `local.properties`):
|
||||
|
||||
```properties
|
||||
ota.major=0
|
||||
ota.minor=1
|
||||
ota.build=0
|
||||
```
|
||||
|
||||
Packed rule (each part 0–99):
|
||||
|
||||
```text
|
||||
versionCode = major * 10000 + minor * 100 + build
|
||||
```
|
||||
|
||||
Example: `0.1.5` → `versionCode` **105**.
|
||||
|
||||
## JSON files
|
||||
|
||||
**`v0/ota/channel/stable.json`**
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "v0",
|
||||
"manifestUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05_manifest.json"
|
||||
}
|
||||
```
|
||||
|
||||
**`*_manifest.json`**
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "v0",
|
||||
"major": 0,
|
||||
"minor": 1,
|
||||
"build": 5,
|
||||
"versionName": "0.1.5",
|
||||
"apkUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05.otapkg",
|
||||
"signUrl": "https://host/v0/ota/00/00.01/00.01.05/android_cast_00.01.05_sign.json",
|
||||
"mandatory": false,
|
||||
"releaseNotes": ""
|
||||
}
|
||||
```
|
||||
|
||||
**`*_sign.json`**
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "v0",
|
||||
"sha256": "…"
|
||||
}
|
||||
```
|
||||
|
||||
The app loads `sha256` from `sign.json` when the manifest omits it.
|
||||
|
||||
## MQTT transport
|
||||
|
||||
Use the same JSON payload shapes as HTTP, but publish them as **retained** messages on topics that match your URI paths:
|
||||
|
||||
- `mqtt://host:1883/v0/ota/channel/stable.json` -> retained payload is `stable.json` content
|
||||
- `mqtt://host:1883/v0/ota/00/..._manifest.json` -> retained payload is manifest JSON
|
||||
- `mqtt://host:1883/v0/ota/00/..._sign.json` -> retained payload is sign JSON
|
||||
- `mqtt://host:1883/v0/ota/00/...otapkg` -> retained payload is raw APK/otapkg bytes
|
||||
|
||||
When `ota.trusted=true` and build is debug, strict checksum/sign enforcement is relaxed for that source. Release builds always remain strict.
|
||||
|
||||
## Publish from a release APK
|
||||
|
||||
```bash
|
||||
chmod +x scripts/generate-ota-v0.sh
|
||||
./scripts/generate-ota-v0.sh app/build/outputs/apk/release/app-release.apk https://your-host:port ./ota-publish
|
||||
```
|
||||
|
||||
Upload the contents of `ota-publish/` to your web root so `https://your-host/v0/ota/...` resolves.
|
||||
|
||||
## App configuration
|
||||
|
||||
**`local.properties`** (not committed):
|
||||
|
||||
```properties
|
||||
ota.channel.url=https://your-host/v0/ota/channel/stable.json
|
||||
ota.major=0
|
||||
ota.minor=1
|
||||
ota.build=0
|
||||
```
|
||||
|
||||
Or set the channel URL under **Developer settings → App updates (OTA)**.
|
||||
|
||||
Legacy `ota.manifest.url` still works as a direct manifest URL fallback.
|
||||
|
||||
## Checklist
|
||||
|
||||
1. Bump `ota.major` / `ota.minor` / `ota.build` (or Gradle defaults).
|
||||
2. Build signed release APK (`versionCode` is derived automatically).
|
||||
3. Run `generate-ota-v0.sh` and upload `v0/ota/**`.
|
||||
4. Confirm `stable.json` points at the new `*_manifest.json`.
|
||||
Reference in New Issue
Block a user