您的位置:首页 > 移动开发 > 微信开发

Android H5微信支付 webview设置referer 请求头无效问题解释和详细处理方案

2018-03-11 16:38 856 查看
Android H5微信支付(或H5视频链接)webview设置referer 请求头无效问题解释和详细处理方案(附源码)

本文说明

这次也是项目中所碰到的问题总结,这次是项目需要对接新的一套第三方微信H5支付。其实开始是很简单的只需要一个集合了所以必要参数后提交后台返回的支付链接再加上订单号就没有问题,不过由于特殊的ios 内购要求(对内购非常严)和对接情况都将按ios的来。

对接流程

通常对接流程

按ios流程对接

问题产生

问题背景

案发现场
案发现场还原一

结果

关键就是在这段代码

解决方法

案发现场还原二

结果

解决方法

案发现场三

解决方法

最终完整方案

可能出现的版本问题

友情提示

对接流程

通常对接流程

前端提交必要参数到后台———-后台生成支付加密链接返回给前端———-前端可以拼接订单id调用微信H5(或者可以直接请求,有的需要提交在webview请求头) ———– 支付完成(回调成功失败)

按ios流程对接

前端提交必要参数到后台———-后台生成支付加密链接返回给前端———-前端需要使用webview请求 过程中需要在链接中添加请求头Referer ———– 支付完成(回调成功失败)

问题产生

问题背景

我们在配合第三方支付的技术时,对方表示必要参数是可以前端或者后台任意一个可以拼接的参数生成支付链接,但是提交到微信H5 则是后台表示无法执行的,由前端来做,那么问题就产生了。

IOS 在使用webView是有原生的方法的可以非常方便的将请求头添加到支付链接上,所以很快就解决了,而且没有任何兼容的问题。

Android 就不一样了,由于个人对webView没有过深入了解,所以当时还真不知道webView有添加请求头的方法,后来发现确实有这个方法。

public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {

}


但是在使用过程中发现问题: 请求头没有添加上。

案发现场

案发现场还原一

上代码

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.achers.ascmake.R;
import java.util.HashMap;
import java.util.Map;

/**
* Create on 2018/3/8 14:42
* <p>
* author lhm
* <p>
* Description:
* <p>
* Version: 1.2.3
*/
public class WebChonzhiAcvitity extends AppCompatActivity {

private Context context = this;
private String url;
private String initUrl;//不拼接UserID的URL
private String title;

private WebView mWebView;
private boolean isFirstLoad = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webchongzhi);
//初始化
initView();

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mWebView.setWebViewClient(new WebViewClient() {

@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}

@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
}

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();  // 接受所有网站的证书
super.onReceivedSslError(view, handler, error);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
Map headers = new HashMap();
if (url1.contains("wx.tenpay.com")) {
//wx.tenpay.com 收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第二次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台请求头 一般是对方固定
} else {
//payh5.bbnpay
if(!isFirstLoad){
//跳转到收银台
headers.put("Referer", "https://xxx.xxxx.cn");//商户申请H5时提交的授权域名
isFirstLoad = true;
}else{
//收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第一次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台请求头 一般是对方固定

}
}
view.loadUrl(url1, headers);

14fb4
return true;
}

});
String Referer="https://xxx.xxxx.cn";  //需要添加到支付链接的请求头
String targetUrl=";  //后台返回的支付链接
if (("4.4.3".equals(android.os.Build.VERSION.RELEASE))
|| ("4.4.4".equals(android.os.Build.VERSION.RELEASE))) {
//兼容这两个版本设置referer无效的问题
mWebView.loadDataWithBaseURL("https://xxx.xxxx.cn",
"<script>window.location.href=\"" + targetUrl + "\";</script>",
"text/html", "utf-8", null);
} else {
Map<String, String> extraHeaders = new HashMap<>();
extraHeaders.put("Referer", "https://xxx.xxxx.cn");
mWebView.loadUrl(targetUrl, extraHeaders);
//  }
}

@Override
protected void onResume() {
super.onResume();
mWebView.onResume();
}

private void initView() {
// TODO Auto-generated method stub
// customViewContainer = (FrameLayout)

mWebView = (WebView) findViewById(R.id.web);
WebSettings webSettings = mWebView.getSettings();
mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
String appCachePath = context.getApplicationContext().getCacheDir()
.getAbsolutePath();
webSettings.setAppCachePath(appCachePath);
webSettings.setAllowFileAccess(true);
webSettings.setAppCacheEnabled(true);
}

@Override
protected void onPause() {
super.onPause();
mWebView.onPause();

}

@Override
protected void onDestroy() {
try {
if (mWebView != null) {
if (null != mWebView.getParent()) {
((ViewGroup) mWebView.getParent()).removeView(mWebView);
}
mWebView.removeAllViews();
mWebView.destroy();
}
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
}


结果



手机系统5.1

通过抓包发现 请求头并没有加上。

但是发现请求头在第一次的时候是加上了,但是被第二次重复加载的时候给默认覆盖了。

关键就是在这段代码

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
Map headers = new HashMap();
if (url1.contains("wx.tenpay.com")) {
//wx.tenpay.com 收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第二次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台商请求头 一般是对方固定
} else {
//payh5.bbnpay
if(!isFirstLoad){
//跳转到收银台
headers.put("Referer", "https://xxx.xxxx.cn");//商户申请H5时提交的授权域名
isFirstLoad = true;
}else{
//收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第一次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台商请求头 一般是对方固定

}
}
view.loadUrl(url1, headers);
return true;
}


这段代码也已经写得很清楚了,在与微信H5 交互的时候他这个shouldOverrideUrlLoading会调 用两次 所以第一次加上的请求头被第二次没加的请求头给默认覆盖了。

解决方法

初始化的时候就添加一次请求头,在调用shouldOverrideUrlLoading 再添加一次请求头

案发现场还原二

@Route(path = Path.PFWebView)
public class PFWebViewActivity extends BaseBarActivity {

@BindView(R.id.webView)
WebView mWebView;
@BindView(R.id.progressBar)
ProgressBar pg;
@Autowired
Param param;
private HashMap<String, String> stringStringHashMap;

@Override
public void initLayout() {
setContentView(R.layout.activity_web_view);
}

@Override
protected void initTitleBar() {

}

@Override
protected void initData() {
param.url="后台返回的支付链接";
stringStringHashMap = new HashMap<>();
stringStringHashMap.put("Referer", "https://shop.cp988.cn");
mWebView.loadUrl(param.url, stringStringHashMap);

WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);//支持javascript
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//设置允许js弹出alert对话框
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  //设置 缓存模式
webSettings.setUseWideViewPort(true);//扩大比例的缩放
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);//自适应屏幕
webSettings.setLoadWithOverviewMode(true);

mWebView.requestFocus();//触摸焦点起作用
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);//取消滚动条

//设置了Alert才会弹出,重新onJsAlert()方法return true可以自定义处理信息
mWebView.setWebChromeClient(new WebClient());
mWebView.setWebViewClient(new TheWebViewClient());
}

class WebClient extends WebChromeClient {

@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return true;
}

@Override
public void onProgressChanged(WebView view, int i) {
super.onProgressChanged(view, i);
pg.setVisibility(i == 100 ? View.GONE : View.VISIBLE);
pg.setProgress(i);
}

}

boolean isFirstLoad = false;

/**
* 和H5的交互
*/
class TheWebViewClient extends android.webkit.WebViewClient {

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
Map<String, String> headers = new HashMap<>();
if (url1.contains("wx.tenpay.com")) {
//wx.tenpay.com 收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第二次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台商请求头 一般是对方固定
} else {
//payh5.bbnpay
if(!isFirstLoad){
//跳转到收银台
headers.put("Referer", "https://xxx.xxxx.cn");//商户申请H5时提交的授权域名
isFirstLoad = true;
}else{
//收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第一次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台商请求头 一般是对方固定
}
}
UtilsLog.logger("shouldOverrideUrlLoading>>" + url1);
view.loadUrl(url1, headers);
return true;
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
showLoadingTransparent();
super.onPageStarted(view, url, favicon);
UtilsLog.logger(url);
}

@Override
public void onPageFinished(WebView view, String url) {
disableLoadingTransparent();
super.onPageFinished(view, url);
UtilsLog.logger(url);
}

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
super.onReceivedSslError(view, handler, error);
}

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
//    view.loadUrl(url, stringStringHashMap);
UtilsLog.logger(url);
return super.shouldInterceptRequest(view, url);
}
}

/**
* 网页回退
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();// 返回前一个页面
return true;
}

return super.onKeyDown(keyCode, event);
}

@Override
protected void onDestroy() {
checkSign();
if (mWebView != null) {
mWebView.setVisibility(View.GONE);
mWebView.removeAllViews();
mWebView.destroy();
releaseAllWebViewCallback();
}
super.onDestroy();
}

private void checkSign() {
if (param.title.equals("签到")) {
RxBus.getInstance().post(new EventModel(EventId.checkh5SignState));
}
}

/**
* 防止内存泄露
*/
public void releaseAllWebViewCallback() {
try {
Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
if (sConfigCallback != null) {
sConfigCallback.setAccessible(true);
sConfigCallback.set(null, null);
}
} catch (NoSuchFieldException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
} catch (ClassNotFoundException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
} catch (IllegalAccessException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
}
}

}


结果

webview加载网页出现(“找不到网页net:err_unknown_url_scheme”)

这样表示你已经成功一半了,因为这样的结果表示链接已经加上了请求头 只是没有调用到微信而已

解决方法

通过根据scheme 协议作出响应跳转

/**
* 根据scheme 协议作出响应跳转是跳系统浏览器还是应用内页面还是用webView 打开
*/
public void doSchemeJump(String linkUrl, Map<String, String> headers) {
try {
UtilsLog.logger("doSchemeJump>>" + linkUrl);
if (!TextUtils.isEmpty(linkUrl)) {
Uri uri = Uri.parse(linkUrl);
String scheme = uri.getScheme();

if (scheme.equals("http") || scheme.equals("https")) {
UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

loadUrl(linkUrl, uri, headers);
} else {
// 调用系统浏览器
UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

openBrowser(linkUrl);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

private void loadUrl(String linkUrl, Uri uri, Map<String, String> headers) {
Bundle bundle = parseExtras(uri);
if (bundle != null) {
if (bundle.containsKey("scheme")) {
String scheme = bundle.getString("scheme");
if (scheme != null && scheme.startsWith("alipays")) {
String schemeUrl = URLDecoder.decode(scheme);
try {
UtilsLog.logger("loadUrl>>open>>" + linkUrl);

open(schemeUrl);
} catch (Exception e) {
e.printStackTrace();
openBrowser(linkUrl);
finish();
}
return;
}
}
}
UtilsLog.logger("loadUrl>>webview加载url>>" + linkUrl);

mWebView.loadUrl(linkUrl, headers);
}

public static Bundle parseExtras(Uri uri) {
Bundle extras = null;
Set<String> queryParameterNames = uri.getQueryParameterNames();
for (String key : queryParameterNames) {
String value = uri.getQueryParameter(key);
if (extras == null) {
extras = new Bundle();
}
extras.putString(key, value);
}

return extras;
}

private void openBrowser(String url) {
try {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}

private void open(String url) throws URISyntaxException {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
startActivity(intent);
}


案发现场三

结合案发一和案发二的修改代码执行,发现锤子手机Pro2 (Android 7.1)没有任何问题的调用到微信支付页面,但是其他手机都可以,在支付请求成功之后,请求头成功添加,但是在调用的时候直接崩溃,当时以为是机型问题,毕竟有手机是可以的,经过测试 三星(Android 7.1) oppo(Android 5.1) vivo(Android 6.0) 华为(Android 4.4) 小米(Android 7.1) 都不可以,这就不是什么机型问题了,而是代码问题。

经过断点debug 发现问题出这行代码

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
view.loadUrl(url, stringStringHashMap);
UtilsLog.logger(url);
return super.shouldInterceptRequest(view, url);
}


解决方法

简单粗暴,直接去掉就好。

但是我们还是要知道 这句代码到底影响了什么

WebResourceResponse shouldInterceptRequest 在每一次请求资源时,都会通过这个函数来回调 那么这个方法可以干什么可以拦截,对链接进行二次处理,这也是为什么当初会加这段代码的因为就是担心请求头没有加上。

这个方法在调用微信的时候结合起来的次数总共达到3次,那么崩溃原因就在于与微信H5交互时的3次连续重复调用 导致资源冲突问题。

最终完整方案

@Route(path = Path.PFWebView)
public class PFWebViewActivity extends BaseBarActivity {

@BindView(R.id.webView)
WebView mWebView;
@BindView(R.id.progressBar)
ProgressBar pg;
@Autowired
Param param;
private HashMap<String, String> stringStringHashMap;

@Override
public void initLayout() {
setContentView(R.layout.activity_web_view);
}

@Override
protected void initTitleBar() {

}

@Override
protected void initData() {
titleBar.setVisibility(View.GONE);
stringStringHashMap = new HashMap<>();
stringStringHashMap.put("Referer", "https://xxx.xxxx.cn");
mWebView.loadUrl(param.url, stringStringHashMap);

WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);//支持javascript
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//设置允许js弹出alert对话框
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  //设置 缓存模式
webSettings.setUseWideViewPort(true);//扩大比例的缩放
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);//自适应屏幕
webSettings.setLoadWithOverviewMode(true);

mWebView.requestFocus();//触摸焦点起作用
mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);//取消滚动条

//设置了Alert才会弹出,重新onJsAlert()方法return true可以自定义处理信息
mWebView.setWebChromeClient(new WebClient());
mWebView.setWebViewClient(new TheWebViewClient());
}

class WebClient extends WebChromeClient {

@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return true;
}

@Override
public void onProgressChanged(WebView view, int i) {
super.onProgressChanged(view, i);
pg.setVisibility(i == 100 ? View.GONE : View.VISIBLE);
pg.setProgress(i);
}

}

boolean isFirstLoad = false;

/**
* 和H5的交互
*/
class TheWebViewClient extends android.webkit.WebViewClient {

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url1) {
Map<String, String> headers = new HashMap<>();
if (url1.contains("wx.tenpay.com")) {
//wx.tenpay.com 收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第二次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台请求头 一般是对方固定
} else {
//payh5.bbnpay
if(!isFirstLoad){
//跳转到收银台
headers.put("Referer", "https://xxx.xxxx.cn");//商户申请H5时提交的授权域名
isFirstLoad = true;
}else{
//收银台点击微信时,shouldOverrideUrlLoading会调用两次,这里是第一次
headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平台请求头 一般是对方固定
}
}
UtilsLog.logger("shouldOverrideUrlLoading>>" + url1);
doSchemeJump(url1, headers);
//view.loadUrl(url1, headers);
return true;
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
showLoadingTransparent();
super.onPageStarted(view, url, favicon);
UtilsLog.logger(url);
}

@Override
public void onPageFinished(WebView view, String url) {
disableLoadingTransparent();
super.onPageFinished(view, url);
UtilsLog.logger(url);
}

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
super.onReceivedSslError(view, handler, error);
}

}

/**
* 根据scheme 协议作出响应跳转是跳系统浏览器还是应用内页面还是用webView 打开
*/
public void doSchemeJump(String linkUrl, Map<String, String> headers) {
try {
UtilsLog.logger("doSchemeJump>>" + linkUrl);
if (!TextUtils.isEmpty(linkUrl)) {
Uri uri = Uri.parse(linkUrl);
String scheme = uri.getScheme();

if (scheme.equals("http") || scheme.equals("https")) {
UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

loadUrl(linkUrl, uri, headers);
} else {
// 调用系统浏览器
UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

openBrowser(linkUrl);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

private void loadUrl(String linkUrl, Uri uri, Map<String, String> headers) {
Bundle bundle = parseExtras(uri);
if (bundle != null) {
if (bundle.containsKey("scheme")) {
String scheme = bundle.getString("scheme");
if (scheme != null && scheme.startsWith("alipays")) {
String schemeUrl = URLDecoder.decode(scheme);
try {
UtilsLog.logger("loadUrl>>open>>" + linkUrl);

open(schemeUrl);
} catch (Exception e) {
e.printStackTrace();
openBrowser(linkUrl);
finish();
}
return;
}
}
}
UtilsLog.logger("loadUrl>>webview加载url>>" + linkUrl);

mWebView.loadUrl(linkUrl, headers);
}

public static Bundle parseExtras(Uri uri) {
Bundle extras = null;
Set<String> queryParameterNames = uri.getQueryParameterNames();
for (String key : queryParameterNames) {
String value = uri.getQueryParameter(key);
if (extras == null) {
extras = new Bundle();
}
extras.putString(key, value);
}

return extras;
}

private void openBrowser(String url) {
try {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}

private void open(String url) throws URISyntaxException {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
intent.addCategory("android.intent.category.BROWSABLE");
intent.setComponent(null);
startActivity(intent);
}

/**
* 网页回退
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();// 返回前一个页面
return true;
}

return super.onKeyDown(keyCode, event);
}

@Override
protected void onDestroy() {
checkSign();
if (mWebView != null) {
mWebView.setVisibility(View.GONE);
mWebView.removeAllViews();
mWebView.destroy();
releaseAllWebViewCallback();
}
super.onDestroy();
}

private void checkSign() {
if (param.title.equals("签到")) {
RxBus.getInstance().post(new EventModel(EventId.checkh5SignState));
}
}

/**
* 防止内存泄露
*/
public void releaseAllWebViewCallback() {
try {
Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
if (sConfigCallback != null) {
sConfigCallback.setAccessible(true);
sConfigCallback.set(null, null);
}
} catch (NoSuchFieldException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
} catch (ClassNotFoundException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
} catch (IllegalAccessException e) {
UtilsLog.log("ActivityWebView.class::" + e.toString());
}
}

@Override
protected void onPause() {
super.onPause();
finish();
}
}


可能出现的版本问题

在4.4.4、4.4.3的设备上,设置的Referer没有生效

if (("4.4.3".equals(android.os.Build.VERSION.RELEASE))
|| ("4.4.4".equals(android.os.Build.VERSION.RELEASE))) {
//兼容这两个版本设置referer无效的问题
view.loadDataWithBaseURL("商户申请H5时提交的授权域名",
"<script>window.location.href=\"" + targetUrl + "\";</script>",
"text/html", "utf-8", null);
} else {
Map<String, String> extraHeaders = new HashMap<>();
extraHeaders.put("Referer", "商户申请H5时提交的授权域名");
view.loadUrl(targetUrl, extraHeaders);
}


友情提示

本文源码 使用了阿里ARouter 和继承了基类base 按需求删除替换就好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息