Compare commits

..

20 commits

Author SHA1 Message Date
4689bb5144 keep track of ideas 2024-12-02 08:42:14 +01:00
c57affd486 make Makefile.apps generation outsourced bash script 2024-12-02 08:41:51 +01:00
d8d3ffa647 fix .gitignore 2024-12-01 08:32:32 +01:00
e3324e374b commit to new branch for android emulator 2024-12-01 08:25:10 +01:00
631056030e remove incorrect empty file 2024-11-01 06:38:39 +01:00
20a426e229 improve Makefile 2024-11-01 06:12:24 +01:00
c08394e44c modify webviews AndroidManifest prevent app restart on rotation 2024-10-31 05:54:01 +01:00
ec9073c681 test to only require permission if needed 2024-10-30 09:30:22 +01:00
f9044c39c2 index.html: add meta-viewport; add input field 2024-10-30 09:30:00 +01:00
ecbbc8dfa2 improve Makefile dependencies; add run 2024-10-30 09:28:36 +01:00
a8b47f8bdf add to .gitignore 2024-10-11 08:43:16 +02:00
0c367132b4 add .gitkeep to webview 2024-10-10 14:11:40 +02:00
df09b2dfcb move apk->apk/webview 2024-10-10 14:02:51 +02:00
6327c380ba prepare Makefie and stuff for apk/{webview,native} 2024-10-10 13:59:02 +02:00
3a9ac9f73f improve Makefiles 2024-10-08 11:38:09 +02:00
94cc0ca1fa fix typo in README.md 2024-10-08 11:38:09 +02:00
fb5409ae83 make example simpler, remove uneeded code 2024-10-08 11:38:09 +02:00
98eef38c7e do not require a res.xml file 2024-10-08 11:38:09 +02:00
17696caf99 make minimal example cleaner 2024-10-08 11:38:09 +02:00
1d7c281a7a update README.md for minimal example app 2024-10-08 09:51:46 +02:00
23 changed files with 483 additions and 111 deletions

View file

@ -1 +0,0 @@

8
.gitignore vendored
View file

@ -1,5 +1,13 @@
*.apk
*.apk.install-log
apk/ToyKey.keystore
apk/obj
apk/obj/*
apk/bin/*
apk/result
apk/result/
apk/result/*
apk/bin/!.gitkeep
/example.app.apk
docker-compose-build.log
/Makefile.apps

View file

@ -1,28 +1,42 @@
FROM archlinux:latest
ARG YESACCEPT=n
RUN echo "this is $YESACCEPT"
RUN pacman -Syu --noconfirm
RUN pacman -S --noconfirm coreutils bash shadow make unzip jdk11-openjdk wget
RUN pacman -S --noconfirm coreutils bash shadow make unzip zip jdk17-openjdk wget
ENV ANDROID_SDK_ROOT="/opt/android"
ENV BUILD_TOOLS_LATEST="$ANDROID_SDK_ROOT/cmdline-tools/latest"
RUN BUILD_TOOLS="$(realpath -m "$BUILD_TOOLS_LATEST/..")";\
mkdir -p "$BUILD_TOOLS";\
cd "$BUILD_TOOLS";\
pwd;\
wget -O cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip;\
unzip cmdline-tools.zip;\
for LATESTTOOLS in \
"$(curl https://developer.android.com/studio#command-line-tools-only | grep -e 'https://dl.google.com/android/repository/commandlinetools-linux-.*_latest.zip' | cut -f2 -d'"')" \
'https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip' ;\
do \
echo "testing to get '$LATESTTOOLS'";\
echo test "${LATESTTOOLS:0:22}" = "https://dl.google.com/" -a "${LATESTTOOLS:(-11)}" = "_latest.zip" ;\
test "${LATESTTOOLS:0:22}" = "https://dl.google.com/" -a "${LATESTTOOLS:(-11)}" = "_latest.zip" || { echo "unsure of URL $LATESTTOOLS correct, skipping it..." >&2; continue; }; \
wget -O cmdline-tools.zip "$LATESTTOOLS" ;\
unzip cmdline-tools.zip && break || { echo "error downloading working cmdline-tools.zip"; exit 1; };\
done;\
ls ;\
ls cmdline-tools;\
rm cmdline-tools.zip;\
mv -v cmdline-tools "$BUILD_TOOLS_LATEST" || true
ENV PATH="$PATH:$BUILD_TOOLS_LATEST/bin"
ENV JAVA_HOME="/usr/lib/jvm/java-11-openjdk/"
#ENTRYPOINT bash -c 'sleep 10000'
#TODO make this automatic
ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk/"
ENV LIBRARY_PATH="$LIBRARY_PATH:$BUILD_TOOLS_LATEST/lib"
ARG YESACCEPT=n
RUN test "$YESACCEPT" = "y" || { printf "\033[31;1;4m%s\n%s\033[0m " "FAILED TO BUILD CONTAINER: You did not ACCEPT THE UPSTREAM LICENSE" " -> export YESACCEPT=y" >&2; exit 1; }
RUN echo you selected to accept the licenses/TOS
RUN echo "$YESACCEPT" | sdkmanager --install "build-tools;33.0.2"
RUN echo "$YESACCEPT" | sdkmanager --install "platforms;android-33"
#RUN apk add setpriv
RUN echo "$YESACCEPT" | sdkmanager --install "ndk;28.0.12433566"
#RUN echo "$YESACCEPT" | sdkmanager --install "system-images;android-33;aosp_atd;x86_64"
#RUN echo "$YESACCEPT" | sdkmanager --install "emulator"
#RUN echo "no" | avdmanager --verbose create avd --force --name "thedevice" --package 'system-images;android-33;aosp_atd;x86_64' --tag "aosp_atd" --abi "x86_64"
#RUN echo "$YESACCEPT" | sdkmanager --install "platform-tools"
COPY entrypoint.sh /entrypoint.sh
RUN chown 0:0 /entrypoint.sh
RUN chmod 0700 /entrypoint.sh

43
IDEAS.TODOS.md Normal file
View file

@ -0,0 +1,43 @@
# Ideas and todos
## 1. EMULATOR: enable a way to have the "sdk emulator" running
this is attempted in the `emulator` branch. Challenges comprise:
* Xorg server must be forwarded (and other stuff like sound etc)
* the emulator itself might need to have `docker .... --device` setup for `/dev/kvm` probably (and at that point it might be
better to have it all run natively inside a VM anyways... (alternative would be nested virutalization)
## 2. BUILD and PACKAGENAME improvements
### status quo: 2 Makefiles (gnu make) are involved,
* a) one being the outer one that uses Makefile.apps as an include and then
* b) an inner one located at `./apps/<app-name>/Makefile`
the inner-one is not "parametrized" and at present has explicit nameing of the android app/ package (i.e. `example.app`),
which comes with the additional negative that one has several files that need to be adjusted, this also being true
because of the "fun that JAVA" naming conventions which basically means that the very least those files all have to
be kept in sync
* `./apps/<app-name>/AndroidManifest.xml`
* `./apps/<app-name>/Makefile`
* `./apps/<app-name>/src/<package-name>/<activity-name>.java`
### goal: attempt to have the `<app-name>`, `<package-name>` and `<package-name>` be abstracted
Ideally make the inner Makefile superfluous
## 3. ALLOW KOTLIN
Since Java was apparently not "good/fancy" enough of maybe "bloated" the hippster did do what they like best
re-invent to garnish personal "pride/achievement" and thus make a unhelpful thing (java) into now 2 unhelpful
things (i.e. Kotlin and Java) super!
However oftentimes now the undesired-yet-existing-kotlin is there and a goal could be to enable it being used.
After all it appears to be a tiny bit less of a boilerplate annoyance...
## 4. ALLOW GRADLEBUILDS
GRADLE is often used as a building system for apps, it would be beneficial to have those build run also
in this `android-docker-app` thing

View file

@ -1,37 +1,18 @@
# this includes explicit rules
include Makefile.apps
Makefile.apps: Makefile apps
@./Makefile.make.Makefile.apps.sh
all: build install
apps:
mkdir "$@"
build:
docker-compose run compile
install: $(shell for APP in apps/*/; do test -d "$$APP" || continue; echo "$$APP""app.apk.install-log"; done)
force-install reinstall:
for APP in apps/*/; do rm -f "$$APP""app.apk.install-log" 2>/dev/null; done; $(MAKE) install
run: $(shell cd apps/; for APP in */; do test -d "$$APP" || continue; echo "run-$${APP%/}"; done)
install:
adb install -r ./apk/example.app.apk
.PHONY: clean-all
clean-all: clean-docker clean-apk
.PHONY: clean-docker
clean-docker:
rm docker-compose-build.log || true
docker-compose down --remove-orphans --rmi all
.PHONY: clean-apk
clean-apk:
cd apk && $(MAKE) clean
apk: apk/app.apk
true
apk/app.apk: docker-compose-build.log
docker-compose run --rm compile
docker-compose-build.log: Dockerfile docker-compose.yml
docker-compose-build.log: Dockerfile compose.yml
docker-compose down --remove-orphans --rmi all
BUILDKIT_PROGRESS=plain docker-compose build | tee docker-compose-build.log

22
Makefile.make.Makefile.apps.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
(
set -xe
cd apps
for APP in */
do
test -d "$APP" || continue;
APP="${APP%/}";
cat << MAKEFILE
apps/$APP/app.apk: docker-compose-build.log
docker compose run --rm compile $APP
build-$APP: apps/$APP/app.apk
true
apps/$APP/app.apk.install-log: apps/$APP/app.apk
adb install -r $< > \$@ || rm \$@
install-$APP: apps/$APP/app.apk.install-log
true
run-$APP: apps/$APP/app.apk.install-log
adb shell am start -n app.example/.ExampleApp
MAKEFILE
done
) > Makefile.apps

View file

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="30"
android:targetSdkVersion="33"/>
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<!-- android:maxSdkVersion="integer" /> -->
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="app.example.ExampleApp"
android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

View file

@ -1 +0,0 @@
./bin/example.app.apk

View file

@ -1,33 +0,0 @@
package app.example;
import android.util.Log;
import android.widget.TextView;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.MenuItem;
import android.view.*;
import android.widget.*;
import android.view.ViewGroup.*;
public class ExampleApp extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// creating LinearLayout
LinearLayout linLayout = new LinearLayout(this);
// specifying vertical orientation
linLayout.setOrientation(LinearLayout.VERTICAL);
// creating LayoutParams
LayoutParams linLayoutParam = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
// set LinearLayout as a root element of the screen
setContentView(linLayout, linLayoutParam);
LayoutParams lpView = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(this);
tv.setText("SUPERVIEalexW");
tv.setLayoutParams(lpView);
linLayout.addView(tv);
}
}

9
apps/webview/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
/ToyKey.keystore
/obj
/obj/*
/bin/*
!/bin/.gitkeep
/result
/result/
/result/*
/example.app.apk

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="30"
android:targetSdkVersion="33"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="android.permission.MANAGE_MEDIA"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name="app.example.ExampleApp"
android:exported="true"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -14,23 +14,29 @@ all: build
.PHONY : deploy
.PHONY : clean
build : ./bin/example.app.apk
ln -sf ./bin/example.app.apk ./example.app.apk
build : ./result/example.app.apk
mv ./result/example.app.apk app.apk
true
./bin/example.app.apk : ./bin/signed.apk
env:
set > set ; env > env
./result/example.app.apk : ./result/signed.apk
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/zipalign -v -f 4 $< $@
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/apksigner sign --ks ToyKey.keystore --key-pass pass:armena --ks-pass pass:armena $@
./bin/signed.apk : ./bin/unsigned.apk ./ToyKey.keystore
./result/signed.apk : ./result/unsigned.apk ./ToyKey.keystore ./result
jarsigner -verbose -keystore ./ToyKey.keystore -storepass armena -keypass armena -signedjar $@ $< helljniKey
./bin/unsigned.apk : ./bin/classes.dex
./result:
mkdir -p "$@"
./result/unsigned.apk : ./bin/classes.dex ./result
rm -rvf "$@"
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/aapt package -v -u -f -M ./AndroidManifest.xml -S ./res \
-I $(ANDROID_HOME)/platforms/$(PLATFORM)/android.jar -F $@ ./bin
-I $(ANDROID_HOME)/platforms/$(PLATFORM)/android.jar -A ./assets -F $@ ./bin
./bin/classes.dex : ./obj/app/example/ExampleApp.class
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/d8 $(shell find obj -name '*.class') --lib $(ANDROID_HOME)/platforms/$(PLATFORM)/android.jar --output bin
./bin/classes.dex : ./obj/app/example/ExampleApp.class ./obj/app/example/ExampleApp$$1.class
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/d8 ./obj/app/example/*.class --lib $(ANDROID_HOME)/platforms/$(PLATFORM)/android.jar --output bin
./src/app/example/R.java : $(shell find ./res -type f)
$(ANDROID_HOME)/build-tools/$(ANDROID_VERSION)/aapt package -v -f -m -S ./res -J ./src -M ./AndroidManifest.xml \
@ -44,4 +50,4 @@ build : ./bin/example.app.apk
-storepass armena -keypass armena -alias helljniKey -keyalg RSA -v
clean:
rm -f ./bin/* ./lib/arm64-v8a/*
rm -f ./bin/* ./lib/arm64-v8a/* ./result/*

View file

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta content="width=device-width,initial-scale=1.0" name="viewport">
</head>
<script>
function sleepit(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, ms);
});
}
function divMessage(html){
var div = document.createElement('div');
div.innerHTML=html;
document.body.appendChild(div);
div.scrollIntoView({ behavior: 'smooth'});
}
(async function webviewprogram(){
var port;
var resolves = [];
function setupMessage(){
return new Promise((resolve) => {
window.addEventListener('message',(e)=>{
if(e.data=="init-from-java" && ! port){
divMessage('INIT');
port = e.ports[0];
port.onmessage = function (ee) {
divMessage('AAport.onmessage='+ee.data);
var response = JSON.parse(ee.data);
divMessage('response.resolveIndex'+response.resolveIndex);//AAport.onmessage='+ee.data);
var localresolve = resolves[response.resolveIndex];
divMessage(typeof localresolve)
localresolve(response);
}
resolve()
}
divMessage('message='+e.data);
},true);
});
}
function doLs(path){
divMessage('doLs');
return new Promise((resolve) => {
divMessage('resolves.length'+resolves.length);
resolves.push(resolve);
divMessage('after push resolves.length'+resolves.length);
port.postMessage('{"function":"ls","path":"'+path+'","resolveIndex":"'+(resolves.length-1)+'"}');
});
}
function doCat(file){
return new Promise((resolve) => {
resolves.push(resolve);
port.postMessage('{"function":"cat","resolveIndex":"'+resolves.length+'"}');
});
}
window.addEventListener('load',()=>{
divMessage('JAVASCRIPT WORKS');
},false);
// await sleepit(2000);
// divMessage('awaited 2000');
// await sleepit(2000);
// divMessage('awaited again 2000');
await setupMessage();
divMessage('setup');
async function mapDoLs(path){
var reply = await doLs(path);
divMessage("reply.result.length"+reply.result.length);
reply.result.forEach((file)=>{
divMessage(file.name);//reply.result.length"+reply.result.length);
//var button
button = document.createElement("button");
button.addEventListener("click",()=>{
if(file.isDirectory)
mapDoLs(path+"/"+file.name);
},false);
//if(file.isDirectory){
//{
// button = document.createElement("button");
// button.addEventListener("click",()=>{
// mapDoLs(path+"/"+file.name);
// },false);
//} else {
// button = document.createElement("div");
//}
////a.href="#";
//////a.textContent="asdasdada"
button.textContent=file.name+ " " + file.size;
document.body.appendChild(button);
});
}
await mapDoLs("/DCIM");
divMessage("done");
// for(let file of DCIM.result){
// divMessage("filename");
//});
})();
</script>
<a href='https://html5test.co/'>https://html5test.co/</a>
<h1> this is html <h1>
<h2> this is a h2</h2>
<input type=text />
<img src='https://wald.alexmahr.de/images/bear.avif'>
<img src='https://wald.alexmahr.de/images/delphin.avif'>
</html>

View file

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,179 @@
package app.example;
import android.provider.Settings ;
import android.content.Intent;
import android.util.Log;
import android.util.Base64;
import java.util.Objects;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.text.method.ScrollingMovementMethod;
import android.view.*;
//import android.view.MenuItem;
import android.view.ViewGroup.*;
import android.widget.*;
//import android.widget.Toast;
//import android.widget.TextView;
import android.webkit.*;
import android.net.Uri;
import org.json.JSONObject;
//import android.webkit.WebView;
//import android.webkit.WebMessage;
//import android.webkit.WebMessagePort;
import java.io.InputStream;
import java.io.File;
public class ExampleApp extends Activity {
public JSONObject doLs(JSONObject message){
try{
JSONObject file;
File directory = new File(Environment.getExternalStorageDirectory().toString() + message.getString("path"));
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++)
{
try{
//Log.d("ALEXINFO","filename"+files[i].getName());
file = new JSONObject();
file.put("name",files[i].getName());
file.put("isFile",files[i].isFile());
file.put("isDirectory",files[i].isDirectory());
file.put("size",files[i].length());
message.accumulate("result",file);
} catch (Exception e) {
Log.d("Exception EX1","ex1");
}
}
} catch (Exception e) {
Log.d("Exception EX2","ex2");
}
return message;
}
public JSONObject doCat(JSONObject message){
try{
File directory = new File(Environment.getExternalStorageDirectory().toString() + message.getString("path"));
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++)
{
try{
message.accumulate("result",files[i].getName());
} catch (Exception e) {}
}
} catch (Exception e) {}
return message;
}
final static int APP_STORAGE_ACCESS_REQUEST_CODE = 501; // Any value
private static final String BASE_URI = "https://alexmahr.de";
private WebMessagePort port;
private void initPort(WebView myWebView) {
final WebMessagePort[] channel=myWebView.createWebMessageChannel();
port=channel[0];
port.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
public void onMessage(WebMessagePort porte, WebMessage message) {
try{
JSONObject messageJSON = new JSONObject(message.getData());
JSONObject reply;
if(Objects.equals(messageJSON.getString("function"),"ls"))
{
reply = doLs(messageJSON);
reply.put("super","man");
port.postMessage(new WebMessage(reply.toString()));
return;
}
else if(Objects.equals(messageJSON.getString("function"),"cat"))
{
reply = doCat(messageJSON);
reply.put("super","cat");
port.postMessage(new WebMessage(reply.toString()));
return;
}
else {
reply=messageJSON;
reply.put("super","else");
reply.accumulate("result",1);
reply.accumulate("result","something");
port.postMessage(new WebMessage(reply.toString()));
}
} catch( Exception e) { }
}
});
myWebView.postWebMessage(new WebMessage("init-from-java", new WebMessagePort[]{channel[1]}),Uri.parse(BASE_URI));
}
public String readFileFromAssets(String filename) {
String filecontents = "";
try {
InputStream stream = getAssets().open(filename);
int filesize = stream.available();
byte[] filebuffer = new byte[filesize];
stream.read(filebuffer);
stream.close();
filecontents = new String(filebuffer);
} catch (Exception e) {
// I <3 java exceptions
}
return filecontents;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// this removes the title bar (a ~1cm big strip at the top of the app showing its name
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
// we create the webview (at least on the android 14 that is a webview that features avif + websockets etc....)
WebView myWebView = new WebView(this);//activityContext);
// MyJavascriptInterface myJavaScriptInterface = new MyJavascriptInterface(this,myWebView);
// we create a webview (there is also setwebviewclient-vs-setwebchromeclient
WebViewClient myWebViewClient= new WebViewClient();
myWebView.setWebViewClient(myWebViewClient);
// to setup settings
WebSettings myWebSettings = myWebView.getSettings();
myWebSettings.setBuiltInZoomControls(true);
myWebSettings.setDisplayZoomControls(false);
myWebSettings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(this, "myJavaScriptInterface");
// load the html from assets file
String html = readFileFromAssets("index.html");
myWebView.loadDataWithBaseURL(BASE_URI,html, "text/html", "UTF-8",null);
//myWebView.loadData(encodedHtml, "text/html", "base64");
// alternatively this could be to load a website
//myWebView.loadUrl("https://alexmahr.de/ru");
setContentView(myWebView);
new CountDownTimer(500, 100) {
public void onTick(long millisUntilFinished) {
try{
JSONObject MyJSONObject = new JSONObject("{\"json\":[1,2,3],\"something\":\"test\"}");
myWebView.postWebMessage(new WebMessage("this is the message"+millisUntilFinished+ " " + MyJSONObject.get("something")),Uri.parse(BASE_URI));
} catch( Exception e) { }
// mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
// myWebView.evaluateJavascript("document.body.innerHTML='SUP "+millisUntilFinished+" all is lost';",null);
}
public void onFinish() {
initPort(myWebView);//myWebView.evaluateJavascript("document.body.innerHTML='all is lost';",null);
}
}.start();
// Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package: app.example"));// + BuildConfig.APPLICATION_ID));
if(!Environment.isExternalStorageManager()){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
} else {
Toast.makeText(this, "berechtigt", Toast.LENGTH_SHORT).show();
}
//intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
// startActivityForResult(intent, APP_STORAGE_ACCESS_REQUEST_CODE);
}
@JavascriptInterface
public String toString() {
// this.webview.evaluateJavascript("(setTimeout(()=>{document.body.innerHTML='all gone';},2000)()",null);
return "this is good";
}
}

View file

@ -1,9 +1,16 @@
services:
compile:
hostname: thinkbox
build:
context: .
args:
YESACCEPT: ${YESACCEPT}
YESACCEPT: ${YESACCEPT:-}
stop_grace_period: 1s
environment:
XAUTHORITY: /root/.Xauthority
DISPLAY: ":0"
volumes:
- ./apk:/apk
- ./apps:/apps
- /home/alex/.Xauthority:/root/.Xauthority:ro

View file

@ -1,8 +1,18 @@
#!/bin/sh
cd /apk;
VOLUID="$(stat -c "%u" /apk)";
VOLGID="$(stat -c "%g" /apk)";
CMD="${*:-"make"}"
setpriv --reuid $VOLUID --regid $VOLGID --clear-groups sh -c "$CMD"
set -x
APKDIR="/apps/$1"
shift
#test -d "$1" ==
#APKDIR=
#cd /apk/$1;
#shift
VOLUID="$(stat -c "%u" "$APKDIR")";
VOLGID="$(stat -c "%g" "$APKDIR")";
#CMD="${*:-"make"}"
cd "$APKDIR"
test -z "$*" && set -- make
setpriv --reuid $VOLUID --regid $VOLGID --clear-groups sh -c "$*"