simple_eif_phone

Write an Android app in Eiffel, and get a signed APK from one command.

MIT License Android 8.0 or later Design by Contract

The layers

 your app (Eiffel)
      |
 SIMPLE_EIF_PHONE   events, lifecycle, touches, screen, metrics, storage, assets, log
      |
 PHONE_NATIVE       the only class that calls C
      |
 runtime/c          sephone glue + Android's native_app_glue
      |
 Android            NativeActivity

The model classes (PHONE_LIFECYCLE, PHONE_TOUCHES, PHONE_EVENT) use no C, so their contracts and tests run on a PC too.

How a build works

 Eiffel --gec--> C --NDK clang--> one .so per processor type
                                      |
                 aapt2 + aapt --> APK --> zipalign (16 KB pages) --> apksigner

gec runs with --cc=no --finalize. A C file whose hash hasn't changed isn't recompiled. No compiler change was needed: gec's C compiled for Android as it stands.

Design decisions

Eiffel owns the loop

There are no callbacks into Eiffel. Android's events wait in a queue, and the app pulls them with wait_for_event or poll_event. A screen with a window and a lifecycle with a window always agree, because one command is applied per poll.

The Back key is decided ahead of time

With no callbacks, the app can't answer "did you handle this?" when Back arrives. So it sets a policy first.

Self-drawn UI

Apps draw their own pixels and hand them over with present_argb. Java stays out of the way: a small fixed helper is there only for what Android offers nowhere else.

A fast setjmp

On Android, setjmp saves the signal mask, which is a system call. gec's C uses it in every assertion block and rescue. runtime/c/sephone_fastjmp.h maps it to _setjmp for every phone build.

One Eiffel system per process

Android can start a new activity in a process while the old one is ending. A second Eiffel system would overwrite the first one's state and abort in the garbage collector. So the first main claims the process. A later one waits up to 2 seconds, then ends the process, and Android starts the app fresh.

Clean process end

The app ends with fflush and _exit, not exit, because exit handlers can race Android's own threads.

Release passwords

A release password reaches apksigner only through an environment variable. The contracts on EIFPHONE_KEYSTORE forbid every other route.