diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index b26b192..b750540 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -10,7 +10,7 @@ android {
defaultConfig {
applicationId = "com.example.lobchat"
minSdk = 30
- targetSdk = 34
+ targetSdk = 35
versionCode = 1
versionName = "1.0"
@@ -64,7 +64,8 @@ dependencies {
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.androidx.appcompat)
- implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+ implementation(libs.androidx.constraintlayout)
+ implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8fa344e..7ae3f0f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,7 @@
+
diff --git a/app/src/main/java/com/example/lobchat/MainActivity.kt b/app/src/main/java/com/example/lobchat/MainActivity.kt
index 167f44d..701e0a6 100644
--- a/app/src/main/java/com/example/lobchat/MainActivity.kt
+++ b/app/src/main/java/com/example/lobchat/MainActivity.kt
@@ -12,8 +12,6 @@ import androidx.appcompat.app.AppCompatActivity
import android.widget.Toast
import android.widget.EditText
import android.widget.Button
-import android.view.View
-import android.util.Log
class MainActivity : AppCompatActivity() {
@@ -67,77 +65,39 @@ class MainActivity : AppCompatActivity() {
}
}
- // 确保链接在 WebView 内部打开,而不是在默认浏览器中打开
- webView.webViewClient = object : WebViewClient() {
- override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
- Toast.makeText(this@MainActivity, "Network error, please try again later.", Toast.LENGTH_SHORT).show()
- }
-
- override fun onPageFinished(view: WebView?, url: String?) {
- super.onPageFinished(view, url)
- // 注入 JavaScript 来禁用 PWA 安装提示
- view?.evaluateJavascript(
- """
- window.addEventListener('beforeinstallprompt', function(e) {
- e.preventDefault();
- console.log('Install prompt blocked by WebView');
- });
- """.trimIndent(), null
- )
- // 隐藏输入框和按钮
- urlInput.visibility = View.GONE
- loadUrlButton.visibility = View.GONE
- webView.visibility = View.VISIBLE
- }
- }
-
- // 设置 WebChromeClient 以处理文件选择和 JavaScript 错误
- webView.webChromeClient = object : WebChromeClient() {
- override fun onShowFileChooser(
- webView: WebView?,
- filePathCallback: ValueCallback>,
- fileChooserParams: FileChooserParams?
- ): Boolean {
- this@MainActivity.filePathCallback?.onReceiveValue(null)
- this@MainActivity.filePathCallback = filePathCallback
-
- val intent = Intent(Intent.ACTION_GET_CONTENT)
- intent.addCategory(Intent.CATEGORY_OPENABLE)
- intent.type = "image/*"
-
- // 使用新的 ActivityResultLauncher 启动文件选择器
- fileChooserLauncher.launch(Intent.createChooser(intent, "Select Picture"))
- return true
- }
-
- override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
- Log.e("WebViewConsole", "JavaScript Error: ${consoleMessage?.message()} -- From line ${consoleMessage?.lineNumber()} of ${consoleMessage?.sourceId()}")
- return true
- }
- }
-
// 点击按钮后加载用户输入的 URL
loadUrlButton.setOnClickListener {
- var url = urlInput.text.toString().trim()
+ val url = urlInput.text.toString().trim()
+ val urlPattern = Regex("^(?:(http|https):\\/\\/)?((?:[\\w-]+\\.)+[a-z0-9]+)((?:\\/[^/?#]*)+)?(\\?[^#]+)?(#.+)?$")
+
if (url.isNotEmpty()) {
// 确保 URL 包含 http 或 https
- if (!url.startsWith("http://") && !url.startsWith("https://")) {
- url = "https://$url"
+ val formattedUrl = if (!urlPattern.matches(url)) {
+ // 如果 URL 格式不正确,则提示用户
+ Toast.makeText(this, "请输入正确的网站地址", Toast.LENGTH_SHORT).show()
+ return@setOnClickListener // 结束函数
+ } else {
+ // 确保 URL 包含 http 或 https
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
+ "https://$url"
+ } else {
+ url
+ }
}
// 保存用户输入的 URL 到 SharedPreferences
with(sharedPreferences.edit()) {
- putString(KEY_SAVED_URL, url)
+ putString(KEY_SAVED_URL, formattedUrl)
apply()
}
- // 加载用户输入的 URL
- webView.loadUrl(url)
+ // 启动 WebViewActivity
+ val intent = Intent(this, WebViewActivity::class.java)
+ intent.putExtra("URL", formattedUrl)
+ startActivity(intent)
} else {
Toast.makeText(this, "Please enter a valid URL", Toast.LENGTH_SHORT).show()
}
}
}
-
- // 此时不再需要权限检查方法
}
diff --git a/app/src/main/java/com/example/lobchat/WebViewActivity.kt b/app/src/main/java/com/example/lobchat/WebViewActivity.kt
new file mode 100644
index 0000000..6bdec34
--- /dev/null
+++ b/app/src/main/java/com/example/lobchat/WebViewActivity.kt
@@ -0,0 +1,101 @@
+package com.example.lobchat
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.util.Log
+import android.webkit.*
+import androidx.appcompat.app.AppCompatActivity
+import androidx.activity.result.ActivityResultLauncher
+import com.google.android.material.snackbar.Snackbar
+
+class WebViewActivity : AppCompatActivity() {
+
+ private lateinit var webView: WebView
+ private var filePathCallback: ValueCallback>? = null
+ private lateinit var fileChooserLauncher: ActivityResultLauncher
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_web_view) // 确保这个布局文件存在
+
+ // 初始化 WebView
+ webView = findViewById(R.id.webView)
+ setupWebView()
+
+ // 获取传递的 URL
+ val url = intent.getStringExtra("URL") // 确保这个 key 和 MainActivity 一致
+ if (!url.isNullOrEmpty()) {
+ webView.loadUrl(url)
+ } else {
+ showSnackbar("No URL provided")
+ }
+ }
+
+ private fun setupWebView() {
+ val webSettings: WebSettings = webView.settings
+ webSettings.javaScriptEnabled = true
+ webSettings.domStorageEnabled = true
+
+ webView.webViewClient = object : WebViewClient() {
+ override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
+ showSnackbar("Network error, please try again later.")
+ }
+
+ override fun onPageFinished(view: WebView?, url: String?) {
+ super.onPageFinished(view, url)
+ // 注入 JavaScript 来禁用 PWA 安装提示
+ injectJavaScript(view)
+ }
+ }
+
+ webView.webChromeClient = object : WebChromeClient() {
+ override fun onShowFileChooser(
+ webView: WebView?,
+ filePathCallback: ValueCallback>,
+ fileChooserParams: FileChooserParams?
+ ): Boolean {
+ this@WebViewActivity.filePathCallback?.onReceiveValue(null)
+ this@WebViewActivity.filePathCallback = filePathCallback
+ launchFileChooser()
+ return true
+ }
+
+ override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
+ Log.e("WebViewConsole", "JavaScript Error: ${consoleMessage?.message()} -- From line ${consoleMessage?.lineNumber()} of ${consoleMessage?.sourceId()}")
+ return true
+ }
+ }
+ }
+
+ private fun injectJavaScript(view: WebView?) {
+ view?.evaluateJavascript(
+ """
+ window.addEventListener('beforeinstallprompt', function(e) {
+ e.preventDefault();
+ console.log('Install prompt blocked by WebView');
+ });
+ """.trimIndent(), null
+ )
+ }
+
+ private fun launchFileChooser() {
+ val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
+ addCategory(Intent.CATEGORY_OPENABLE)
+ type = "image/*"
+ }
+ fileChooserLauncher.launch(Intent.createChooser(intent, "Select Picture"))
+ }
+
+ private fun showSnackbar(message: String) {
+ Snackbar.make(findViewById(android.R.id.content), message, Snackbar.LENGTH_LONG).show()
+ }
+
+ override fun onBackPressed() {
+ if (webView.canGoBack()) {
+ webView.goBack()
+ } else {
+ super.onBackPressed()
+ }
+ }
+}
diff --git a/app/src/main/res/layout/activity_web_view.xml b/app/src/main/res/layout/activity_web_view.xml
new file mode 100644
index 0000000..d5e5890
--- /dev/null
+++ b/app/src/main/res/layout/activity_web_view.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 34048d0..da39d16 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,6 @@
[versions]
agp = "8.6.0"
+constraintlayout = "2.1.4"
kotlin = "1.9.0"
coreKtx = "1.10.1"
junit = "4.13.2"
@@ -9,9 +10,11 @@ lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2024.04.01"
appcompat = "1.7.0"
+material = "1.12.0"
[libraries]
+androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
@@ -27,6 +30,7 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }