An open API service indexing awesome lists of open source software.

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

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:

![View, Open in Browser](https://github.com/i-e-b/MiniWeb/raw/main/_docs/view-in-browser-android-studio.png)

## 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.