版本/工具说明
- 开发工具:
- IntelliJ IDEA 2022.2.5 (已安装安卓环境)
- gradle-7.3.3
安卓应用前置条件
1.新建安卓项目
2.安装 gradle 与配置使用
- 为了避免构建出现 gradle:Connection timed out 的报错,gradle 版本需要在 gradle-wrapper.properties 文件里查看下载(注意,版本一定不能错。)
- 下载之后在设置里面配置 gradle 路径
- 确定之后, IDEA 会自动构建, 构建时间可能有点长, 需耐心等待
步骤
如果你想在安卓应用中固定一个指定的 URL,并且通过 WebView 显示一个 H5 页面,可以按照以下步骤来实现:
1.添加权限
- 确保你的应用具有访问互联网的权限,在 AndroidManifest.xml 中加入以下权限:
<uses-permission android:name="android.permission.INTERNET" />
2.创建 WebView 布局
- 在你的 activity_main.xml 或其他布局文件中,添加一个 WebView 控件
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
3.配置 WebView
- 在你的 MainActivity.java 中,设置 WebView 加载指定的 URL:
package cn.odjbin.ribtest;
import android.annotation.SuppressLint;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
//开启 JavaScript 支持
webView.getSettings().setJavaScriptEnabled(true);
//设置 WebViewClient,避免点击链接时跳转到浏览器
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
//固定指定 URL
//跳转到外部浏览器
return !request.getUrl().toString().equals("http://xxx");//在 WebView 中加载
}
});
//加载指定 URL
webView.loadUrl("http://xxx");
}
@Override
public void onBackPressed() {
//让 WebView 支持返回键回退功能
if(webView.canGoBack()){
webView.goBack();
}else{
super.onBackPressed();
}
}
}
运行调试: 我这边选择手机的无线调试
问题 1: net:ERR_CLEARTEXT_NOT_PREMITTEN
-
net::ERR_CLEARTEXT_NOT_PERMITTED 错误通常发生在 Android 9.0(API 级别 28)及更高版本中,当你的应用尝试通过 HTTP(即非加密的清晰文本连接)访问一个 URL 时,Android 出于安全考虑会阻止这种行为。
-
默认情况下,Android 9 及以上版本要求所有的网络请求都使用 HTTPS(加密的连接)。
解决办法:
-
1.使用 HTTPS(推荐)
-
2.允许 HTTP 请求(不推荐,只有在特殊情况下使用)
如果你必须通过 HTTP 访问某个 URL,可以通过以下方法修改应用的配置,允许清晰文本 HTTP 连接。
- ①在 AndroidManifest.xml 中启用 Cleartext 支持
在你的 AndroidManifest.xml 文件中的 <application 标签内,加入以下代码:
android:usesCleartextTraffic="true"
这会告诉系统允许应用进行 HTTP 请求。
- ②为特定域名配置 Cleartext 支持(推荐方式)
为了更细粒度地控制,可以在 network_security_config.xml 文件中指定哪些域名允许使用 HTTP。
首先,创建一个 res/xml/network_security_config.xml 文件(如果没有的话),并添加如下内容:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">yourdomain.com</domain>
</domain-config>
</network-security-config>
然后,确保在 AndroidManifest.xml 中<application 引用这个配置文件:
android:networkSecurityConfig="@xml/network_security_config"
这样,你只会允许 yourdomain.com 使用 HTTP,而其他域名仍然要求使用 HTTPS。
- ③避免使用 HTTP 连接
如果是你自己控制的服务器或第三方 API,建议尽可能支持 HTTPS,这不仅能解决此问题,还能提高数据传输的安全性。
问题 2: 安卓 WebView 中加载的 H5 网页内无法进行路由切换
通常是因为 WebView 在加载页面时并未正确处理 SPA(单页应用)路由,或者是页面上的 JavaScript 路由(例如 Vue Router、React Router 等)没有正确响应 URL 路径的变化。
解决办法:
MainActivity.java
- 开启 JavaScript 支持
webView.getSettings().setJavaScriptEnabled(true);
- 修改 WebViewClient 的拦截逻辑
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
// 只拦截外部链接,自己域名的放行
if (url.startsWith("https://yourdomain.com")) {
return false; // 交给 WebView 内部处理
} else {
// 外链交给系统浏览器处理
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
});
问题 3: WebView 嵌入 url 后, 网站中 文件上传调用相册, 如何实现
在 Android 的 WebView 中实现 H5 网页调用设备的相册进行文件上传,需要正确配置 WebView 和处理文件选择的回调逻辑。
解决办法:
MainActivity.java
- 定义全局变量和常量
private ValueCallback<Uri[]> filePathCallback; // 文件选择回调(适用于 Android 5.0+)
private Uri cameraUri;
- 1.启用文件上传功能
确保 WebView 的设置支持文件上传:
webView.getSettings().setJavaScriptEnabled(true); // 启用 JavaScript
webView.getSettings().setAllowFileAccess(true); // 允许访问文件
webView.getSettings().setAllowContentAccess(true); // 允许内容访问
问题 3.1: 'startActivityForResult(android.content.Intent, int)' 已弃用
在 Android 11(API 30) 之后,startActivityForResult() 和 onActivityResult() 已被 弃用,
推荐使用 新的 Activity Result API (registerForActivityResult()) 来处理,比如文件选择、拍照、权限请求等
解决办法: 创建新的 Activity Result API
private final ActivityResultLauncher<Intent> fileChooserLauncher=registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),result -> {
if(filePathCallback==null)return;
Uri[] results = null;
if(result.getResultCode()== Activity.RESULT_OK){
Intent data=result.getData();
if(data==null){
// 拍照
if (cameraUri != null) {
results = new Uri[]{cameraUri};
}
}else{
Uri uriData =data.getData();
if(uriData !=null){
results = new Uri[]{uriData };
}
}
}
// ✅ 必须调用,不管有没有结果,否则第二次不再触发
filePathCallback.onReceiveValue(results);
filePathCallback=null;
cameraUri = null;
});
问题 3.2: WebView 文件上传第二次点击无反应
出现的原因几乎都是:
📌 第一次回调后,没有正确调用 filePathCallback.onReceiveValue(null) 清空回调对象。
导致 WebView 认为上一个文件选择请求还没结束,从而不再触发第二次选择。
- 2.处理文件选择回调
通过重写 WebChromeClient,处理文件选择器的调用。
//2. 处理文件选择回调
webView.setWebChromeClient(new WebChromeClient() {
//用于处理文件选择的回调
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
//先清理上一次残留的 callback, 防止"第二次无响应"
if(MainActivity.this.filePathCallback!=null){
MainActivity.this.filePathCallback.onReceiveValue(null);
MainActivity.this.filePathCallback=null;
}
// 保存回调
MainActivity.this.filePathCallback=filePathCallback;
//调用系统相册或文件选择器
Intent intent = fileChooserParams.createIntent();
try {
//使用新的 Launcher 启动
fileChooserLauncher.launch(intent);
} catch (ActivityNotFoundException e) {
MainActivity.this.filePathCallback = null;
Toast.makeText(MainActivity.this, "无法打开文件选择器", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
});




