https://github.com/i-e-b/miniweb
A small framework for building small android apps
https://github.com/i-e-b/miniweb
android css hot-reload html java javascript small web
Last synced: 2 months ago
JSON representation
A small framework for building small android apps
- Host: GitHub
- URL: https://github.com/i-e-b/miniweb
- Owner: i-e-b
- License: bsd-3-clause
- Created: 2022-07-08T12:58:32.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2023-01-30T16:21:06.000Z (over 3 years ago)
- Last Synced: 2025-01-27T12:11:17.214Z (over 1 year ago)
- Topics: android, css, hot-reload, html, java, javascript, small, web
- Language: Java
- Homepage:
- Size: 314 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# MiniWeb
A small framework for building small android apps
## What is it?
A simple set of drivers for the built-in Android WebView that provides
a web-like development environment contained in a single app.
The app uses as much of the built-in Android system features as possible to result
in a small final APK. The app plus example pages comes to around 50KB
when built in release mode.
### Road-map
- [ ] **Overlay** - Draw a new view over the current one. Clicking outside of the new view, or clicking 'back' reloads the original view without the overlay.
- [ ] Implement something big (or at least non-trivial) in this. Add anything found to be missing
- [ ] Hooks for 'wallet' service, hot code loading / live updates.
- [ ] Action and progress controls -- template that replaces with a progress display and triggers a back-end task. Another replacement when task completes.
## How it works
The app is based around a set of self registering "controllers". These are classes
that register a set of web methods. Each method will return the path of a view
template and an optional object used to complete that template.
Note that the web client and app server and tightly coupled 1:1, so you can
get away with directly calling 'server' code from the client in a way you
can't with normal web development.
Urls for the app are in the form `app://{controller}/{method}?param=values`
The app will start in `app://home/index`, which is the same as `app://home`.
Templates should be in `assets/views`, and the file name should end in `.html`.
Each template is a fragment of HTML which will be wrapped in a \ tag and
given a default style sheet.
The default style sheet is in `assets/styles/default.css`
## Calling JavaScript
JavaScript is enabled on the web view, and should work as normal.
It is possible to call directly from JavaScript to the host app. An object called `manager` is
available to all scripts. This exposes any methods in the `JsCallbackManager` class which
are decorated with the `@JavascriptInterface` annotation.
There are some limitations around the kind of data that can be passed to `manager`.
It sometimes needs an intermediary call in the page to serialise an object to send back to the app.
(see the 'Forms and parameters' example)
## Templating
The view templates are mostly plain HTML, with the ability to inject values from
the controller method.
Template holes can be put anywhere in a template -- text, tags, scripts, etc.
### Simple values
Values are copied from the model object into 'holes' in the html, which start with `<_>` and end with ``.
For example, with a model containing `public String greeting = "hello";` and a template with
`
<_>greeting world
`, then the final result is `hello world
`
Note: the field name used with a template hole is case sensitive, and must be a field on the model,
not a function or method.
For injection in other HTML tags and attributes, and for injecting into `` tags,
you can use <code>`_$`modelField`$_`</code>. This only does simple replacements, and can't
do any logic, repetition, or sub-views.
### Complex values
You can reach further into an object hierarchy with a dotted path. See the 'templating' demo page for
examples. It's generally better to restructure your model instead.
### Looping and Conditional output
You can use a pair of <code>`<_for model_field>`</code> and <code>`</_for>`</code> to
enclose a block of HTML.
* If the `model_field` is a boolean value, the block will be displayed once, and only if the value is `true`
* If the `model_field` is a list or array, the block will repeat for each item
* For any other value, the block will be displayed once, and only if the value is not `null`
Inside a loop, you can use <code>`<_>#.`loopItem`</_>`</code> to read values from each item.
You can loop or use a conditional block with a child item. For example:
```
<_for people>
<p>Dear <_>#.name</_>, we are writing regarding account <_>#.accountNumber</_>...</p>
</_for>
```
### Nesting loops
You can put a `<_for ...>` loop inside another.
You can loop over an item in a loop using `<_for #.item>`
```
<_for accounts>
<p><_>#.userName</_> has these items</p>
<ol>
<_for #.basketItems>
<li><_>#.name</_> x <_>#.quantity</_></li>
</_for>
</ol>
</_for>
```
## Editing HTML
If you use Android Studio, some basic HTML editing tools are available.
You might want to use a different one of the IntelliJ suite of tools for better support.
As well as 'hot reload' described below, you can open a HTML page in your browser for basic design
using `View` > `Open in Browser` in the Android Studio main menu:

## Emulator Host and Hot Reload
MiniWeb supports "hot-reload" of pages and assets when running under an emulator
(i.e. during development). You need to run the Emulator Host tool (`TinyWebHook`)
or a similar compatible service.
If you want to connect to the hot-reload service from a real device, you will need
to have an active `adb` connection, and ensure port `1310` is 'reversed'.
This can be done with `adb reverse --no-rebind tcp:1310 tcp:1310`.
The `adb` tool is installed to `C:\Users\{user}\AppData\Local\Android\Sdk\platform-tools`
if using Android Studio for Windows.
The Emulator Host tool **must** be running when your app first starts, otherwise
the hot-reload system will be disabled.
If that is working correctly, changes to files in the `assets` folder will be
monitored, and if any files being used by the current page (including linked
resources) will cause the page to refresh with the updated resources.
Note: the controller is not called during hot-reload. The template model used
to render the page is kept to allow redraw without calling the controller.
This means that any external effects of your page (like reading from, *or* writing
to, a database) will not be repeated for a hot-reload.
The Android Emulator connects to the host over IP address `10.0.2.2`.
The MiniWeb class at `e.s.miniweb.core.EmulatorHostCall` has a few methods to make
HTTP calls to the host over this address (with very short connection timeout, so
that failures don't pause the app significantly).
If there is a HTTP server listening on port `1310`, MiniWeb will try to communicate
with it using a very simple protocol.
### TinyWebHook
There is a `TinyWebHook` dotnet app that supports the MiniWeb Hot-Host Protocol.
`TinyWebHook` also supports a `/` path for test use.
This must be run with administrator access under Windows, or with http binding
access on other systems (`root` should be ok for development).
Call `TinyWebHook` with the path to your Android app's `assets` folder.
(e.g. `C:\gits\MiniWeb\app\src\main\assets`)
### Hot-Host Protocol
#### Version
```
http://10.0.2.2:1310/host
```
This should return `ANDROID_EMU_HOST_V1`; If this path
fails or returns a different value, Hot Reload will **not** be active.
This is agreed in code at `e.s.miniweb.core.EmulatorHostCall#HOST_UP_MSG` and `TinyWebHook.Program.HostUpMsg`
#### Time
```
http://10.0.2.2:1310/time
```
This should return the current server time as **UTC**
in the format `yyyy-MM-dd HH:mm:ss`.
#### Assets
```
http://10.0.2.2:1310/assets/{path to asset}
```
This should return the file contents for the asset requested. The path is allowed
to be any path into the assets folder.
The path may **not** contain `..` or `.` elements.
* If the host returns a 200 status, the content will be used instead of the content in the APK of the running Android app.
* If the host returns a 404 status, the file will be treated as removed, regardless if its presence in the APK.
* If the host returns any other status, the file will be loaded from the APK as normal.
#### Last touch
```
http://10.0.2.2:1310/touched/{path to asset}
```
This should return the modified date of the file requested.
The Android app will request and store this when a file is loaded through the host, and
will periodically request again while the page is being displayed.
* If the host returns 200, and the date has **not** changed, the Android app takes no action
* If the host returns 200, and the date **has** changed, the Android app will try to reload the current page with existing data on the updated template
* If the host returns any other code, the Android app takes no action.
#### Last page push
```
http://10.0.2.2:1310/push
```
The Android app should `POST` to this when it renders a page.
The Emulator Host will then make this available on the host machine
#### Last page get
```
http://127.0.0.1:1310/get
```
Returns the body of the last page that was pushed by the Android app.
If nothing has been pushed yet, the page will be blank
## Other bits
Test cert jks password: `deploy.jks`
Do **not** use this certificate for your app, it is public and should only be used for testing.