[SpaccWebView.Android] Config as XML

This commit is contained in:
octospacc 2024-11-10 15:58:44 +01:00
parent 04b053cbc2
commit 7093760d38
9 changed files with 157 additions and 33 deletions

View File

@ -1,7 +1,6 @@
package com.example.spaccwebviewapplication; package com.example.spaccwebviewapplication;
import android.os.Bundle; import android.os.Bundle;
import org.eu.spacc.spaccdotweb.android.helpers.DataMoveHelper; import org.eu.spacc.spaccdotweb.android.helpers.DataMoveHelper;
import org.eu.spacc.spaccdotweb.android.SpaccWebViewActivity; import org.eu.spacc.spaccdotweb.android.SpaccWebViewActivity;
@ -15,6 +14,7 @@ public class MainActivity extends SpaccWebViewActivity {
DataMoveHelper.run(this, R.string.exit, R.string.move_app_data, R.string.move_app_data_info); DataMoveHelper.run(this, R.string.exit, R.string.move_app_data, R.string.move_app_data_info);
this.webView = findViewById(R.id.webview); this.webView = findViewById(R.id.webview);
this.webView.loadConfig(this, R.xml.app_config);
this.webView.loadAppIndex(); this.webView.loadAppIndex();
} }
} }

View File

@ -1,11 +1,54 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccdotweb.android;
import org.eu.spacc.spaccdotweb.android.Constants.*; import org.eu.spacc.spaccdotweb.android.Constants.*;
import org.eu.spacc.spaccdotweb.android.helpers.ConfigReader;
public class Config { public class Config extends Defaults {
public static final Boolean ALLOW_JAVASCRIPT = true; private ConfigReader configReader;
public static final Boolean ALLOW_STORAGE = true;
public static final AppIndex APP_INDEX = AppIndex.LOCAL; public Config() {}
public static final String LOCAL_INDEX = "index.html";
public static final String REMOTE_INDEX = "https://example.com"; public Config(ConfigReader configReader) {
this.configReader = configReader;
}
public Boolean getAllowJavascript() {
Boolean value = getBoolean("allow_javascript");
return (value != null ? value : Defaults.ALLOW_JAVASCRIPT);
}
public Boolean getAllowStorage() {
Boolean value = getBoolean("allow_storage");
return (value != null ? value : Defaults.ALLOW_STORAGE);
}
public AppIndex getAppIndex() {
AppIndex value = (AppIndex)get("app_index");
return (value != null ? value : Defaults.APP_INDEX);
}
public String getLocalIndex() {
String value = getString("local_index");
return (value != null ? value : Defaults.LOCAL_INDEX);
}
public String getRemoteIndex() {
return getString("remote_index");
}
private Object get(String key) {
if (configReader != null) {
return configReader.get(key);
} else {
return null;
}
}
private Boolean getBoolean(String key) {
return (Boolean)get(key);
}
private String getString(String key) {
return (String)get(key);
}
} }

View File

@ -0,0 +1,10 @@
package org.eu.spacc.spaccdotweb.android;
import org.eu.spacc.spaccdotweb.android.Constants.*;
public class Defaults {
public static final Boolean ALLOW_JAVASCRIPT = true;
public static final Boolean ALLOW_STORAGE = true;
public static final AppIndex APP_INDEX = AppIndex.LOCAL;
public static final String LOCAL_INDEX = "index.html";
}

View File

@ -0,0 +1,59 @@
package org.eu.spacc.spaccdotweb.android.helpers;
import android.content.Context;
import android.content.res.XmlResourceParser;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eu.spacc.spaccdotweb.android.Constants.*;
import org.xmlpull.v1.XmlPullParserException;
public class ConfigReader {
private final Map<String, Object> configData = new HashMap<>();
public ConfigReader(Context context, int configResource) {
try {
parseConfigData(context, configResource);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object get(String key) {
return configData.get(key);
}
private void parseConfigData(Context context, int configResource) throws IOException, XmlPullParserException {
XmlResourceParser parser = context.getResources().getXml(configResource);
int eventType = parser.getEventType();
while (eventType != XmlResourceParser.END_DOCUMENT) {
if (eventType == XmlResourceParser.START_TAG) {
String type = parser.getName();
if (!type.equals("config")) {
String name = parser.getAttributeValue(null, "name");
String value = parser.nextText();
configData.put(name, parseValue(type, value));
}
}
eventType = parser.next();
}
}
private Object parseValue(String type, String value) {
switch (type) {
case "boolean":
return Boolean.parseBoolean(value);
case "string":
return value;
default:
value = value.toUpperCase();
try {
switch (type) {
case "AppIndex":
return AppIndex.valueOf(value);
}
} catch (IllegalArgumentException ignored) {}
}
return null;
}
}

View File

@ -6,11 +6,9 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import org.eu.spacc.spaccdotweb.android.Constants; import org.eu.spacc.spaccdotweb.android.Constants;
import org.eu.spacc.spaccdotweb.android.utils.StorageUtils; import org.eu.spacc.spaccdotweb.android.utils.StorageUtils;
import org.eu.spacc.spaccdotweb.android.utils.FileUtils; import org.eu.spacc.spaccdotweb.android.utils.FileUtils;
import java.io.IOException; import java.io.IOException;
public class DataMoveHelper { public class DataMoveHelper {

View File

@ -3,7 +3,6 @@ package org.eu.spacc.spaccdotweb.android.utils;
import static android.content.Context.DOWNLOAD_SERVICE; import static android.content.Context.DOWNLOAD_SERVICE;
import android.app.DownloadManager; import android.app.DownloadManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.webkit.CookieManager; import android.webkit.CookieManager;

View File

@ -3,14 +3,14 @@ package org.eu.spacc.spaccdotweb.android.webview;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ContextMenu;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils;
import org.eu.spacc.spaccdotweb.android.Config; import org.eu.spacc.spaccdotweb.android.Config;
import org.eu.spacc.spaccdotweb.android.helpers.ConfigReader;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils;
public class SpaccWebView extends WebView { public class SpaccWebView extends WebView {
private Config config;
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
public SpaccWebView(Context context, AttributeSet attrs) { public SpaccWebView(Context context, AttributeSet attrs) {
@ -18,18 +18,8 @@ public class SpaccWebView extends WebView {
this.setWebViewClient(new WebViewClient(context)); this.setWebViewClient(new WebViewClient(context));
this.setWebChromeClient(new WebChromeClient(context)); this.setWebChromeClient(new WebChromeClient(context));
this.setDownloadListener(new DownloadListener(context)); this.setDownloadListener(new DownloadListener(context));
this.config = new Config();
WebSettings webSettings = this.getSettings(); this.applyConfig(context);
webSettings.setJavaScriptEnabled(Config.ALLOW_JAVASCRIPT);
ApiUtils.apiRun(7, () -> webSettings.setDomStorageEnabled(Config.ALLOW_STORAGE));
ApiUtils.apiRun(5, () -> webSettings.setDatabaseEnabled(Config.ALLOW_STORAGE));
if (Config.ALLOW_STORAGE) {
ApiUtils.apiRun(5, () -> webSettings.setDatabasePath(context.getDir("databases", 0).getAbsolutePath()));
}
ApiUtils.apiRun(3, () -> webSettings.setAllowFileAccess(false));
} }
// TODO: Implement context menu (long-press on links, images, etc...) // TODO: Implement context menu (long-press on links, images, etc...)
@ -38,16 +28,36 @@ public class SpaccWebView extends WebView {
// super.onCreateContextMenu(menu); // super.onCreateContextMenu(menu);
// } // }
private void applyConfig(Context context) {
WebSettings webSettings = this.getSettings();
webSettings.setJavaScriptEnabled(config.getAllowJavascript());
boolean allowStorage = config.getAllowStorage();
ApiUtils.apiRun(7, () -> webSettings.setDomStorageEnabled(allowStorage));
ApiUtils.apiRun(5, () -> webSettings.setDatabaseEnabled(allowStorage));
if (allowStorage) {
ApiUtils.apiRun(5, () -> webSettings.setDatabasePath(context.getDir("databases", 0).getAbsolutePath()));
}
ApiUtils.apiRun(3, () -> webSettings.setAllowFileAccess(false));
}
public void loadConfig(Context context, int configResource) {
this.config = new Config(new ConfigReader(context, configResource));
this.applyConfig(context);
}
public void loadAppIndex() { public void loadAppIndex() {
String url = null; String url = null;
switch (Config.APP_INDEX) { switch (config.getAppIndex()) {
case LOCAL: case LOCAL:
url = ("file:///android_asset/" + Config.LOCAL_INDEX); url = ("file:///android_asset/" + config.getLocalIndex());
break; break;
case REMOTE: case REMOTE:
url = Config.REMOTE_INDEX; url = config.getRemoteIndex();
break; break;
} }
loadUrl(url); this.loadUrl(url);
} }
} }

View File

@ -1,13 +1,9 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccdotweb.android.webview;
import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.webkit.WebView; import android.webkit.WebView;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils; import org.eu.spacc.spaccdotweb.android.utils.ApiUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<boolean name="allow_javascript">true</boolean>
<boolean name="allow_storage">true</boolean>
<AppIndex name="app_index">local</AppIndex> <!-- local or remote -->
<string name="local_index">index.html</string>
<string name="remote_index">https://example.com</string>
</config>