Compare commits
10 commits
f817f61876
...
f83bf386cd
Author | SHA1 | Date | |
---|---|---|---|
f83bf386cd | |||
b8dbee59ad | |||
be0786db68 | |||
444b92d1e7 | |||
03c0ec74c0 | |||
ba9d3ebca2 | |||
51b333c3d7 | |||
f9302f11a7 | |||
e6df08287e | |||
911170325e |
7 changed files with 128 additions and 66 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,8 +1,6 @@
|
||||||
/Dockerfile
|
/Dockerfile
|
||||||
/app/result
|
|
||||||
/app/result/*
|
/app/result/*
|
||||||
/app/obj
|
|
||||||
/app/obj/*
|
/app/obj/*
|
||||||
/app/bin
|
!/app/obj/.gitkeep
|
||||||
/app/bin/*
|
|
||||||
/app/app.apk
|
/app/app.apk
|
||||||
|
/app/Makefile.app-config
|
||||||
|
|
|
@ -8,31 +8,21 @@ test -f app-config.sh && {
|
||||||
echo "package $APP_PACKAGE;"
|
echo "package $APP_PACKAGE;"
|
||||||
|
|
||||||
cat << 'APPACTIVITYJAVA'
|
cat << 'APPACTIVITYJAVA'
|
||||||
|
|
||||||
import android.provider.Settings ;
|
import android.provider.Settings ;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Base64;
|
|
||||||
import java.util.Objects;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.text.method.ScrollingMovementMethod;
|
|
||||||
import android.view.*;
|
|
||||||
//import android.view.MenuItem;
|
//import android.view.MenuItem;
|
||||||
import android.view.ViewGroup.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
// for WebView,WebMessage,WebMessagePort,
|
||||||
//import android.widget.Toast;
|
|
||||||
//import android.widget.TextView;
|
|
||||||
import android.webkit.*;
|
import android.webkit.*;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
//import android.webkit.WebView;
|
|
||||||
//import android.webkit.WebMessage;
|
|
||||||
//import android.webkit.WebMessagePort;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,6 +60,9 @@ public class AppActivity extends Activity {
|
||||||
myWebSettings.setBuiltInZoomControls(true);
|
myWebSettings.setBuiltInZoomControls(true);
|
||||||
myWebSettings.setDisplayZoomControls(false);
|
myWebSettings.setDisplayZoomControls(false);
|
||||||
myWebSettings.setJavaScriptEnabled(true);
|
myWebSettings.setJavaScriptEnabled(true);
|
||||||
|
myWebSettings.setDomStorageEnabled(true);
|
||||||
|
myWebSettings.setDatabaseEnabled(true);
|
||||||
|
myWebSettings.setDatabasePath("/data/data/" + myWebView.getContext().getPackageName() + "/databases/");
|
||||||
myWebView.addJavascriptInterface(this, "myJavaScriptInterface");
|
myWebView.addJavascriptInterface(this, "myJavaScriptInterface");
|
||||||
// load the html from assets file
|
// load the html from assets file
|
||||||
String html = readFileFromAssets("index.html");
|
String html = readFileFromAssets("index.html");
|
||||||
|
@ -85,4 +78,3 @@ public class AppActivity extends Activity {
|
||||||
return "this is good";
|
return "this is good";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
APPACTIVITYJAVA
|
|
||||||
|
|
|
@ -13,11 +13,21 @@ test -n "$LINES" || {
|
||||||
test -n "$LINES" || {
|
test -n "$LINES" || {
|
||||||
read -r LINES COLUMNS < <(stty size)
|
read -r LINES COLUMNS < <(stty size)
|
||||||
}
|
}
|
||||||
test -n "$LINES" || {
|
|
||||||
|
|
||||||
|
test -z "$LINES" && {
|
||||||
LINES=25
|
LINES=25
|
||||||
COLUMS=80
|
}
|
||||||
|
test "$LINES" -lt "16" && {
|
||||||
|
LINES=16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test -z "$COLUMNS" && {
|
||||||
|
COLUMNS=80
|
||||||
|
}
|
||||||
|
test "$COLUMNS" -lt "36" && {
|
||||||
|
COLUMNS=36
|
||||||
|
}
|
||||||
|
|
||||||
type whiptail &>/dev/null && {
|
type whiptail &>/dev/null && {
|
||||||
ECHO(){
|
ECHO(){
|
||||||
|
|
88
app/Makefile
88
app/Makefile
|
@ -1,51 +1,64 @@
|
||||||
SHELL=/bin/bash
|
.ONESHELL:
|
||||||
|
|
||||||
|
SHELL=/bin/makefile-bash-wrapper.sh
|
||||||
|
|
||||||
|
# the include of the Makefile.app-config defines the Makefile
|
||||||
|
# variables $(BUILDTOOLS), $(ANDROID_JAR) and $(PACKAGE)
|
||||||
|
# which depend on the configuration and are necessary to have the Makefile work
|
||||||
|
# the rule whose target is Makefile.app-config will trigger a reload of this include as ncessary
|
||||||
|
# (as explained https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#include)
|
||||||
|
include Makefile.app-config
|
||||||
|
|
||||||
# symlink
|
# symlink
|
||||||
./app.apk: ./result/app.apk
|
./app.apk: ./result/app.apk
|
||||||
ln -sfrv ./result/app.apk ./app.apk
|
ln -sfrv ./result/app.apk ./app.apk
|
||||||
|
|
||||||
# zipalign and sign again (second signing)
|
# zipalign and sign again (second signing)
|
||||||
./result/app.apk : ./result/signed.apk app-config.sh
|
./result/app.apk : ./result/signed.apk app-config.sh ./keystore
|
||||||
source app-config.sh; $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)/zipalign -v -f 4 $< $@
|
$(BUILDTOOLS)/zipalign -v -f 4 $< $@
|
||||||
source app-config.sh; $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)/apksigner sign \
|
$(BUILDTOOLS)/apksigner sign --ks keystore --key-pass pass:armena --ks-pass pass:armena $@
|
||||||
--ks ToyKey.keystore --key-pass pass:armena --ks-pass pass:armena $@
|
|
||||||
|
|
||||||
# sign the apk file (first sign)
|
# sign the apk file (first sign)
|
||||||
./result/signed.apk : ./result/unsigned.apk ./ToyKey.keystore ./result
|
./result/signed.apk : ./result/unsigned.apk ./keystore
|
||||||
jarsigner -verbose -keystore ./ToyKey.keystore -storepass armena -keypass armena -signedjar $@ $< helljniKey
|
jarsigner -verbose -keystore ./keystore -storepass armena -keypass armena -signedjar $@ $< helljniKey
|
||||||
|
|
||||||
# make a "keystore" for the cryptographic signing stuff
|
# make a "keystore" for the cryptographic signing stuff
|
||||||
./ToyKey.keystore :
|
./keystore :
|
||||||
keytool -genkeypair -validity 1000 -dname "CN=alexander,O=Android,C=JPN" -keystore $@ \
|
keytool -genkeypair -validity 1000 -dname "CN=alexander,O=Android,C=JPN" -keystore $@ \
|
||||||
-storepass armena -keypass armena -alias helljniKey -keyalg RSA -v
|
-storepass armena -keypass armena -alias helljniKey -keyalg RSA -v
|
||||||
|
|
||||||
# aapt "package" together the dalvik/hex stuff (and "assets" and "res")
|
# aapt "package" together the dalvik/hex stuff (and "assets" and "res")
|
||||||
./result/unsigned.apk : ./bin/classes.dex ./result ./assets ./bin ./AndroidManifest.xml
|
./result/unsigned.apk : ./result/bin/classes.dex ./assets ./AndroidManifest.xml
|
||||||
rm -rvf "$@"
|
rm -rvf "$@"
|
||||||
source app-config.sh; $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)/aapt package \
|
$(BUILDTOOLS)/aapt package \
|
||||||
-v -u -f -M ./AndroidManifest.xml -S ./res \
|
-v -u -f -M ./AndroidManifest.xml -S ./res \
|
||||||
-I $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.platforms.version.current)/android.jar -A ./assets -F $@ ./bin
|
-I $(ANDROID_JAR) -A ./assets -F $@ ./result/bin
|
||||||
|
|
||||||
# convert "java class"es files (i.e bytecode to dalvic/d8 android thing
|
# convert "java class"es files (i.e bytecode) to dalvic/d8 android thing
|
||||||
./bin/classes.dex : ./obj/package ./obj/package/AppActivity.class ./bin
|
./result/bin/classes.dex : ./obj/$(PACKAGE)/AppActivity.class
|
||||||
ls ./obj/package/*.class
|
mkdir -p ./result/bin
|
||||||
source app-config.sh; $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)/d8 $$(realpath --relative-to=. $<)/*.class \
|
$(BUILDTOOLS)/d8 ./obj/$(PACKAGE)/*.class \
|
||||||
--lib $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.platforms.version.current)/android.jar --output bin
|
--lib $(ANDROID_JAR) --output ./result/bin
|
||||||
|
|
||||||
# compile (javac) the class from
|
# compile (javac) the class from
|
||||||
./obj/package/AppActivity.class : ./src/package/AppActivity.java ./src/package/R.java ./obj/package
|
./obj/$(PACKAGE)/AppActivity.class : ./src/$(PACKAGE)/AppActivity.java ./src/$(PACKAGE)/R.java
|
||||||
javac -d ./obj -classpath $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.platforms.version.current)/android.jar \
|
mkdir -p ./obj/$(PACKAGE)
|
||||||
-sourcepath ./src $$(realpath --relative-to=/src $<)
|
javac -d ./obj -classpath $(ANDROID_JAR) -sourcepath ./src $<
|
||||||
|
|
||||||
# generate teh AppActivity.java (template)
|
|
||||||
./src/package/AppActivity.java: ./src/package app-config.sh
|
|
||||||
./.Makefile.scripts/make--AppActivity.java.sh > $@
|
|
||||||
|
|
||||||
# make the resources "R.java" thing
|
# make the resources "R.java" thing
|
||||||
./src/package/R.java : $(shell find ./res -type f) app-config.sh ./src/package ./AndroidManifest.xml ./android-sdk/installed
|
./src/$(PACKAGE)/R.java : $(shell find ./res -type f) app-config.sh ./AndroidManifest.xml ./android-sdk/installed | ./src/$(PACKAGE)
|
||||||
source app-config.sh; $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)/aapt package \
|
$(BUILDTOOLS)/aapt package \
|
||||||
-v -f -m -S ./res -J ./src -M ./AndroidManifest.xml \
|
-v -f -m -S ./res -J ./src -M ./AndroidManifest.xml \
|
||||||
-I $${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.platforms.version.current)/android.jar
|
-I $(ANDROID_JAR)
|
||||||
|
|
||||||
|
# generate the AppActivity.java (template
|
||||||
|
# the "|" denotes an "order-only" prerequiste (as in https://stackoverflow.com/a/58040049/1711186)
|
||||||
|
./src/$(PACKAGE)/AppActivity.java: app-config.sh | ./src/$(PACKAGE)
|
||||||
|
./.Makefile.scripts/make--AppActivity.java.sh > $@
|
||||||
|
|
||||||
|
./src/$(PACKAGE):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
# install the necessary android sdks
|
# install the necessary android sdks
|
||||||
./android-sdk/installed: app-config.sh
|
./android-sdk/installed: app-config.sh
|
||||||
|
@ -55,19 +68,24 @@ SHELL=/bin/bash
|
||||||
./AndroidManifest.xml: app-config.sh
|
./AndroidManifest.xml: app-config.sh
|
||||||
./.Makefile.scripts/make--AndroidManifest.xml
|
./.Makefile.scripts/make--AndroidManifest.xml
|
||||||
|
|
||||||
# recipe to make directories (if) needed
|
Makefile.app-config: app-config.sh Makefile
|
||||||
./result ./bin ./assets ./src/ ./obj:
|
source app-config.sh; \
|
||||||
mkdir -p "$@"
|
tee $@ << MAKEFILE_APP_CONFIG
|
||||||
|
BUILDTOOLS:=$${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.buildtools.version.current)
|
||||||
# make symlinksa and directories (to cater for the "helpful" java thing, to use folders for package names and yes we need a package name :( )
|
ANDROID_JAR:=$${ANDROID_SDK_ROOT}/$$(tr ';' '/' < android-sdk/.installed.platforms.version.current)/android.jar
|
||||||
./src/package: app-config.sh
|
PACKAGE:=$$(echo "$$APP_PACKAGE" | tr '.' '/')
|
||||||
set -x; source app-config.sh; PKGDIR=$$(echo "$$APP_PACKAGE" | tr '.' '/'); mkdir -p src/$$PKGDIR; rm -rf $@ ; ln -sfrv src/$$PKGDIR $@
|
MAKEFILE_APP_CONFIG
|
||||||
|
|
||||||
./obj/package: app-config.sh
|
|
||||||
source app-config.sh; PKGDIR=$$(echo "$$APP_PACKAGE" | tr '.' '/'); mkdir -p obj/$$PKGDIR; rm -rf $@; ln -sfrv obj/$$PKGDIR $@
|
|
||||||
|
|
||||||
|
# use whiptail textgui to make configuration (android API level, app-name, app-label etc...)
|
||||||
app-config.sh:
|
app-config.sh:
|
||||||
./.Makefile.scripts/make--app-config.sh
|
./.Makefile.scripts/make--app-config.sh
|
||||||
|
|
||||||
|
# rule to effectuate a cleanup
|
||||||
|
clean:
|
||||||
|
rm -rf obj/* result/*
|
||||||
|
|
||||||
|
# this rule's purpose is to run "by force" no matter what, doing nothing
|
||||||
|
# as listed prerequisite to another rule it causes that rule to be made/run
|
||||||
|
# unconditionally every time
|
||||||
FORCE:
|
FORCE:
|
||||||
@true
|
@true
|
||||||
|
|
|
@ -4,7 +4,37 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||||
</head>
|
</head>
|
||||||
|
<style>
|
||||||
|
@keyframes wobble {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.1);
|
||||||
|
opacity:0.0
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1.0);
|
||||||
|
opacity:1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<h1> SUPER</h1>
|
<h1>Webview</h1>
|
||||||
|
<script>
|
||||||
|
window.addEventListener("error",(error)=>{
|
||||||
|
document.body.innerHTML = "<h1>error</h1><pre>" +
|
||||||
|
error.filename +
|
||||||
|
"\nline:" + error.lineno +
|
||||||
|
"\n"+error.message +"</pre>";
|
||||||
|
},false);
|
||||||
|
|
||||||
|
window.addEventListener("load",()=>{
|
||||||
|
var count = localStorage.getItem("app-opened-count")|| 0;
|
||||||
|
count++;
|
||||||
|
localStorage.setItem("app-opened-count",count);
|
||||||
|
var h2 = document.createElement("h2");
|
||||||
|
h2.textContent = "Javascript works! (app was opened " + count + " times)";
|
||||||
|
h2.style.animation="wobble 1s ease-in-out 0s 1 forwards normal running"
|
||||||
|
document.body.appendChild(h2);
|
||||||
|
},false);
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
0
app/obj/.gitkeep
Normal file
0
app/obj/.gitkeep
Normal file
|
@ -1,11 +1,11 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
set -ex
|
set -e
|
||||||
|
|
||||||
CONTAINERRUNTIMES='docker podman nerdctl'
|
CONTAINERRUNTIMES='docker podman nerdctl'
|
||||||
for CONTAINERRUNTIME in $CONTAINERRUNTIMES /
|
for CONTAINERRUNTIME in $CONTAINERRUNTIMES /
|
||||||
do
|
do
|
||||||
type $CONTAINERRUNTIME 2>/dev/null && break
|
type $CONTAINERRUNTIME >/dev/null 2>/dev/null && break
|
||||||
test "$CONTAINERRUNTIME" = / && {
|
test "$CONTAINERRUNTIME" = / && {
|
||||||
echo "install a container runtime (e.g ${CONTAINERRUNTIMES//\ /\/})" >&2
|
echo "install a container runtime (e.g ${CONTAINERRUNTIMES//\ /\/})" >&2
|
||||||
exit 2
|
exit 2
|
||||||
|
@ -15,7 +15,7 @@ done
|
||||||
HASHES='md5sum cksum sha1sum base64 uuencode'
|
HASHES='md5sum cksum sha1sum base64 uuencode'
|
||||||
for HASH in $HASHES /
|
for HASH in $HASHES /
|
||||||
do
|
do
|
||||||
type $HASH 2>/dev/null && break
|
type $HASH >/dev/null 2>/dev/null && break
|
||||||
test "$HASH" = / && {
|
test "$HASH" = / && {
|
||||||
echo "install checksum (e.g ${HASHES//\ /\/})" >&2
|
echo "install checksum (e.g ${HASHES//\ /\/})" >&2
|
||||||
exit 3
|
exit 3
|
||||||
|
@ -26,32 +26,46 @@ DockerfileContent(){
|
||||||
cat << 'DOCKERFILEEOF'
|
cat << 'DOCKERFILEEOF'
|
||||||
FROM debian:latest
|
FROM debian:latest
|
||||||
RUN apt-get update -y && apt-get install -y make openjdk-17-jdk-headless unzip zip wget curl whiptail
|
RUN apt-get update -y && apt-get install -y make openjdk-17-jdk-headless unzip zip wget curl whiptail
|
||||||
ENTRYPOINT ["/bin/bash","-c","make"]
|
|
||||||
ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64/"
|
ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64/"
|
||||||
ENV ANDROID_SDK_ROOT="/app/android-sdk"
|
ENV ANDROID_SDK_ROOT="/app/android-sdk"
|
||||||
ENV BUILD_TOOLS_LATEST="$ANDROID_SDK_ROOT/cmdline-tools/latest"
|
ENV BUILD_TOOLS_LATEST="$ANDROID_SDK_ROOT/cmdline-tools/latest"
|
||||||
ENV PATH="$BUILD_TOOLS_LATEST/bin:$PATH"
|
ENV PATH="$BUILD_TOOLS_LATEST/bin:$PATH"
|
||||||
ENV LIBRARY_PATH="$LIBRARY_PATH:$BUILD_TOOLS_LATEST/lib"
|
ENV LIBRARY_PATH="$LIBRARY_PATH:$BUILD_TOOLS_LATEST/lib"
|
||||||
|
CMD ["make","--trace"]
|
||||||
|
RUN <<EOF
|
||||||
|
cat > /bin/makefile-bash-wrapper.sh << 'WRAPPER'
|
||||||
|
#!/bin/bash
|
||||||
|
printf $'\033[0;32m''#----------------------------------------\n'$'\033[0m' >&2
|
||||||
|
bash "$@"
|
||||||
|
printf '\n\n\n\n' >&2
|
||||||
|
WRAPPER
|
||||||
|
chmod u+x /bin/makefile-bash-wrapper.sh
|
||||||
|
EOF
|
||||||
DOCKERFILEEOF
|
DOCKERFILEEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
diff Dockerfile <(DockerfileContent) 2>/dev/null > /dev/null || {
|
diff Dockerfile <(DockerfileContent) 2>/dev/null > /dev/null || {
|
||||||
|
test -f Dockerfile && {
|
||||||
read -p 'reset/start Dockerfile[Y/n]' YES
|
read -p 'reset/start Dockerfile[Y/n]' YES
|
||||||
test "$YES" = "n" && { echo "aborting..." >&2; exit 1; }
|
test "$YES" = "n" && { echo "aborting..." >&2; exit 1; }
|
||||||
|
}
|
||||||
DockerfileContent > Dockerfile
|
DockerfileContent > Dockerfile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IMAGE=android-app:"$($HASH Dockerfile | tr -cd '[a-zA-Z0-9]' | head -c 12)"
|
IMAGE=build-android-app:"$($HASH Dockerfile | tr -cd '[a-zA-Z0-9]' | head -c 12)"
|
||||||
docker image inspect "$IMAGE" >/dev/null 2>/dev/null || {
|
docker image inspect "$IMAGE" >/dev/null 2>/dev/null || {
|
||||||
$CONTAINERRUNTIME build --tag "$IMAGE" .
|
$CONTAINERRUNTIME build --tag "$IMAGE" .
|
||||||
}
|
}
|
||||||
|
#(optional) tag the latest image build
|
||||||
|
docker tag $IMAGE build-android-app:latest
|
||||||
|
|
||||||
$CONTAINERRUNTIME run --name build-android-app-$(date +%F--%H-%M-%S) \
|
time $CONTAINERRUNTIME run --name build-android-app-$(date +%F--%H-%M-%S) \
|
||||||
--workdir=/app \
|
--workdir=/app \
|
||||||
|
--env LINES=10 \
|
||||||
|
--env COLUMNS=$COLUMNS \
|
||||||
--hostname build-android-app \
|
--hostname build-android-app \
|
||||||
--volume ./app:/app \
|
--volume ./app:/app \
|
||||||
-it \
|
-it \
|
||||||
--rm \
|
--rm \
|
||||||
"$IMAGE"
|
"$IMAGE" "$@"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue