Compare commits

...

2 commits

Author SHA1 Message Date
2386b29233 add new branch "native" 2024-10-10 11:56:06 +02:00
947f057649 request manage all files, list files 2024-10-10 02:05:22 +02:00
6 changed files with 198 additions and 21 deletions

View file

@ -23,6 +23,7 @@ RUN test "$YESACCEPT" = "y" || { printf "\033[31;1;4m%s\n%s\033[0m " "FAILED TO
RUN echo you selected to accept the licenses/TOS RUN echo you selected to accept the licenses/TOS
RUN echo "$YESACCEPT" | sdkmanager --install "build-tools;33.0.2" RUN echo "$YESACCEPT" | sdkmanager --install "build-tools;33.0.2"
RUN echo "$YESACCEPT" | sdkmanager --install "platforms;android-33" RUN echo "$YESACCEPT" | sdkmanager --install "platforms;android-33"
RUN echo "$YESACCEPT" | sdkmanager --install "ndk;28.0.12433566"
#RUN apk add setpriv #RUN apk add setpriv
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
RUN chown 0:0 /entrypoint.sh RUN chown 0:0 /entrypoint.sh

View file

@ -1,16 +1,28 @@
# Repo allowing -in a KISS way- to create a containered way to build an Android App APK # Repo allowing -in a KISS way- to create a containered way to build an Android App APK
## changelog ## branchs
* using https://android.googlesource.com/platform/cts/+/android-7.1.1_r13/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java derived ### branch `native`
webmessage to send data to Javascript/Webview from Java (using a timer)
## brach `no-res.xml` this branch should allow to use the Native Developer Kit to build an app without much java
the content below apk/native are LICENSE MIT
### branch `no-res.xml`
this branch features the exmaple.app to not require the compoletely bogus unneeded requirement this branch features the exmaple.app to not require the compoletely bogus unneeded requirement
to setup a `./apk/res/layouts/res.xml` file to setup the layout to be used. to setup a `./apk/res/layouts/res.xml` file to setup the layout to be used.
Instead a layout is created inline Instead a layout is created inline
### branch `webview`
a bra
## changelog
* using https://android.googlesource.com/platform/cts/+/android-7.1.1_r13/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java derived
webmessage to send data to Javascript/Webview from Java (using a timer)
## tl;dr ## tl;dr

View file

@ -9,6 +9,7 @@
<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_DOCUMENTS"/>
<uses-permission android:name="android.permission.MANAGE_MEDIA"/> <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.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/> <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_IMAGES"/>

View file

@ -1,21 +1,106 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<script> <script>
window.addEventListener('message',(e)=>{
function sleepit(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, ms);
});
}
function divMessage(html){
var div = document.createElement('div'); var div = document.createElement('div');
div.innerHTML='message'+e.data; div.innerHTML=html;
document.body.appendChild(div); document.body.appendChild(div);
div.scrollIntoView({ behavior: 'smooth'}); div.scrollIntoView({ behavior: 'smooth'});
},true); }
window.addEventListener('load',()=>{
var div = document.createElement('div'); (async function webviewprogram(){
div.innerHTML='JAVASCRIPT works' var port;
document.body.appendChild(div); var resolves = [];
div.scrollIntoView({ behavior: 'smooth'}); function setupMessage(){
},false); 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> </script>
<a href='https://html5test.co/'>https://html5test.co/</a> <a href='https://html5test.co/'>https://html5test.co/</a>
<h1> this is html <h1> <h1> this is html <h1>
<h2> this is a h2</h2> <h2> this is a h2</h2>
<img src='https://wald.alexmahr.de/images/bear.avif'> <img src='https://wald.alexmahr.de/images/bear.avif'>
<img src='https://wald.alexmahr.de/images/delphin.avif'>
</html> </html>

View file

@ -1,10 +1,13 @@
package app.example; package app.example;
import android.provider.Settings ;
import android.content.Intent;
import android.util.Log; import android.util.Log;
import android.util.Base64; 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.CountDownTimer;
import android.os.Environment;
import android.text.method.ScrollingMovementMethod; import android.text.method.ScrollingMovementMethod;
import android.view.*; import android.view.*;
//import android.view.MenuItem; //import android.view.MenuItem;
@ -18,9 +21,50 @@ import org.json.JSONObject;
//import android.webkit.WebMessage; //import android.webkit.WebMessage;
//import android.webkit.WebMessagePort; //import android.webkit.WebMessagePort;
import java.io.InputStream; import java.io.InputStream;
import java.io.File;
public class ExampleApp extends Activity { 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 static final String BASE_URI = "https://alexmahr.de";
private WebMessagePort port; private WebMessagePort port;
private void initPort(WebView myWebView) { private void initPort(WebView myWebView) {
@ -28,10 +72,35 @@ public class ExampleApp extends Activity {
port=channel[0]; port=channel[0];
port.setWebMessageCallback(new WebMessagePort.WebMessageCallback() { port.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override @Override
public void onMessage(WebMessagePort port, WebMessage message) { 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("", new WebMessagePort[]{channel[1]}),Uri.parse(BASE_URI)); myWebView.postWebMessage(new WebMessage("init-from-java", new WebMessagePort[]{channel[1]}),Uri.parse(BASE_URI));
} }
public String readFileFromAssets(String filename) { public String readFileFromAssets(String filename) {
@ -73,7 +142,7 @@ public class ExampleApp extends Activity {
// alternatively this could be to load a website // alternatively this could be to load a website
//myWebView.loadUrl("https://alexmahr.de/ru"); //myWebView.loadUrl("https://alexmahr.de/ru");
setContentView(myWebView); setContentView(myWebView);
new CountDownTimer(5000, 1000) { new CountDownTimer(500, 100) {
public void onTick(long millisUntilFinished) { public void onTick(long millisUntilFinished) {
try{ try{
JSONObject MyJSONObject = new JSONObject("{\"json\":[1,2,3],\"something\":\"test\"}"); JSONObject MyJSONObject = new JSONObject("{\"json\":[1,2,3],\"something\":\"test\"}");
@ -84,9 +153,17 @@ public class ExampleApp extends Activity {
} }
public void onFinish() { public void onFinish() {
myWebView.evaluateJavascript("document.body.innerHTML='all is lost';",null); initPort(myWebView);//myWebView.evaluateJavascript("document.body.innerHTML='all is lost';",null);
} }
}.start(); }.start();
// Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package: app.example"));// + BuildConfig.APPLICATION_ID));
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
//intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
Uri uri = Uri.fromParts("package", this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
// startActivityForResult(intent, APP_STORAGE_ACCESS_REQUEST_CODE);
} }
@JavascriptInterface @JavascriptInterface
public String toString() { public String toString() {

View file

@ -1,5 +1,6 @@
services: services:
compile: compile:
hostname: android-app-builder
build: build:
context: . context: .
args: args: