如何解决React Native 自定义 webview 在开发时防止 SSL 错误
问题
尝试在 Android 上使用 react-native-webview
连接到我的本地开发服务器。
您可以使用 http://10.0.0.2
作为默认网关来连接到模拟器上的本地机器。或者,我在手机上运行构建并连接到我机器的 IPV4 地址。
我需要 Crypto API,而该 API 仅在 HTTPS 上可用,这意味着我需要连接到 https://10.0.0.2
。
我没有使用自签名证书。
快速而肮脏的解决方案
在 handler.proceed()
包的 onReceivedSslError
方法的第一行调用 com.reactnativecommunity.webview
。
虽然这可能有效,但它不是首选方式,因为它不受源代码控制,并且需要在每次进行发布构建或全新安装项目时将其删除。
解决方案
查看下面的答案
在开发版本上创建自定义 webview 以规避 SSL 错误(或任何其他 webview 方法)。
解决方法
我的解决方案
1. 创建仅用于调试的类 CustomWebviewManager.java
我们不希望我们的自定义 webview 管理器最终出现在发布版本中。
package nl.myapp;
import android.webkit.WebView;
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.reactnativecommunity.webview.RNCWebViewManager;
@ReactModule(name = CustomWebViewManager.REACT_CLASS)
public class CustomWebViewManager extends RNCWebViewManager {
protected static final String REACT_CLASS = "RNCCustomWebView"; // React native import name
protected static class CustomWebviewClient extends RNCWebViewClient {
@Override
public void onReceivedSslError(WebView view,SslErrorHandler handler,SslError error){
// Prevent SSL errors
handler.proceed();
}
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected void addEventEmitters(ThemedReactContext reactContext,WebView view) {
// Set our custom client as webview client
view.setWebViewClient(new CustomWebviewClient());
}
}
2. 创建一个新类来注册 React Packages MyappAppPackage.java
我们应该仅在调试模式下注册我们的调试类并作为 ViewManager
。
React Native 将在下一步注册我们的包后自动调用 createViewManagers
使用 BuildConfig.DEBUG
仅在调试版本中执行。
我们不能直接实例化我们的类,因为它会导致产品构建错误。这就是我们使用 Class.forName
package nl.myapp;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyappAppPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ViewManager> viewManagers = new ArrayList<>();
if (BuildConfig.DEBUG) {
// Add custom webview manager to circumvent SSL errors
try {
Class<ViewManager> c = (Class<ViewManager>) Class.forName("nl.myapp.CustomWebViewManager");
viewManagers.add(c.newInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
return viewManagers;
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
3.注册我们的套餐
package nl.myapp;
import android.app.Application;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new MyappAppPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
...
}
4.最后在开发时使用我们的自定义 webview
把它放在单独的文件中,否则热重载将不起作用,因为requireNativeComponent
会再次尝试注册ViewManager
src/components/native/RNCCustomWebView.js
import {requireNativeComponent} from 'react-native';
module.exports = requireNativeComponent('RNCCustomWebView');
src/components/webview.js
import React from 'react';
import { WebView } from 'react-native-webview';
import RNCCustomWebView from './native/RNCCustomWebView';
// ...
const renderWebView = () => {
// ...
const nativeConfig = {};
if (__DEV__) { // __DEV__ is set by RN on debug builds
// Set custom component to circumvent SSL errors
nativeConfig.component = RNCCustomWebView;
}
return (
<WebView
nativeConfig={nativeConfig}
source="https://10.0.0.1"
/>
);
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。