WebView篇
安卓WebView
一,安卓weiView接入如下,在安卓程序启动时调用下面方法
private void InitWebView()
{
//动态创建一个WebView对象并添加到LinearLayout中
webView = new WebView(this);
WebSettings webSetting=webView.getSettings();
webSetting.setLoadWithOverviewMode(true);
webSetting.setJavaScriptEnabled(true);
//此处”paraConfig”即Javascript接口名,在Javascript中通过这个接口调用Java函数。这里使用Activity作为目标对象,所以Activity类中必须有public属性的接口函数供Javascript调用。
webView.addJavascriptInterface(this, "paraConfig");
//不跳转到其他浏览器,必须要调用url拦截,不然不能请求非http和https链接
webView.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
Log.i("Unity","shouldOverrideUrlLoading++++++++++++++++");
//非http或者https的网络请求拦截,用action_view启动。可能报错。
try {
if (url.startsWith("http:") || url.startsWith("https:")){
return false;
}else{
Uri uri = Uri.parse(url);
Intent intent =new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
return true;
}catch (Exception e){
Log.i("Unity","出现异常++++++++++");
e.printStackTrace();
return false;
}
}
//页面加载完成
public void onPageFinished(WebView view, String url)
{
Log.i("Unity", "onPageFinished " + url);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT);
addContentView(webView,params); //这里可以根据具体需要,在需要的地方添加视图}
});
//用于webView的辅助类,拦截 js 弹窗,关闭,还有进度条等等事件
webView.setWebChromeClient(new WebChromeClient()
{
public void onCloseWindow(WebView window)
{
Log.i("Unity", "拦截到windowClose");
ViewGroup vg = (ViewGroup) webView.getParent();
vg.removeView(webView);
viewHierarchyId--;
super.onCloseWindow(window);
}
// 处理javascript的alert
public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) {
Log.i("Unity", "拦截到onJsAlert");
return true;
};
});
}
//在继承Activity的类下面加上以上方法即可,在需要加载界面的地方掉用一下方法
Privat void Load()
{
handler.post(new Runnable() {
@Override
public void run() {
Log.i("Unity", "------------url_webview"+url_webview);
webView.loadUrl(url_webview);
//设置Web视图
setContentView(webView); }
});
}
这里有个坑,如果只是单纯的 调用 webView.loadUrl( url_webview)时,会出现如下错误
A WebView method was called on thread ‘JavaBridge‘. All WebView methods must be called on the same thread。
解决的办法就是调用上面的load方法即可。
我这里用的是
public void CloseWebView(){
Log.i("Unity","CloseWebView++Destory");
ViewGroup vg = (ViewGroup) webView.getParent();
vg.removeView(webView);
}
*另外需要一个脚本去让js调用安卓的接口JSBridge.Java内容如下:
Public class JSBridge extends Object {
rivate UnityPlayerActivity playerActivity;
public JSBridge(UnityPlayerActivity player){
playerActivity=player;
}
//需要添加这个@JavascriptInterface 来供js调用用来移除显示的H5界面
@JavascriptInterface public void CloseWebView(){
}
}
*注意:由于是在游戏里面打开webView界面,最开始是用的setContentView(webView)的方式显示。会出现如下情况 Skipped rendering frame because GfxDevice is in invalid state (device lost). 最终导致程序直接崩溃,我猜可能是因为这样使安卓接管了webView视图,导致游戏视图丢失。解决方案是,在原先的基础上 使用addContentView去实现,此种需要在视图创建的时候,通过调用view.SetID去设置层级即可。js调用的JSBridge的 CoseWebView方法有个大坑。实际测试中,js调用的是可以进入到playerActivity.CloseWebView 函数里面,但是确不能移除此webView组件。具体原因还不清楚,后来通过setWebChromeClient 去重写onCloseWindow 方法 去拦截js的关闭界面,才可移除。
Ios篇
一 需要如下操作其中.h文件如下
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#import "OCJSHelper.h"
@interface WkWebViewManager : UIViewController<WKNavigationDelegate,WKUIDelegate>
@property (nonatomic, strong) UIProgressView *progressView;
@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) OCJSHelper *ocjsHelper;
+(instancetype)sharedManager;
-(void)InitWKWebView;
@end
需要注意的是此文件必须继承UIViewController 和WKNavigationDelegate,WKUIDelegate这2个协议。
.m文件内容如下:
#import "WkWebViewManager.h"
@implementation WkWebViewManager
+(instancetype)sharedManager
{
static dispatch_once_t onceToken;
static WkWebViewManager *instance;
dispatch_once(&onceToken, ^{
instance = [[WkWebViewManager alloc] init];
});
return instance;
}
// 用来测试的一些url链接
- (NSURL *)testurl {
// NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
//NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSURL *url = [NSURL URLWithString:@"http://dagou.daxianggames.com/pay/order_con.php?uid=10004455&appid=1001&goodsid=1&cashtype=2"];
// NSURL *url = [NSURL URLWithString:@"https://z.yeemiao.com/share/share.html"]; // 自建证书,在iOS8下面,无法通过验证
return url;
}
-(void)InitWKWebView
{
[self clearWbCache];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = [[WKUserContentController alloc] init];
//JS交互对象设置,kJS_Name 需要与js端保持一致
[config.userContentController addScriptMessageHandler:(id)self.ocjsHelper name:@"kJS_Namer"];
//如果是ios原生的,将UnityGetGLView()替换成self.view。我这里是基于unity上的
self.webView = [[WKWebView alloc] initWithFrame:UnityGetGLView().bounds configuration:config];
self.ocjsHelper.webView = self.webView;
// [self.view addSubview:webview];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
NSURL *url = [self testurl];
//加载页面,self.urlString是网址
NSLog(@"加载url请求++++++++++");
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
//[self.webView setHidden:true];
}
- (void)clearWbCache {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
}
// 页面开始加载时调用
-(void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"开始加载");
}
// 页面加载完成之后调用
-(void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation *)navigation{
NSLog(@"加载完成");
[UnityGetGLView() addSubview:self.webView];
}
// 在收到响应后,决定是否跳转
-(void)webView:(WKWebView*)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"22222222222");
NSLog(@"%@",navigationResponse.response.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在发送请求之前,决定是否跳转
-(void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSLog(@"%@",navigationAction.request.URL.absoluteString);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
NSString*urlString = [navigationAction.request.URL absoluteString];
urlString = [urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([urlString containsString:@"weixin://wap/pay?"])
{
actionPolicy =WKNavigationActionPolicyCancel;
//解决wkwebview weixin://无法打开微信客户端的处理
NSURL*url = [NSURL URLWithString:urlString];
if([[UIApplication sharedApplication]respondsToSelector:@selector(openURL:options:completionHandler:)])
{
[[UIApplication sharedApplication]openURL:url options:@{UIApplicationOpenURLOptionUniversalLinksOnly:@NO} completionHandler:^(BOOL success) { }];
}
else {
[[UIApplication sharedApplication]openURL:webView.URL];
}
}
//允许跳转
decisionHandler(actionPolicy);
}
// 加载 HTTPS 的链接,需要权限认证时调用 \ 如果 HTTPS 是用的证书在信任列表中这不要此代理方法
-(void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if ([challenge previousFailureCount] == 0) {
NSURLCredential *credential=[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}
#pragma mark - WKUIDelegate
// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
NSLog(@"###############");
return [[WKWebView alloc]init];
}
#pragma mark - Setter & Getter
- (OCJSHelper *)ocjsHelper {
if (!_ocjsHelper) {
_ocjsHelper = [[OCJSHelper alloc] initWithDelegate:(id)self vc:self];
}
return _ocjsHelper;
}
@end
ocjsHelper代码如下:
.h文件代码
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@protocol OCJSHelperDelegate <NSObject>
@optional
@end
@interface OCJSHelper : NSObject <WKScriptMessageHandler>
@property (nonatomic, weak) id<OCJSHelperDelegate> delegate;
@property (nonatomic, weak) WKWebView *webView;
/**
指定初始化方法
代理
实现WebView的VC
返回自身实例
*/
-(instancetype)initWithDelegate:(id<OCJSHelperDelegate>)delegate vc:(UIViewController *)vc;
@end
.m文件
#import "OCJSHelper.h"
@interface OCJSHelper()
@property (nonatomic, weak) UIViewController *vc;
@end
@implementation OCJSHelper
-(instancetype)initWithDelegate:(id<OCJSHelperDelegate>)delegate vc:(UIViewController *)vc; {
if (self = [super init]) {
self.delegate = delegate;
self.vc = vc;
}
return self;
}
- (void)dealloc {
NSLog(@"%@, %s", self.class, __func__);
}
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([[message.body valueForKey:@"body"] isEqualToString:@"close_win"] ) {
[[WkWebViewManager sharedManager] colseView];
} else {
return;
}
}
@end