Some progress on hacking the webview
This commit is contained in:
parent
a1caff328d
commit
7fb71c27a7
|
@ -1 +1,5 @@
|
|||
.gradle/*
|
||||
.idea/*
|
||||
local.properties
|
||||
app/build/*
|
||||
build/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'])
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.eu.octt.browserocto"
|
||||
android:versionCode="0"
|
||||
android:versionName="0">
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0.1">
|
||||
<uses-sdk android:minSdkVersion="1" android:targetSdkVersion="30"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<With.length; i++) {
|
||||
if (Check.startsWith(With[i])) {
|
||||
return true;
|
||||
};
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
public static boolean EqualsOneOf(String Check, String[] With) {
|
||||
for (int i=0; i<With.length; i++) {
|
||||
if (Check.equals(With[i])) {
|
||||
return true;
|
||||
};
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
public static void ToastMsg(String Msg, Context c) {
|
||||
Toast.makeText(c, Msg, Toast.LENGTH_SHORT).show();
|
||||
};
|
||||
|
||||
public static boolean IsUrlValid(String Url) {
|
||||
Url = Url.toLowerCase();
|
||||
if (
|
||||
(Url.startsWith("file://") || Url.startsWith("http://") || Url.startsWith("https://"))
|
||||
&& !(Url.equals("file://") || Url.equals("http://") || Url.equals("https://"))
|
||||
) {
|
||||
Url = Url.trim().toLowerCase();
|
||||
String[] Prefixes = {"file://", "http://", "https://", "data:", "javascript:"};
|
||||
if (StartsWithOneOf(Url, Prefixes) && !EqualsOneOf(Url, Prefixes)) {
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/a/5713929
|
||||
public static String StreamToString(InputStream is) throws IOException {
|
||||
if (is != null) {
|
||||
Writer writer = new StringWriter();
|
||||
char[] buffer = new char[1024];
|
||||
try {
|
||||
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
||||
int n;
|
||||
while ((n = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, n);
|
||||
};
|
||||
} finally {
|
||||
is.close();
|
||||
};
|
||||
return writer.toString();
|
||||
};
|
||||
return "";
|
||||
};
|
||||
};
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- TODO: Make this be CheckBox on Android < ICS because Switch doesn't exist -->
|
||||
<Switch
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
rm -rf ./build || true
|
||||
cp -r ./app/src/main ./build
|
||||
cd ./build
|
||||
mv ./java ./src
|
||||
cp -r ../tools/tiny-android-template/* ./
|
||||
echo "${SecEncodedKeystore}" | base64 --decode > ./Keystore.jks
|
||||
|
||||
perl ./link.pl
|
||||
bash ./make.sh
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
export SecEncodedKeystore="$(cat ../Test.jks | base64 -w0)"
|
||||
export SecKeystorePassword="123456"
|
||||
|
||||
sh ./tools/Build.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"
|
||||
|
|
|
@ -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="<activity([^>]+)"
|
||||
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
|
Loading…
Reference in New Issue