From 7fb71c27a73daa5f06f48b95e817594e7622bb61 Mon Sep 17 00:00:00 2001 From: octospacc Date: Wed, 15 Feb 2023 00:13:36 +0100 Subject: [PATCH] Some progress on hacking the webview --- .gitignore | 4 + .gitlab-ci.yml | 18 ++-- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 4 +- .../org/eu/octt/browserocto/MainActivity.java | 56 ++++++++----- .../octt/browserocto/WebWindowActivity.java | 84 +++++++++++++++++-- .../java/org/eu/octt/browserocto/_Util.java | 46 ++++++++-- app/src/main/res/layout/main.xml | 1 + tools/Build.sh | 11 +++ tools/DevBuild.sh | 6 ++ tools/tiny-android-template/includes.sh | 2 +- tools/tiny-android-template/run.sh | 25 ++++++ 12 files changed, 210 insertions(+), 51 deletions(-) create mode 100755 tools/Build.sh create mode 100755 tools/DevBuild.sh create mode 100755 tools/tiny-android-template/run.sh diff --git a/.gitignore b/.gitignore index 9074157..32f5ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ +.gradle/* +.idea/* +local.properties app/build/* +build/* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a84792c..de0136e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,22 +8,16 @@ BleedingEdge: interruptible: true stage: build script: | - mkdir -p ./AndroidSdk - cd ./AndroidSdk + StartDir="$(pwd)" + mkdir -p ../AndroidSdk + cd ../AndroidSdk wget -O BuildTools.zip https://dl.google.com/android/repository/build-tools_r30.0.3-linux.zip wget -O Platform.zip https://dl.google.com/android/repository/platform-30_r03.zip yes A | unzip BuildTools.zip || true yes A | unzip Platform.zip || true - cd .. + cd "$StartDir" - mv ./app/src/main ./main - cd ./main - mv ./java ./src - mv ../tools/tiny-android-template/* ./ - echo "${SecEncodedKeystore}" | base64 --decode > ./Keystore.jks - - perl ./link.pl - bash ./make.sh + sh ./tools/Build.sh artifacts: paths: - - main/app.apk + - build/app.apk diff --git a/app/build.gradle b/app/build.gradle index 269a9fb..b8a9706 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,7 +9,7 @@ android { minSdkVersion 1 targetSdkVersion 29 versionCode 1 - versionName "1.0.0" + versionName "1.0.1" } buildTypes { release { @@ -20,5 +20,5 @@ android { } dependencies { - //compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b087f81..4fd5ac9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="1" + android:versionName="1.0.1"> diff --git a/app/src/main/java/org/eu/octt/browserocto/MainActivity.java b/app/src/main/java/org/eu/octt/browserocto/MainActivity.java index e5b99f4..4a25ffa 100644 --- a/app/src/main/java/org/eu/octt/browserocto/MainActivity.java +++ b/app/src/main/java/org/eu/octt/browserocto/MainActivity.java @@ -48,10 +48,9 @@ public class MainActivity extends Activity { }; private Intent MakeIntBrowse(String Url, Boolean Cache) { - Intent IntBrowse = new Intent(getApplicationContext(), WebWindowActivity.class); + Intent IntBrowse = new Intent(getApplicationContext(), WebWindowActivity.class) // To get unlimited activities in general but only 1 per site, set only FLAG_ACTIVITY_NEW_DOCUMENT and put site URL in intent.setData // NOTE: This only gives a good UX on Android >= 7, for the lower versions we need to implement things differently - IntBrowse .setAction(Intent.ACTION_OPEN_DOCUMENT) .setData(Uri.parse(Url)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT /*| Intent.FLAG_ACTIVITY_MULTIPLE_TASK*/) @@ -84,50 +83,61 @@ public class MainActivity extends Activity { }; private final void CreateShortcutFallback(String Url, String Name) { - Intent IntExt = new Intent(); - IntExt.putExtra(Intent.EXTRA_SHORTCUT_INTENT, MakeIntBrowse(Url, true)); - IntExt.putExtra(Intent.EXTRA_SHORTCUT_NAME, Name); - IntExt.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.drawable.ic_launcher)); - - IntExt.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); - //IntExt.putExtra("duplicate", false); //may it's already there so don't duplicate + Intent IntExt = new Intent() + .putExtra(Intent.EXTRA_SHORTCUT_INTENT, MakeIntBrowse(Url, true)) + .putExtra(Intent.EXTRA_SHORTCUT_NAME, Name) + .putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(getApplicationContext(), R.drawable.ic_launcher)) + .setAction("com.android.launcher.action.INSTALL_SHORTCUT"); + //.putExtra("duplicate", false); //may it's already there so don't duplicate getApplicationContext().sendBroadcast(IntExt); }; - private void ShowShortcutDial(String Url) { final AlertDialog.Builder Dial = new AlertDialog.Builder(this); final String Url_ = Url; - final View v = getLayoutInflater().inflate(R.layout.dialmakeshortcut, null); - Dial.setView(v); + final View DialView = getLayoutInflater().inflate(R.layout.dialmakeshortcut, null); + Dial.setView(DialView); - final EditText EditName = v.findViewById(R.id.EditName); - //final EditText EditIcon = v.findViewById(R.id.EditIcon); + final EditText EditName = DialView.findViewById(R.id.EditName); + //final EditText EditIcon = DialView.findViewById(R.id.EditIcon); Dial.setTitle("Create Home Shortcut"); - //Dial.setCancelable(false); + Dial.setCancelable(false); + + // https://stackoverflow.com/a/15619098 + //Dial.setPositiveButton("Ok", new DialogInterface.OnClickListener() { + // @Override + // public void onClick(DialogInterface Dial, int w) { + // // Do nothing here because we override this button later to change the behavior. + // // However, we still need this because of quirks on older versions of Android. + // }; + //}); + Dial.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface Dial, int w) { + Dial.dismiss(); + }; + }); + + //Dial.show(); + + // TODO: FIX it seems we just broke this with our crap idea of hacking the dialog cancellation Dial.setPositiveButton("Ok", new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface d, int w) { + public void onClick(DialogInterface Dial, int w) { final String Name = EditName.getText().toString(); //String IconUrl = EditIcon.getText().toString(); if (!Name.equals("")) { CreateShortcut(Url_, Name); + Dial.dismiss(); } else if (Name.equals("")) { _Util.ToastMsg("Name can't be empty!", getApplicationContext()); }; }; }); - - Dial.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface d, int w) { - - }; - }); Dial.show(); }; diff --git a/app/src/main/java/org/eu/octt/browserocto/WebWindowActivity.java b/app/src/main/java/org/eu/octt/browserocto/WebWindowActivity.java index 839eb14..f9d13b9 100644 --- a/app/src/main/java/org/eu/octt/browserocto/WebWindowActivity.java +++ b/app/src/main/java/org/eu/octt/browserocto/WebWindowActivity.java @@ -5,26 +5,98 @@ import android.content.*; import android.os.*; import android.webkit.*; import android.widget.*; +import android.util.*; +import java.io.*; +import java.net.*; public class WebWindowActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.webwindow); - Bundle Extra = getIntent().getExtras(); LinearLayout LayMain = findViewById(R.id.LayMain); - + WebView Web0 = findViewById(R.id.Web0); - Web0.setWebViewClient(new WebViewClient()); + //Web0.setWebViewClient(new WebViewClient()); + + Web0.setWebViewClient(new WebViewClient() { + // https://gist.github.com/kmerrell42/b4ff31733c562a3262ee9a42f5704a89 + @Override + public WebResourceResponse shouldInterceptRequest(WebView v, String Url) { + return HandleRequest(Url); + } + @Override + public WebResourceResponse shouldInterceptRequest(WebView v, WebResourceRequest Req) { + return HandleRequest(Req.getUrl().toString()); + } + private WebResourceResponse HandleRequest(String Url) { + //Thread thread = new Thread(new Runnable() { + // @Override + // public void run() { + try { + //URL url; + //HttpURLConnection Connection = null; + URL Url_ = new URL(Url); + HttpURLConnection Connection = (HttpURLConnection)Url_.openConnection(); + String ContentType = Connection.getContentType(); + String ContentEncoding = null; + if (ContentType != null) { + ContentType = ContentType.split("\\;")[0]; + ContentEncoding = ContentType.split("\\=")[1]; + } + InputStream In = new BufferedInputStream(Connection.getInputStream()); + return new WebResourceResponse(ContentType, ContentEncoding, In); + } catch (Exception Ex) { + Log.e("browserocto/Log", "", Ex); + }; + // };//}); + return null; + }; + }); + Web0.getSettings().setJavaScriptEnabled(true); Web0.getSettings().setDomStorageEnabled(true); Web0.getSettings().setCacheMode(WhichCacheMode(Extra.getBoolean("Cache"))); + + // This is apparently not working like I want (force caching of all site resources in spite of bad Cache-Control HTTP headers) + //webView.getSettings().setAppCacheMaxSize(1024*1024*8); + //webView.getSettings().setAppCachePath("/data/data/" + getPackageName() + "/cache"); + //webView.getSettings().setAllowFileAccess(true); + //webView.getSettings().setAppCacheEnabled(true); + Web0.loadUrl(Extra.getString("Url")); - - _Util.ToastMsg(Extra.getString("Url"), getApplicationContext()); + _Util.ToastMsg(Extra.getString("Url"), this); + +// Thread thread = new Thread(new Runnable() { +// @Override +// public void run() { +// URL url; +// HttpURLConnection urlConnection = null; +// try { +// url = new URL("http://www.android.com/"); +// urlConnection = (HttpURLConnection) url.openConnection(); +// InputStream in = new BufferedInputStream(urlConnection.getInputStream()); +// runOnUiThread(new Runnable() { +// @Override +// public void run() { +// try { +// _Util.ToastMsg(_Util.StreamToString(in), getApplicationContext()); +// } catch (Exception Ex) { +// Log.e("browserocto/Log", "", Ex); +// }; +// }; +// }); +// } catch (Exception Ex) { +// Log.e("browserocto/Log", "", Ex); +// } finally { +// urlConnection.disconnect(); +// }; +// }; +// }); +// thread.start(); }; - + public int WhichCacheMode(boolean Opt) { if (Opt) { return WebSettings.LOAD_CACHE_ELSE_NETWORK; diff --git a/app/src/main/java/org/eu/octt/browserocto/_Util.java b/app/src/main/java/org/eu/octt/browserocto/_Util.java index 49445cc..3a50a43 100644 --- a/app/src/main/java/org/eu/octt/browserocto/_Util.java +++ b/app/src/main/java/org/eu/octt/browserocto/_Util.java @@ -3,20 +3,56 @@ package org.eu.octt.browserocto; import android.app.*; import android.content.*; import android.widget.*; +import java.io.*; public class _Util extends Activity { + public static boolean StartsWithOneOf(String Check, String[] With) { + for (int i=0; i + ./Keystore.jks + +perl ./link.pl +bash ./make.sh diff --git a/tools/DevBuild.sh b/tools/DevBuild.sh new file mode 100755 index 0000000..fa6acc8 --- /dev/null +++ b/tools/DevBuild.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +export SecEncodedKeystore="$(cat ../Test.jks | base64 -w0)" +export SecKeystorePassword="123456" + +sh ./tools/Build.sh diff --git a/tools/tiny-android-template/includes.sh b/tools/tiny-android-template/includes.sh index 2b01c9c..e8c2ec0 100644 --- a/tools/tiny-android-template/includes.sh +++ b/tools/tiny-android-template/includes.sh @@ -7,7 +7,7 @@ API_LEVEL_MIN="1" ANDROID_VERSION="11" NDK_VERSION="r23-beta4" TARGET_ARCHES=( "arm64-v8a" ) -SDK_DIR="../AndroidSdk" +SDK_DIR="../../AndroidSdk" KOTLIN_LIB_DIR="/usr/share/kotlin/lib" REPO="https://dl.google.com/dl/android/maven2" diff --git a/tools/tiny-android-template/run.sh b/tools/tiny-android-template/run.sh new file mode 100755 index 0000000..cfee6d2 --- /dev/null +++ b/tools/tiny-android-template/run.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +source includes.sh + +MF=`cat AndroidManifest.xml` +TERM="package=[\'\"]([a-z0-9.]+)" + +if [[ "$MF" =~ $TERM ]] +then + package="${BASH_REMATCH[1]}" + activity=".MainActivity" + + TERM="]+)" + if [[ "$MF" =~ $TERM ]]; then + tag="${BASH_REMATCH[1]}" + TERM="[\'\"]([^\'\"]+)" + [[ "$tag" =~ $TERM ]] && activity="${BASH_REMATCH[1]}" + fi + + $CMD_ADB install -r -t app.apk && \ + $CMD_ADB shell am start -n $package/$activity +else + echo Could not find a suitable package name inside AndroidManifest.xml + exit +fi