First commit, basic working app for Android > 7 (bad UX on lower versions)

This commit is contained in:
2023-02-10 16:47:34 +01:00
commit 6c382aac9d
21 changed files with 1092 additions and 0 deletions

24
app/build.gradle Normal file
View File

@ -0,0 +1,24 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "21.1.0"
defaultConfig {
applicationId "org.eu.octt.browserocto"
minSdkVersion 1
targetSdkVersion 29
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
//compile fileTree(dir: 'libs', include: ['*.jar'])
}

17
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.eu.octt.browserocto">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<application
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:resizeableActivity="true">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".WebWindowActivity"
android:label="@string/app_name"
android:exported="true">
</activity>
</application>
</manifest>

View File

@ -0,0 +1,134 @@
package org.eu.octt.browserocto;
import android.app.*;
import android.content.*;
import android.os.*;
import android.widget.*;
import android.view.View.*;
import android.view.*;
import android.net.*;
import android.content.pm.*;
import android.graphics.drawable.*;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final LinearLayout LayMain = findViewById(R.id.LayMain);
final EditText EditUrl = findViewById(R.id.EditUrl);
final Button BtnOpen = findViewById(R.id.BtnOpen);
final Button BtnShortcut = findViewById(R.id.BtnShortcut);
final Switch SwitchCache = findViewById(R.id.SwitchCache);
BtnOpen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String Url = EditUrl.getText().toString();
if (_Util.IsUrlValid(Url)) {
startActivity(MakeIntBrowse(Url, SwitchCache.isChecked()));
} else {
_Util.ToastMsg("URL is invalid!", getApplicationContext());
};
};
});
BtnShortcut.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String Url = EditUrl.getText().toString();
if (_Util.IsUrlValid(Url)) {
ShowShortcutDial(Url);
} else {
_Util.ToastMsg("URL is invalid!", getApplicationContext());
};
};
});
};
private Intent MakeIntBrowse(String Url, Boolean Cache) {
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*/)
.putExtra("Url", Url)
.putExtra("Cache", Cache);
return IntBrowse;
};
private final void CreateShortcut(String Url, String Name) {
// https://stackoverflow.com/a/51184905
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
ShortcutManager ShortMan = getApplicationContext().getSystemService(ShortcutManager.class);
if (ShortMan != null) {
if (ShortMan.isRequestPinShortcutSupported()) {
ShortcutInfo shortcut = new ShortcutInfo.Builder(getApplicationContext(), Url)
.setShortLabel(Name)
//.setLongLabel("Open the Android Document")
.setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_launcher)) // TODO Get site icon, or let user pick
//.setIcon(IconFromUrlElseDefault(Url))
.setIntent(MakeIntBrowse(Url, true))
.build();
ShortMan.requestPinShortcut(shortcut, null);
} else {
CreateShortcutFallback(Url, Name);
};
};
} else {
CreateShortcutFallback(Url, Name);
};
};
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
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 EditText EditName = v.findViewById(R.id.EditName);
//final EditText EditIcon = v.findViewById(R.id.EditIcon);
Dial.setTitle("Create Home Shortcut");
//Dial.setCancelable(false);
Dial.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface d, int w) {
final String Name = EditName.getText().toString();
//String IconUrl = EditIcon.getText().toString();
if (!Name.equals("")) {
CreateShortcut(Url_, Name);
} 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();
};
};

View File

@ -0,0 +1,34 @@
package org.eu.octt.browserocto;
import android.app.*;
import android.content.*;
import android.os.*;
import android.webkit.*;
import android.widget.*;
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.getSettings().setJavaScriptEnabled(true);
Web0.getSettings().setDomStorageEnabled(true);
Web0.getSettings().setCacheMode(WhichCacheMode(Extra.getBoolean("Cache")));
Web0.loadUrl(Extra.getString("Url"));
_Util.ToastMsg(Extra.getString("Url"), getApplicationContext());
};
public int WhichCacheMode(boolean Opt) {
if (Opt) {
return WebSettings.LOAD_CACHE_ELSE_NETWORK;
};
return WebSettings.LOAD_NO_CACHE;
};
};

View File

@ -0,0 +1,22 @@
package org.eu.octt.browserocto;
import android.app.*;
import android.content.*;
import android.widget.*;
public class _Util extends Activity {
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://"))
) {
return true;
};
return false;
};
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/LayMain"
android:gravity="center_horizontal">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp">
<!--
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reset Name"
android:padding="10dp"/>
-->
<EditText
android:layout_width="wrap_content"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/EditName"
android:padding="10dp"
android:hint="Name..."/>
</LinearLayout>
<!--
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reset Icon URL"
android:padding="10dp"/>
<EditText
android:layout_width="wrap_content"
android:ems="10"
android:layout_height="wrap_content"
android:id="@+id/EditIcon"
android:padding="10dp"/>
</LinearLayout>
-->
</LinearLayout>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/LayMain">
<EditText
android:layout_width="match_parent"
android:ems="10"
android:layout_height="wrap_content"
android:hint="URL..."
android:text="https://"
android:padding="10dp"
android:id="@+id/EditUrl"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Now"
android:padding="10dp"
android:id="@+id/BtnOpen"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Shortcut"
android:padding="10dp"
android:id="@+id/BtnShortcut"/>
</LinearLayout>
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[Open Now] Force load from local cache"
android:padding="10dp"
android:checked="true"
android:id="@+id/SwitchCache"/>
</LinearLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/LayMain">
<WebView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/Web0"/>
</LinearLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.Material.Light">
</style>
</resources>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">browserocto</string>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.Holo.Light">
</style>
</resources>