3.1 KiB
3.1 KiB
Architecture: Telefon (Android, ohne Google)
Same conventions as the other apps. No network permission. The app owns almost no data: it reads the system call log and contacts.
Stack
| Schicht | Wahl | warum |
|---|---|---|
| UI | Kotlin + Compose, M3 Expressive, dynamic colour | same as the others |
| Telefonie | RoleManager.ROLE_DIALER + own InCallService (BIND_INCALL_SERVICE, IN_CALL_SERVICE_UI) |
the only official way to show the call UI and control calls |
| Anrufen | TelecomManager.placeCall |
uses the default SIM/phone account, works for emergency numbers through the system |
| Daten | CallLog.Calls and ContactsContract via ContentResolver, observed with ContentObserver → Flow |
no copy of personal data in our database |
| Eigene Daten | DataStore (quick replies, theme) | – |
| Audio | InCallService.setMuted / setAudioRoute, CallEndpoint on API 34+ |
speaker, earpiece, Bluetooth |
| Näherungssensor | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK while the earpiece is active |
screen off at the ear |
Permissions
READ_CALL_LOG, WRITE_CALL_LOG (delete entries), READ_CONTACTS, CALL_PHONE, READ_PHONE_STATE, MANAGE_OWN_CALLS no, USE_FULL_SCREEN_INTENT, POST_NOTIFICATIONS, WAKE_LOCK, SEND_SMS no (quick replies hand off to the SMS app with smsto:).
The dialer role grants most of these automatically once the user accepts it.
Data
No schema. Own state in DataStore only. Access: single user; the system enforces the permissions.
Interne API
| Aufruf | macht | Flow |
|---|---|---|
CallLogRepo.observe(filter) |
query CallLog, join contact name/photo by number (PhoneLookup), group by day | F01 |
ContactsRepo.favorites() / search(q) / t9(digits) |
starred contacts; name/number search; T9 digit match on names and numbers | F02, F03, F06 |
Dialer.call(number) |
placeCall(tel:) |
F01–F03 |
CallManager (in InCallService) |
StateFlow of calls; answer, reject (with SMS), hold, unhold, mute, route, DTMF, disconnect | F04, F05, F07 |
Role.request() |
role request intent | F08 |
Was beißt
- Wrong default dialer state: without the role, calls still work through the system dialer; the app shows a banner instead of failing.
- Lock screen: incoming UI via full-screen-intent notification;
showWhenLocked+turnScreenOnon the activity. - Ringtone: the system rings for the default dialer? No: the InCallService app must play the ringtone itself only when
Call.Detailssay so; on modern Android the platformRingerplays it for the default dialer. We do not play our own. - Process death mid-call: the InCallService is bound by the system as long as calls exist; UI state is rebuilt from
calls. - Emergency numbers: always via
placeCall, never blocked by our UI. - Privacy: no network, no analytics; call log stays in the system.
Build-Reihenfolge
- Slice: role request, InCallService, incoming + in-call screens, place a call from the keypad.
- Must: call log with grouping and call back, favourites, search, notifications, mute/speaker/DTMF, proximity.
- Should: filters, T9, hold, call waiting, quick reply SMS, details screen, voicemail, Bluetooth.