在Kotlin中开发Android应用时,如果你想要在WebView
中处理HTML5的<input type="file">
标签以触发文件选择器,你可以结合使用registerForActivityResult
(也称为rememberLauncherForActivityResult
,但在Fragment中更常用的是前者)和WebChromeClient
。以下是一个在Activity中实现的示例代码,展示了如何设置WebView
并处理文件选择。
在你的Activity中,设置WebView
,并注册一个用于处理文件选择的ActivityResultLauncher
,同时设置WebChromeClient
以监听文件选择器的请求:
import android.content.Intent import android.net.Uri import android.os.Bundle import android.webkit.ValueCallback import android.webkit.WebChromeClient import android.webkit.WebView import android.webkit.WebViewClient import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { private lateinit var webView: WebView private lateinit var fileChooserLauncher: ActivityResultLauncher<Intent> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) webView = findViewById(R.id.webview) // 设置WebViewClient处理页面加载 webView.webViewClient = WebViewClient() // 设置WebChromeClient处理文件选择等 webView.webChromeClient = object : WebChromeClient() { override fun onShowFileChooser( webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams? ): Boolean { // 创建Intent来启动文件选择器 val intent = Intent(Intent.ACTION_GET_CONTENT) intent.type = "*/*" // 设置MIME类型,这里表示所有类型 intent.addCategory(Intent.CATEGORY_OPENABLE) // 使用ActivityResultLauncher启动Intent fileChooserLauncher.launch(intent) // 必须返回true,表示文件选择器将被处理 return true } } // 加载网页 webView.loadUrl("https://your-website.com/page-with-file-input.html") // 注册ActivityResultLauncher以处理文件选择结果 fileChooserLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { // 处理选择的文件,这里假设filePathCallback是全局可访问的 // 注意:在实际应用中,filePathCallback可能不是全局的,你需要通过其他方式传递它 // 例如,你可以将WebView的引用和filePathCallback一起传递给一个自定义的类,该类将处理文件选择 // 这里只是示例,所以省略了这部分逻辑 // 假设你有一个全局的filePathCallback变量 // filePathCallback?.onReceiveValue(arrayOf(result.data?.data)) } } } // 注意:上面的filePathCallback处理是简化的,实际中你可能需要不同的逻辑 // 因为在WebChromeClient的onShowFileChooser方法中,filePathCallback是局部的 // 你需要找到一种方法来在文件选择结果返回时调用它 // 一种可能的解决方案是使用弱引用或全局变量(但请注意内存泄漏的风险) // 或者,你可以将WebView的引用和filePathCallback一起封装在一个自定义的类中 }
注意:上面的代码示例中,filePathCallback
的处理是简化的,因为在实际情况下,filePathCallback
是在onShowFileChooser
的局部作用域中定义的,并且不是全局可访问的。因此,你需要找到一种方法来在文件选择结果返回时调用它。
一种常见的做法是将WebView
的引用和filePathCallback
一起封装在一个自定义的类中,该类将负责处理文件选择请求和结果。这样,你就可以在文件选择结果返回时,通过该类的实例来调用filePathCallback
。