feat: Add support for IP address:port access
Update regex to support IP address format Improve URL handling logic for IP addresses Update error message to reflect supported formats fix: Allow cleartext HTTP traffic Add android:usesCleartextTraffic="true" to AndroidManifest.xml Fix err_cleartext_not_permitted error perf: Optimize regex performance Precompile regex patterns as constants Use precompiled URL_PATTERN and IP_PATTERN for matching Reduce CPU overhead on each button click
This commit is contained in:
parent
789d2eea0d
commit
3d49ae565d
6 changed files with 48 additions and 13 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.WebViewApp">
|
||||
android:theme="@style/Theme.WebViewApp"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class MainActivity : AppCompatActivity() {
|
|||
companion object {
|
||||
const val SHARED_PREFS_NAME = "lobchat_prefs"
|
||||
const val KEY_SAVED_URL = "saved_url"
|
||||
private val URL_PATTERN = Regex("^(?:(http|https):\\/\\/)?((?:[\\w-]+\\.)+[a-z0-9]+|(?:\\d{1,3}\\.){3}\\d{1,3})(:\\d+)?((?:\\/[^/?#]*)+)?(\\?[^#]+)?(#.+)?$")
|
||||
private val IP_PATTERN = Regex("^(\\d{1,3}\\.){3}\\d{1,3}(:\\d+)?$")
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -40,18 +42,16 @@ class MainActivity : AppCompatActivity() {
|
|||
// 点击按钮后加载用户输入的 URL
|
||||
loadUrlButton.setOnClickListener {
|
||||
val url = urlInput.text.toString().trim()
|
||||
val urlPattern = Regex("^(?:(http|https):\\/\\/)?((?:[\\w-]+\\.)+[a-z0-9]+)((?:\\/[^/?#]*)+)?(\\?[^#]+)?(#.+)?$")
|
||||
|
||||
if (url.isNotEmpty()) {
|
||||
// 确保 URL 包含 http 或 https
|
||||
val formattedUrl = if (!urlPattern.matches(url)) {
|
||||
Toast.makeText(this, "请输入正确的网站地址", Toast.LENGTH_SHORT).show()
|
||||
val formattedUrl = if (!URL_PATTERN.matches(url)) {
|
||||
Toast.makeText(this, "请输入正确的网站地址或IP", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
} else {
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
"https://$url"
|
||||
} else {
|
||||
url
|
||||
when {
|
||||
IP_PATTERN.matches(url) -> "http://$url"
|
||||
!url.startsWith("http://") && !url.startsWith("https://") -> "https://$url"
|
||||
else -> url
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,3 +71,4 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.example.lobchat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
|
@ -23,6 +24,12 @@ class WebViewActivity : AppCompatActivity() {
|
|||
private var isLobeChatVerified = false
|
||||
private lateinit var refreshButton: FloatingActionButton
|
||||
|
||||
companion object {
|
||||
const val SHARED_PREFS_NAME = "lobchat_prefs"
|
||||
const val KEY_SAVED_URLS = "saved_urls"
|
||||
const val MAX_URL_HISTORY = 5
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -77,7 +84,9 @@ class WebViewActivity : AppCompatActivity() {
|
|||
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
validateLobeChat(view)
|
||||
if (url != null) {
|
||||
validateLobeChat(view, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +103,7 @@ class WebViewActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun validateLobeChat(view: WebView?) {
|
||||
private fun validateLobeChat(view: WebView?, url: String) {
|
||||
if (!isLobeChatVerified) {
|
||||
view?.evaluateJavascript(
|
||||
"""
|
||||
|
|
@ -107,6 +116,7 @@ class WebViewActivity : AppCompatActivity() {
|
|||
if (result == "true") {
|
||||
isLobeChatVerified = true
|
||||
Toast.makeText(this@WebViewActivity, "LobeChat validation passed", Toast.LENGTH_SHORT).show()
|
||||
saveUrlToHistory(url)
|
||||
} else {
|
||||
handleLobeChatValidationFailure()
|
||||
}
|
||||
|
|
@ -114,6 +124,28 @@ class WebViewActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveUrlToHistory(url: String) {
|
||||
val sharedPreferences = getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val urls = sharedPreferences.getStringSet(KEY_SAVED_URLS, mutableSetOf())?.toMutableList() ?: mutableListOf()
|
||||
|
||||
// Remove the URL if it already exists
|
||||
urls.remove(url)
|
||||
|
||||
// Add the URL to the beginning of the list
|
||||
urls.add(0, url)
|
||||
|
||||
// Ensure the list does not exceed the maximum size
|
||||
if (urls.size > MAX_URL_HISTORY) {
|
||||
urls.removeAt(urls.size - 1)
|
||||
}
|
||||
|
||||
// Save the updated list back to SharedPreferences
|
||||
with(sharedPreferences.edit()) {
|
||||
putStringSet(KEY_SAVED_URLS, urls.toSet())
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLobeChatValidationFailure() {
|
||||
Toast.makeText(this@WebViewActivity, "The webpage does not contain the required LobeChat text in the header.", Toast.LENGTH_LONG).show()
|
||||
val intent = Intent(this@WebViewActivity, MainActivity::class.java)
|
||||
|
|
|
|||
Loading…
Reference in a new issue