[SpaccWebView.Android] Make actual Android library, upgrade to SDK 35

This commit is contained in:
2025-05-26 01:19:38 +02:00
parent 6313d99e30
commit fcbd40ea34
38 changed files with 206 additions and 121 deletions

View File

@ -12,9 +12,8 @@ android {
versionCode 1 versionCode 1
versionName '1.0' versionName '1.0'
minSdk 1 minSdk 1
//noinspection OldTargetApi targetSdk 35
targetSdk 34 compileSdk 35
compileSdk 34
} }
signingConfigs { signingConfigs {
@ -42,6 +41,11 @@ android {
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
} }
java { java {
@ -49,3 +53,7 @@ java {
languageVersion = JavaLanguageVersion.of(17) languageVersion = JavaLanguageVersion.of(17)
} }
} }
dependencies {
implementation project(":SpaccWebView")
}

View File

@ -13,16 +13,26 @@ import android.view.MenuItem;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.EditText; import android.widget.EditText;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils; import org.eu.spacc.spaccwebview.android.utils.ApiUtils;
import org.eu.spacc.spaccdotweb.android.helpers.DataMoveHelper; import org.eu.spacc.spaccwebview.android.helpers.DataMoveHelper;
import org.eu.spacc.spaccdotweb.android.SpaccWebViewActivity; import org.eu.spacc.spaccwebview.android.SpaccWebViewActivity;
import org.eu.spacc.spaccdotweb.android.webview.SpaccWebViewClient; import org.eu.spacc.spaccwebview.android.webview.SpaccWebViewClient;
public class MainActivity extends SpaccWebViewActivity { public class MainActivity extends SpaccWebViewActivity {
private ActionBar actionBar = null; private ActionBar actionBar = null;
private Menu menu = null; private Menu menu = null;
private long pageStartTime = 0; private long pageStartTime = 0;
private void refreshMenu(boolean started) {
if (menu != null) {
menu.findItem(R.id.stop).setVisible(started);
menu.findItem(R.id.reload).setVisible(!started);
menu.findItem(R.id.about_app).setVisible(webView.getConfig().getAboutPage() != null);
menu.findItem(R.id.backwards).setEnabled(webView.canGoBack());
menu.findItem(R.id.forward).setEnabled(webView.canGoForward());
}
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -30,10 +40,9 @@ public class MainActivity extends SpaccWebViewActivity {
ApiUtils.apiRun(11, () -> this.actionBar = getActionBar()); ApiUtils.apiRun(11, () -> this.actionBar = getActionBar());
DataMoveHelper.run(this, R.string.exit, R.string.move_app_data, R.string.move_app_data_info); DataMoveHelper.run(this);
this.webView = findViewById(R.id.webview); this.webView = findViewById(R.id.webview);
this.webView.setStrings(R.string.open_menu, R.string.open_externally_menu, R.string.copy_url_menu);
this.webView.setWebViewClient(new SpaccWebViewClient(this) { this.webView.setWebViewClient(new SpaccWebViewClient(this) {
@SuppressLint("UseRequiresApi") @SuppressLint("UseRequiresApi")
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@ -41,16 +50,12 @@ public class MainActivity extends SpaccWebViewActivity {
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon); super.onPageStarted(view, url, favicon);
pageStartTime = System.currentTimeMillis(); pageStartTime = System.currentTimeMillis();
refreshMenu(true);
if (menu != null) { if (menu != null) {
menu.findItem(R.id.stop).setVisible(true);
menu.findItem(R.id.reload).setVisible(false);
menu.findItem(R.id.open_externally).setVisible(!ApiUtils.isInternalUrl(Uri.parse(url))); menu.findItem(R.id.open_externally).setVisible(!ApiUtils.isInternalUrl(Uri.parse(url)));
menu.findItem(R.id.about_app).setVisible(webView.getConfig().getAboutPage() != null);
menu.findItem(R.id.backwards).setEnabled(webView.canGoBack());
menu.findItem(R.id.forward).setEnabled(webView.canGoForward());
} }
if (actionBar != null) { if (actionBar != null) {
actionBar.setSubtitle(R.string.loading); actionBar.setSubtitle(org.eu.spacc.spaccwebview.android.R.string.loading);
} }
// if (justStarted) { // if (justStarted) {
// new Handler().postDelayed(() -> Objects.requireNonNull(getActionBar()).hide(), 3000); // new Handler().postDelayed(() -> Objects.requireNonNull(getActionBar()).hide(), 3000);
@ -63,10 +68,7 @@ public class MainActivity extends SpaccWebViewActivity {
@Override @Override
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url); super.onPageFinished(view, url);
if (menu != null) { refreshMenu(false);
menu.findItem(R.id.stop).setVisible(false);
menu.findItem(R.id.reload).setVisible(true);
}
if (actionBar != null && pageStartTime != 0) { if (actionBar != null && pageStartTime != 0) {
actionBar.setSubtitle("~" + (System.currentTimeMillis() - pageStartTime) + "ms"); actionBar.setSubtitle("~" + (System.currentTimeMillis() - pageStartTime) + "ms");
} }
@ -89,43 +91,33 @@ public class MainActivity extends SpaccWebViewActivity {
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { int id = item.getItemId();
case R.id.stop: if (id == R.id.stop) {
this.webView.stopLoading(); webView.stopLoading();
break; } else if (id == R.id.reload) {
case R.id.reload: webView.reload();
this.webView.reload(); } else if (id == R.id.backwards) {
break; webView.goBack();
case R.id.backwards: } else if (id == R.id.forward) {
this.webView.goBack(); webView.goForward();
break; } else if (id == R.id.copy_url) {
case R.id.forward: ApiUtils.writeToClipboard(this, webView.getUrl());
this.webView.goForward(); } else if (id == R.id.open_externally) {
break; ApiUtils.openOrShareUrl(this, Uri.parse(webView.getUrl()));
case R.id.copy_url: } else if (id == R.id.exec_script) {
ApiUtils.writeToClipboard(this, webView.getUrl()); EditText scriptText = new EditText(this);
break; new AlertDialog.Builder(this)
case R.id.open_externally: .setTitle(org.eu.spacc.spaccwebview.android.R.string.execute_javascript)
ApiUtils.openOrShareUrl(this, Uri.parse(webView.getUrl())); .setView(scriptText)
break; .setPositiveButton("OK", (dialogInterface, i) -> webView.injectScript(scriptText.getText().toString()))
case R.id.exec_script: .setNeutralButton(org.eu.spacc.spaccwebview.android.R.string.cancel, null)
EditText scriptText = new EditText(this); .show();
new AlertDialog.Builder(this) } else if (id == R.id.hide) {
.setTitle(R.string.execute_javascript) actionBar.hide();
.setView(scriptText) } else if (id == R.id.exit) {
.setPositiveButton("OK", (dialogInterface, i) -> webView.injectScript(scriptText.getText().toString())) finish();
.setNeutralButton(R.string.cancel, null) } else if (id == R.id.about_app) {
.show(); ApiUtils.openOrShareUrl(this, Uri.parse(webView.getConfig().getAboutPage()));
break;
case R.id.hide:
actionBar.hide();
break;
case R.id.exit:
finish();
break;
case R.id.about_app:
ApiUtils.openOrShareUrl(this, Uri.parse(webView.getConfig().getAboutPage()));
break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

View File

@ -1,6 +1,6 @@
package com.example.spaccwebviewapplication; package com.example.spaccwebviewapplication;
import org.eu.spacc.spaccdotweb.android.SpaccWebViewApplication; import org.eu.spacc.spaccwebview.android.SpaccWebViewApplication;
public class MainApplication extends SpaccWebViewApplication { public class MainApplication extends SpaccWebViewApplication {
// This proxy class can be left empty, // This proxy class can be left empty,

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity"> tools:context=".MainActivity">
<org.eu.spacc.spaccdotweb.android.webview.SpaccWebView <org.eu.spacc.spaccwebview.android.webview.SpaccWebView
android:id="@+id/webview" android:id="@+id/webview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
<!ENTITY about_app "About App">
<!ENTITY exit "Exit">
<!ENTITY hide "Hide">
<!ENTITY reload "Reload">
<!ENTITY stop_loading "Stop Loading">
<!ENTITY backwards "Backwards">
<!ENTITY forward "Forward">
<!ENTITY open "Open">
<!ENTITY open_externally "&open; Externally">
<!ENTITY copy_url "Copy URL">
<!ENTITY execute_javascript "Execute JavaScript">
]>
<resources>
<string name="app_name" translatable="false">SpaccWebView Application</string>
</resources>

View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,29 @@
plugins {
id 'com.android.library'
}
android {
namespace 'org.eu.spacc.spaccwebview.android'
defaultConfig {
minSdk 1
compileSdk 35
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
// testImplementation 'junit:junit:4.13.2'
// androidTestImplementation 'androidx.test.ext:junit:1.2.1'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}

View File

@ -0,0 +1,26 @@
package org.eu.spacc.spaccwebview.android;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("org.eu.spacc.spaccwebview.android.test", appContext.getPackageName());
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@ -1,7 +1,7 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccwebview.android;
import org.eu.spacc.spaccdotweb.android.Constants.*; import org.eu.spacc.spaccwebview.android.Constants.*;
import org.eu.spacc.spaccdotweb.android.helpers.ConfigReader; import org.eu.spacc.spaccwebview.android.helpers.ConfigReader;
public class Config extends Defaults { public class Config extends Defaults {
private ConfigReader configReader; private ConfigReader configReader;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccwebview.android;
public class Constants { public class Constants {
public enum ActivityCodes { UPLOAD_FILE /* , DOWNLOAD_FILE */ } public enum ActivityCodes { UPLOAD_FILE /* , DOWNLOAD_FILE */ }

View File

@ -1,6 +1,6 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccwebview.android;
import org.eu.spacc.spaccdotweb.android.Constants.*; import org.eu.spacc.spaccwebview.android.Constants.*;
public class Defaults { public class Defaults {
public static final Boolean ALLOW_JAVASCRIPT = true; public static final Boolean ALLOW_JAVASCRIPT = true;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccwebview.android;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -9,8 +9,8 @@ import android.os.Build;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import java.io.File; import java.io.File;
import org.eu.spacc.spaccdotweb.android.webview.SpaccWebChromeClient; import org.eu.spacc.spaccwebview.android.webview.SpaccWebChromeClient;
import org.eu.spacc.spaccdotweb.android.webview.SpaccWebView; import org.eu.spacc.spaccwebview.android.webview.SpaccWebView;
public class SpaccWebViewActivity extends Activity { public class SpaccWebViewActivity extends Activity {
protected SpaccWebView webView; protected SpaccWebView webView;

View File

@ -1,7 +1,7 @@
package org.eu.spacc.spaccdotweb.android; package org.eu.spacc.spaccwebview.android;
import android.app.Application; import android.app.Application;
import org.eu.spacc.spaccdotweb.android.utils.StorageUtils; import org.eu.spacc.spaccwebview.android.utils.StorageUtils;
import java.io.File; import java.io.File;
public class SpaccWebViewApplication extends Application { public class SpaccWebViewApplication extends Application {

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.helpers; package org.eu.spacc.spaccwebview.android.helpers;
import android.content.Context; import android.content.Context;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
@ -7,7 +7,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.eu.spacc.spaccdotweb.android.Constants.*; import org.eu.spacc.spaccwebview.android.Constants.*;
public class ConfigReader { public class ConfigReader {
private final Map<String, Object> configData = new HashMap<>(); private final Map<String, Object> configData = new HashMap<>();

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.helpers; package org.eu.spacc.spaccwebview.android.helpers;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -7,13 +7,14 @@ import android.content.Intent;
import android.os.Build; import android.os.Build;
import java.io.IOException; import java.io.IOException;
import org.eu.spacc.spaccdotweb.android.Constants; import org.eu.spacc.spaccwebview.android.Constants;
import org.eu.spacc.spaccdotweb.android.utils.StorageUtils; import org.eu.spacc.spaccwebview.android.R;
import org.eu.spacc.spaccdotweb.android.utils.FileUtils; import org.eu.spacc.spaccwebview.android.utils.StorageUtils;
import org.eu.spacc.spaccwebview.android.utils.FileUtils;
public class DataMoveHelper { public class DataMoveHelper {
public static void run(Context context, int labelExit, int dialogTitle, int dialogMessage) { public static void run(Context context) {
SharedPrefHelper sharedPrefHelper = new SharedPrefHelper(context); SharedPrefHelper sharedPrefHelper = new SharedPrefHelper(context);
Constants.DataLocation dataLocationReal = (StorageUtils.isInstalledOnExternalStorage(context) ? Constants.DataLocation.EXTERNAL : Constants.DataLocation.INTERNAL); Constants.DataLocation dataLocationReal = (StorageUtils.isInstalledOnExternalStorage(context) ? Constants.DataLocation.EXTERNAL : Constants.DataLocation.INTERNAL);
Integer dataLocationSaved = sharedPrefHelper.getInt("data_location"); Integer dataLocationSaved = sharedPrefHelper.getInt("data_location");
@ -21,10 +22,10 @@ public class DataMoveHelper {
sharedPrefHelper.setInt("data_location", dataLocationReal.ordinal()); sharedPrefHelper.setInt("data_location", dataLocationReal.ordinal());
} else if (!dataLocationSaved.equals(dataLocationReal.ordinal())) { } else if (!dataLocationSaved.equals(dataLocationReal.ordinal())) {
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setTitle(dialogTitle) .setTitle(R.string.move_app_data)
.setMessage(dialogMessage) .setMessage(R.string.move_app_data_info)
.setCancelable(false) .setCancelable(false)
.setNegativeButton(labelExit, (dialogInterface, i) -> ((Activity)context).finish()) .setNegativeButton(R.string.exit, (dialogInterface, i) -> ((Activity)context).finish())
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
// TODO: Check that the storage locations are all present to copy, and implement an error dialog // TODO: Check that the storage locations are all present to copy, and implement an error dialog
try { try {

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.helpers; package org.eu.spacc.spaccwebview.android.helpers;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.utils; package org.eu.spacc.spaccwebview.android.utils;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.utils; package org.eu.spacc.spaccwebview.android.utils;
import static android.content.Context.DOWNLOAD_SERVICE; import static android.content.Context.DOWNLOAD_SERVICE;
import android.app.DownloadManager; import android.app.DownloadManager;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.utils; package org.eu.spacc.spaccwebview.android.utils;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@ -7,7 +7,7 @@ import android.os.Build;
import android.os.Environment; import android.os.Environment;
import java.io.File; import java.io.File;
import org.eu.spacc.spaccdotweb.android.Constants.*; import org.eu.spacc.spaccwebview.android.Constants.*;
public class StorageUtils { public class StorageUtils {

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccwebview.android.webview;
import android.net.Uri; import android.net.Uri;

View File

@ -1,9 +1,9 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccwebview.android.webview;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import org.eu.spacc.spaccdotweb.android.utils.FileUtils; import org.eu.spacc.spaccwebview.android.utils.FileUtils;
public class DownloadListener implements android.webkit.DownloadListener { public class DownloadListener implements android.webkit.DownloadListener {
private final Context context; private final Context context;

View File

@ -1,7 +1,6 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccwebview.android.webview;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@ -11,13 +10,12 @@ import android.webkit.WebChromeClient;
import android.webkit.WebView; import android.webkit.WebView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import org.eu.spacc.spaccdotweb.android.Config; import org.eu.spacc.spaccwebview.android.Config;
import org.eu.spacc.spaccdotweb.android.Constants; import org.eu.spacc.spaccwebview.android.Constants;
import org.eu.spacc.spaccdotweb.android.SpaccWebViewActivity; import org.eu.spacc.spaccwebview.android.SpaccWebViewActivity;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils; import org.eu.spacc.spaccwebview.android.utils.ApiUtils;
public class SpaccWebChromeClient extends WebChromeClient { public class SpaccWebChromeClient extends WebChromeClient {
private final SpaccWebViewActivity activity; private final SpaccWebViewActivity activity;

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccwebview.android.webview;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
@ -11,10 +11,11 @@ import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import java.util.ArrayList; import java.util.ArrayList;
import org.eu.spacc.spaccdotweb.android.Config; import org.eu.spacc.spaccwebview.android.Config;
import org.eu.spacc.spaccdotweb.android.SpaccWebViewActivity; import org.eu.spacc.spaccwebview.android.R;
import org.eu.spacc.spaccdotweb.android.helpers.ConfigReader; import org.eu.spacc.spaccwebview.android.SpaccWebViewActivity;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils; import org.eu.spacc.spaccwebview.android.helpers.ConfigReader;
import org.eu.spacc.spaccwebview.android.utils.ApiUtils;
public class SpaccWebView extends WebView { public class SpaccWebView extends WebView {
private Config config; private Config config;
@ -22,9 +23,6 @@ public class SpaccWebView extends WebView {
private SpaccWebViewClient webViewClient; private SpaccWebViewClient webViewClient;
private SpaccWebChromeClient webChromeClient; private SpaccWebChromeClient webChromeClient;
private int openString;
private int openExternallyString;
private int copyUrlString;
private Boolean isLoaded = false; private Boolean isLoaded = false;
protected ArrayList<String> scriptQueue = new ArrayList<>(); protected ArrayList<String> scriptQueue = new ArrayList<>();
@ -48,12 +46,6 @@ public class SpaccWebView extends WebView {
this.applyConfig(context); this.applyConfig(context);
} }
public void setStrings(int open, int openExternally, int copyUrl) {
openString = open;
openExternallyString = openExternally;
copyUrlString = copyUrl;
}
@Override @Override
public void setWebViewClient(WebViewClient client) { public void setWebViewClient(WebViewClient client) {
super.setWebViewClient(client); super.setWebViewClient(client);
@ -81,19 +73,19 @@ public class SpaccWebView extends WebView {
String href = result.getExtra(); String href = result.getExtra();
if (href != null) { if (href != null) {
menu.setHeaderTitle(href); menu.setHeaderTitle(href);
menu.add(openString).setOnMenuItemClickListener(menuItem -> { menu.add(R.string.open_menu).setOnMenuItemClickListener(menuItem -> {
if (!webViewClient.shouldOverrideUrlLoading(this, href)) { if (!webViewClient.shouldOverrideUrlLoading(this, href)) {
this.loadUrl(href); this.loadUrl(href);
} }
return false; return false;
}); });
if (!ApiUtils.isInternalUrl(Uri.parse(href))) { if (!ApiUtils.isInternalUrl(Uri.parse(href))) {
menu.add(openExternallyString).setOnMenuItemClickListener(menuItem -> { menu.add(R.string.open_externally_menu).setOnMenuItemClickListener(menuItem -> {
ApiUtils.openOrShareUrl(context, Uri.parse(href)); ApiUtils.openOrShareUrl(context, Uri.parse(href));
return false; return false;
}); });
} }
menu.add(copyUrlString).setOnMenuItemClickListener(menuItem -> { menu.add(R.string.copy_url_menu).setOnMenuItemClickListener(menuItem -> {
ApiUtils.writeToClipboard(context, href); ApiUtils.writeToClipboard(context, href);
return false; return false;
}); });

View File

@ -1,4 +1,4 @@
package org.eu.spacc.spaccdotweb.android.webview; package org.eu.spacc.spaccwebview.android.webview;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -9,9 +9,9 @@ import android.webkit.WebViewClient;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Arrays; import java.util.Arrays;
import org.eu.spacc.spaccdotweb.android.Config; import org.eu.spacc.spaccwebview.android.Config;
import org.eu.spacc.spaccdotweb.android.Constants; import org.eu.spacc.spaccwebview.android.Constants;
import org.eu.spacc.spaccdotweb.android.utils.ApiUtils; import org.eu.spacc.spaccwebview.android.utils.ApiUtils;
public class SpaccWebViewClient extends WebViewClient { public class SpaccWebViewClient extends WebViewClient {
private final Context context; private final Context context;

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [ <!DOCTYPE resources [
<!ENTITY app_name "SpaccWebView Application">
<!ENTITY about_app "About App"> <!ENTITY about_app "About App">
<!ENTITY exit "Exit"> <!ENTITY exit "Exit">
<!ENTITY hide "Hide"> <!ENTITY hide "Hide">
@ -14,7 +13,6 @@
<!ENTITY execute_javascript "Execute JavaScript"> <!ENTITY execute_javascript "Execute JavaScript">
]> ]>
<resources> <resources>
<string name="app_name" translatable="false">&app_name;</string>
<string name="about_app">&about_app;</string> <string name="about_app">&about_app;</string>
<string name="about_app_menu"> &about_app;</string> <string name="about_app_menu"> &about_app;</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>

View File

@ -0,0 +1,17 @@
package org.eu.spacc.spaccwebview.android;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View File

@ -1,4 +1,4 @@
plugins { plugins {
id 'com.android.application' version '7.4.2' apply false id 'com.android.application' version '8.4.2' apply false
id 'com.android.library' version '7.4.2' apply false id 'com.android.library' version '8.4.2' apply false
} }

View File

@ -1,6 +1,7 @@
#Sun May 25 21:16:27 CEST 2025
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@ -19,4 +19,5 @@ dependencyResolutionManagement {
} }
rootProject.name = 'SpaccWebView Application' rootProject.name = 'SpaccWebView Application'
include ':app' include ':ExampleApp'
include ':SpaccWebView'