2017-09-15 00:01:38 Margaret_MO 阅读数 647
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    8012 人正在学习 去看看 秦子恒

iOS与H5界面JSBridge交互Demo

我用了一个library(GCWebviewJSBridge-iOS), github网址:github.com/wheying/GCWebviewJSBridge-iOS

他的Demo不太容易看得懂, 看得我一脸懵逼, 我写了一个简洁明了的Demo

首先做好准工作, 建立一些基本的视图
iOS的准备工作
// 1.新建WebView
self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];

// 2.加载网页
NSString *indexPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString *appHtml = [NSString stringWithContentsOfFile:indexPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseUrl = [NSURL fileURLWithPath:indexPath];
[self.webView loadHTMLString:appHtml baseURL:baseUrl];

// 3.开启日志
[GCWebviewJSBridge setEnableLogging];

// 4.给webView建立JS和OC的沟通桥梁
_bridge = [GCWebviewJSBridge bridgeForWebView:self.webView];
[_bridge setwebViewDelegate:self];

JS的准备工作

之前是只写一套, 发现iOS行了Android又不行了; Android行了iOS又不行了. 最后才知道需要写两套

// 这段代码是固定的,必须要放到js中
function setupWebViewJavascriptBridge(callback) {
   //Android
   if (window.GCWebviewAndroidJSBridge) {
       callback(GCWebviewAndroidJSBridge)
   } else {
       document.addEventListener(
         'GCWebviewAndroidJSBridgeReady'
         , function() {
         callback(GCWebviewAndroidJSBridge)
         },
         false
     );
   }
   
   //iOS
   if (window.GCWebviewJSBridge) {
       return callback(GCWebviewJSBridge);
   }
   if (window.KBWVJSBCallBacks) {
       return window.KBWVJSBCallBacks.push(callback);
   }
   window.KBWVJSBCallBacks = [callback];
   var GCWVJSBIframe = document.createElement('iframe');
   GCWVJSBIframe.style.display = 'none';
   GCWVJSBIframe.src = 'gcwvjsbscheme://__GC_BRIDGE_LOADED__';
   document.documentElement.appendChild(GCWVJSBIframe);
   setTimeout(function() { document.documentElement.removeChild(GCWVJSBIframe) }, 0);
}
一. iOS注册方法提供给JS调用
iOS注册访问相册方法
[_bridge registerObjCHandler:@"openCamera" handler:^(id data, GCWVJSBResponseCallback responseCallback) {
    NSLog(@"需要%@图片", data[@"count"]);
    UIImagePickerController *imageVC = [[UIImagePickerController alloc] init];
    imageVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentViewController:imageVC animated:YES completion:nil];
}];
JS调用该方法的代码片段
JS调用打开相册方法
bridge.callHandler('openCamera', {'count':'10张'}, function responseCallback(responseData) {
   console.log("OC中返回的参数:", responseData)
});
二. JS注册方法提供给iOS调用
iOS注册提供用户信息方法
/* JS给OC提供公开的API, 在OC中可以手动调用此API, 并且可以接收OC中传过来的参数,同时可回调OC */
// 获取用户信息
bridge.registerHandler('getUserInfo', function(data, responseCallback) {
   console.log("OC中传递过来的参数:", data);
   // 把处理好的结果返回给OC
   responseCallback({"userID":"DX001", "userName":"旋之华", "age":"18", "otherName":"旋之华"})
});

iOS调用JS中的方法, 获得用户信息

// 调用JS中的API
[self.bridge callHandler:@"getUserInfo" data:@{@"userId":@"DX001"} responseCallback:^(id responseData) {
    NSString *userInfo = [NSString stringWithFormat:@"%@,姓名:%@,年龄:%@", responseData[@"userID"], responseData[@"userName"], responseData[@"age"]];
}];

文章写得不详细, 可以以下我的Demo直接看代码:Demo下载地址

哎~ 这种方式实现,需要三方配合测试, 真的是很麻烦啊~

2017-03-24 14:50:00 SandyLoo 阅读数 15706
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    8012 人正在学习 去看看 秦子恒

OC与JS的交互(iOS与H5混编)

在开发过程中,经常会出现需要iOS移动端与H5混编的使用场景。 iOS中加载html网页, 可以使用UIWebView或WKWebView. 本篇博客将介绍两种控件使用过程中如何实现OC与JS的交互。
UIWebView delegate 协议方法

 //网页即将开始加载
 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

 //网页开始加载
 - (void)webViewDidStartLoad:(UIWebView *)webView;

 //网页加载完成
 - (void)webViewDidFinishLoad:(UIWebView *)webView;

 //网页加载失败
 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;



 //UIWebView自带了一个方法, 可以直接调用JS代码(转化为string类型的js代码)
 - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

 //例如修改id为‘html’标签内部的text属性
 [web stringByEvaluatingJavaScriptFromString:@"document.getElementById('html').innerText='修改内容'"];

 //也可以执行多行js代码
 [web stringByEvaluatingJavaScriptFromString:@"var div = document.getElementById('html'); div.innerText = '修改内容'"];

利用JavaScriptCore实现交互
JavaScriptCore中类及协议:

 JSContext:给JavaScript提供运行的上下文环境
 JSValue:JavaScript和Objective-C数据和方法的桥梁
 JSManagedValue:管理数据和方法的类
 JSVirtualMachine:处理线程相关,使用较少
 JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议
 OC中提供了JavaScriptCore 这个库,使得OC与js的交互变得更加方便。
 使用方法:
 1  加入JavaScriptCore 这个framework
 2  引入头文件<JavaScriptCore/JavaScriptCore.h>
 3  在VC里面加入一个JSContext属性
    @property (strong, nonatomic) JSContext *context;
    JSContext是什么那? 我们看一下api里面的解释

 @interface
 @discussion A JSContext is a JavaScript execution environment. All
 JavaScript execution takes place within a context, and all JavaScript values
 are tied to a context.

大概意思是说:JSContext是一个JS的执行环境,所有的JS执行都发生在一个context里面, 所有的JS value都绑定到context里面


具体使用

 //初始化context
 self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

 //OC调用JS

 //(1)例如html的script中一个方法

   function dolike(a,b,c){



   }

 //通过OC调用此方法

 NSString * method = @"dolike";

 JSValue * function = [self.context objectForKeyedSubscript:method];

 //这里面的a,b,c就是OC调用JS的时候给JS传的参数
 [function callWithArguments:@[a,b,c]];



 //JS调用OC
 //例如网页中有个标签,点击button的时候调用Jump方法, 此处3为传入的参数
 <button onclick="jump('3')">点我</button>

 //当点击网页中的button的时候,触发jump方法, 在OC中用如下代码可以捕捉到jump方法, 并拿到JS给我传的参数‘3’
 self.context[@"jump"] = ^(NSString * str){

 //此处 str 值为'3'(js调用OC时传给OC的参数)

 };

WKWebView :
说到WKWebView, 首先要说下WKWebView的优势

1 更多的支持HTML5的特性
2 官方宣称的高达60fps的滚动刷新率以及内置手势
3 将UIWebViewDelegate与UIWebView拆分成了14类与3个协议,以前很多不方便实现 的功能得以实现
4 Safari相同的JavaScript引擎
5 占用更少的内存

类:

    WKBackForwardList: 之前访问过的 web 页面的列表,可以通过后退和前进动作来访问到。
    WKBackForwardListItem: webview 中后退列表里的某一个网页。
    WKFrameInfo: 包含一个网页的布局信息。
    WKNavigation: 包含一个网页的加载进度信息。
    WKNavigationAction: 包含可能让网页导航变化的信息,用于判断是否做出导航变化。
    WKNavigationResponse: 包含可能让网页导航变化的返回内容信息,用于判断是否做出导航变化。
    WKPreferences: 概括一个 webview 的偏好设置。
    WKProcessPool: 表示一个 web 内容加载池。
    WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法。
    WKScriptMessage: 包含网页发出的信息。
    WKUserScript: 表示可以被网页接受的用户脚本。
    WKWebViewConfiguration: 初始化 webview 的设置。
    WKWindowFeatures: 指定加载新网页时的窗口属性。

协议:

      WKNavigationDelegate: 提供了追踪主窗口网页加载过程和判断主窗口和子窗口是否进行页面加载新页面的相关方法。
      WKScriptMessageHandler: 提供从网页中收消息的回调方法。
      WKUIDelegate: 提供用原生控件显示网页的方法回调。
 加载方式:
 //方式一
 WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
 [self.view addSubview:webView];

 //方式二
 WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init];
 webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
 [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
 [self.view addSubview:webView];


协议方法介绍:
 #pragma mark - WKNavigationDelegate
 // 页面开始加载时调用
 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{

 }
 // 当内容开始返回时调用
 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{

 }
 // 页面加载完成之后调用
 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{

 }
 // 页面加载失败时调用
 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{

 }
 // 接收到服务器跳转请求之后调用
 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{

 }
 // 在收到响应后,决定是否跳转
 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

 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(WKNavigationActionPolicyAllow);
 //不允许跳转
 decisionHandler(WKNavigationActionPolicyCancel);
 }
 #pragma mark - WKUIDelegate
 // 创建一个新的WebView
 - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
 return [[WKWebView alloc]init];
 }
 // 输入框
 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
 completionHandler(@"http");
 }
 // 确认框
 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
 completionHandler(YES);
 }
 // 警告框
 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
 NSLog(@"%@",message);
 completionHandler();
 }

OC与JS的交互

WKWebView

WKWebView的 UIDelegate 提供了三个协议方法, 可以让前端很方便的拦截JS的alert, confirm, prompt方法。除此之外,OC,JS互调可以按照如下方法。

1 OC 调用JS

 可以使用webkit这个库

 - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

//例如OC调用JS的方法 setName

   [webView evaluateJavaScript:@"setname('张三')" completionHandler:nil];

//此处 setname为JS定义的方法名, 内部 ‘张三’为传给JS的参数。 如果setname方法需要传入一个json或者array等非字符参数, 需要用format方法将其转为string类型,在调用evaluate方法。例如

   NSString * para = [NSString stringWithFormat:@"setname('%@')",json];

JS调用OC

此时就要用到WKScriptMessageHandler了


 //首先.m中加入属性
 @property (nonatomic ,strong)WKUserContentController * userCC;


//1 遵循WKScriptMessageHandler协议
//2 初始化
   WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc]init];

 self.wkWebViw = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

 [self.wkWebViw loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.webPageUrl]]];

 [self.view addSubview:self.wkWebViw];

 self.userCC = config.userContentController;

 [self.userCC addScriptMessageHandler:self name:@"callOSX"];

 //此处相当于监听了JS中callFunction这个方法

 [self.userCC addScriptMessageHandler:self name:@"callFunction"];

 //当JS发出callFunction这个方法指令的时候, WKScriptMessageHandler的协议方法中我们就会收到这个消息

 #pragma mark  WKScriptMessageHandler delegate
 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
 {
//这个回调里面, message.name代表方法名(‘本例为 callFunction’), message.body代表JS给我们传过来的参数

 }

//最后, VC销毁的时候一定要把handler移除
-(void)dealloc
{
    [_userContentController removeScriptMessageHandlerForName:@"callFunction"];
}




//对应的JS代码

<button onclick="buttonClick('温馨提示')">点我</button>

<script>
       function buttonClick(string){
       //JS调用OC, 格式如下
       //(window.webkit.messageHandlers.Method_Name.postMessage(parameterToOC))
              window.webkit.messageHandlers.callFunction.postMessage(string)
        }       
</script>  





2016-06-13 17:49:27 wjchao1990 阅读数 1527
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    8012 人正在学习 去看看 秦子恒

在当前的移动开发过程中,原生与H5的混合开发越来越多,H5界面在APP中的比例越来越大,H5不在仅仅是展示内容信息,儿此时的交互,也越来越多。接下来介绍一点iOS与H5交互的心得。

iOS加载webView
iOS加载webView还是非常方便的,声明webView,接着load一下,就可以了。

@property (nonatomic,strong) UIWebView * webView;
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];

    [self.webView loadRequest:request];

接下来说一些交互的东西
1、首先是打开界面时传参数,这里只需要在URL后面拼接就可以。

[NSString stringWithFormat:@"http://yourIP?username=%@&password=%@",username,password];

2、H5界面向iOS端传递信息

这里是H5部分写的

window.location.href = "协议名:传值内容"; 
window.location.href = "ios:back";

这是iOS端做的操作

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
 NSString *requestString = [[request URL] absoluteString];
  requestString = [requestString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    if( navigationType == UIWebViewNavigationTypeOther ) {
        if ([requestString hasPrefix:@"ios:"]) {
           //开始处理你的逻辑,收到消息要怎么做
         [self.navigationController popViewControllerAnimated:YES];
            return NO;
        }
    }
    return YES;
}

在这之前,一定记得先遵循协议。
逻辑非常简单,H5端刷新界面,但是提前约定好刷新的URl,拿到这个URL,就拦截,不允许刷新,同事将URL后跟的拿到,这是,你想做什么做什么。

3、Objective-C调用javascript

我们用去调用一个js方法,这个js方法我们可以重复上面2的写法,相当于有了回调,我们点击某个原生按钮,激活这个方法,会导致h5界面里的方法向我们传值。

     [_webview stringByEvaluatingJavaScriptFromString:@"function h5里的方法"];

如图
这里写图片描述

2019-07-11 20:46:10 zgd826237710 阅读数 917
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    8012 人正在学习 去看看 秦子恒

本文详细讲述了如何使用 JSBridge 在 H5 和原生 Android、IOS之间进行交互。IOS 端包含 OC 和 Swift 的版本,Android 端包含 Java 和 Kotlin 版本。

一、写在前面

本文主要是通过代码讲述了如何使用 JSBridge 在 H5 和 原生之间进行通信。文中包含 H5、IOS、Android 三部分的代码。
IOS 中使用 OC 和 Swift 分别进行了代码实现。Android 中使用 Java 和 Kotlin 分别进行了代码实现。

Demo 地址:jsbridge-example

  • JSBridgeH5H5 端代码实现
  • JSBridgeIOSOC:原生 IOSOC 代码实现
  • JSBridgeIOSSwift:原生 IOSSwift 代码实现
  • JSBridgeAndroidJava:原生 AndroidJava 代码实现
  • JSBridgeAndroidKotlin:原生 IOSKotlin 代码实现

本文没有讲解关于原理的部分,只是详细使用代码介绍了 JSBridge 的使用。想要了解原理的朋友,可以另行搜索关于原理的博客。


二、H5 端代码

  • 初始化 WebViewJavascriptBridge,方式代码如下
  • 注册供原生调用的事件函数:
    window.setupWebViewJavascriptBridge(bridge => bridge.registerHandler('fnName', function) )
  • 调用原生事件函数:
    window.setupWebViewJavascriptBridge(bridge => bridge.callHandler('fnName', data, callback) )

1、初始化 WebViewJavascriptBridge

在项目入口文件或者根 js 文件下,添加以下代码:


// 这里根据移动端原生的 userAgent 来判断当前是 Android 还是 ios
const u = navigator.userAgent;
// Android终端
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
// IOS 终端
const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); 

/**
 * 配合 IOS 使用时的初始化方法
 */
const iosFunction = (callback) => {
    if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) }
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function(){
         document.documentElement.removeChild(WVJBIframe);
    }, 0);
}

/**
 * 配合 Android 使用时的初始化方法
 */
const androidFunction = (callback) => {
    if (window.WebViewJavascriptBridge) {
        callback(window.WebViewJavascriptBridge);
    } else {
        document.addEventListener('WebViewJavascriptBridgeReady', function () {
            callback(window.WebViewJavascriptBridge);
        }, false)
    }
}

window.setupWebViewJavascriptBridge = isAndroid ? androidFunction : iosFunction;

isAndroid && window.setupWebViewJavascriptBridge(function (bridge) {
    // 注册 H5 界面的默认接收函数(与安卓交互时,安卓端可以不调用函数名,直接 send 数据过来,就能够在这里接收到数据)
    bridge.init(function (msg, responseCallback) {
        console.log(msg);
        responseCallback("JS 返回给原生的消息内容");
    })
});

2、注册与原生交互的事件函数

/*
    window.setupWebViewJavascriptBridge(bridge => {
        bridge.registerHandler('事件函数名',fun 执行函数);
    })
*/
window.setupWebViewJavascriptBridge(bridge => {
    /**
     * data:原生传过来的数据
     * fn: 原生传过来的回调函数
     */
    bridge.registerHandler("H5Function", (data, fn) => {
        console.log(data);
        fn && fn();
    });
});

3、调用原生注册的事件函数

调用原生注册的时间函数时使用如下的代码:

/*
    window.setupWebViewJavascriptBridge(bridge => {
        bridge.callHandler('安卓端函数名', "传给原生端的数据", callback 回调函数);
    })
*/
window.setupWebViewJavascriptBridge(bridge => {
    bridge.callHandler('changeData', data, (result) => {
        console.log(result);
    });
})

三、IOS 端代码

  • 初始化 WebViewJavascriptBridge:

    + (instancetype)bridgeForWebView:(id)webView;
    + (instancetype)bridge:(id)webView;
    
  • 注册与 H5 端交互的事件函数:
    - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;

  • 调用 H5 端事件函数:

    - (void)callHandler:(NSString*)handlerName;
    - (void)callHandler:(NSString*)handlerName data:(id)data;
    - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
    

1、引入 WebViewJavascriptBridge

直接使用方式

  • 下载 WebViewJavascriptBridge

  • 找到 WebViewJavascriptBridge文件夹,直接拖入到 XCode 项目中,在提示的弹窗中选择 Copy items if neededCreate groups,如下图:
    Drag Group

  • ViewController.h 头文件中引入 #import "WebViewJavascriptBridge.h" 即可

Cocopad 使用方式

如必须使用这种方式请自行 Google。

2、初始化 WebViewJavascriptBridge

// 启用 WebViewJavascriptBridge Log
[WebViewJavascriptBridge enableLogging];

// 初始化 WKWebViewConfiguration 对象
self.webConfig = [[WKWebViewConfiguration alloc] init];
// 设置偏好设置
_webConfig.preferences = [[WKPreferences alloc] init];
// 默认为0
_webConfig.preferences.minimumFontSize = 10;
// 默认认为YES
_webConfig.preferences.javaScriptEnabled = YES;
// 在iOS上默认为NO,表示不能自动通过窗口打开
_webConfig.preferences.javaScriptCanOpenWindowsAutomatically = NO;

// TODO: 请替换成页面的 url 地址
NSString *URLSTR = @"http://xxx.xxx.xxx.xx:xxxx";
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:_webConfig];
// 设置 UserAgent 后缀
_webView.customUserAgent = [NSString stringWithFormat:self.webView.customUserAgent, @"app"];
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
NSURL *url = [NSURL URLWithString:URLSTR];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[_webView loadRequest:urlRequest];
[self.view addSubview:_webView];

self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[_bridge setWebViewDelegate:self];

3、注册与 H5 端交互的事件函数

// 例:注册修改 User 名称的 changeUser 函数
[self.bridge registerHandler:@"changeUser" handler:^(id data, WVJBResponseCallback responseCallback) {
    // 在这里处理逻辑
    NSLog(@"JS 传过来的数据%@", data);
    if (responseCallback) {
        // 执行回调函数
        responseCallback(@"返回给 JS 的数据");
    }
}];

4、调用 H5 端事件函数

// 调用 H5 界面的 changeName 事件函数
[self.bridge callHandler:@"changeName" data:name responseCallback:^(id responseData) {
    NSLog(@"JS 调用 OC 回调函数返回的值:%@", responseData);
}];

四、Android 端代码

  • 注册与 H5 交互的事件函数:
    public void registerHandler(String handlerName, BridgeHandler handler) {
        if (handler != null) {
            messageHandlers.put(handlerName, handler);
        }
    }
    
  • 调用 H5 端事件函数
    public void callHandler(String handlerName, String data, CallBackFunction callBack) {
        doSend(handlerName, data, callBack);
    }
    
  • 注册与 H5 交互的默认事件,即 H5 端不调用函数名,直接使用 send 函数传递数据,安卓端也可以在这个事件中接收到数据
    // 设置默认接收函数
    public void setDefaultHandler(BridgeHandler handler) {
        this.defaultHandler = handler;
    }
    
  • 调用 H5 端注册的默认事件函数
    @Override
    public void send(String data, CallBackFunction responseCallback) {
        doSend(null, data, responseCallback);
    }
    

1、引入 BridgeWebView

  • 在项目的 build.gradle 文件中添加如下代码:
    buildTypes {
        // ...
        repositories {
            // ...
            maven { url "https://jitpack.io" }
        }
    }
    
  • 添加依赖:implementation 'com.github.lzyzsd:jsbridge:1.0.4'

2、初始化 BridgeWebView

activity_main.xml 文件中添加布局

<com.github.lzyzsd.jsbridge.BridgeWebView
    android:id="@+id/main_wv"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</com.github.lzyzsd.jsbridge.BridgeWebView>

在 MainActivity 中初始化 BridgeWebView

mWebView = findViewById(R.id.main_wv);

mWebView.getSettings().setAllowFileAccess(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setDatabaseEnabled(true);
// 开启 localStorage
mWebView.getSettings().setDomStorageEnabled(true);
// 设置支持javascript
mWebView.getSettings().setJavaScriptEnabled(true);
// 进行缩放
mWebView.getSettings().setBuiltInZoomControls(true);
// 设置UserAgent
mWebView.getSettings().setUserAgentString(mWebView.getSettings().getUserAgentString() + "app");
// 设置不用系统浏览器打开,直接显示在当前WebView
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(new MyWebViewClient(mWebView));

mWebView.loadUrl(URL);

3、注册与 H5 交互的事件函数

// 默认事件函数
mWebView.setDefaultHandler(new BridgeHandler() {
    @Override
    public void handler(String data, CallBackFunction function) {
        Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
        function.onCallBack("安卓返回给 JS 的消息内容");
    }
});

// 普通事件函数
mWebView.registerHandler("reloadUrl", new BridgeHandler() {

    @Override
    public void handler(String data, CallBackFunction function) {
        mWebView.reload();
        Toast.makeText(MainActivity.this, "刷新成功~", Toast.LENGTH_SHORT).show();
        function.onCallBack("");
    }
});

4、调用 H5 端事件函数

// 调用 H5 端默认事件函数
mWebView.send("安卓传递给 JS 的消息", new CallBackFunction() {
    @Override
    public void onCallBack(String data) {
        Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
    }
});

// 调用 H5 端普通事件函数
mWebView.callHandler("changeName", mEditName.getText().toString(), new CallBackFunction() {
    @Override
    public void onCallBack(String data) {
        Toast.makeText(MainActivity.this, "name 修改成功", Toast.LENGTH_SHORT).show();
        mEditName.setText("");
    }
});

5、添加网络权限

这一步是必须的,否则的话, WebView 加载不出来,手机界面会提示 Webpage not available

  • AndroidManifest.xml 清单文件中添加:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    
  • 添加了权限之后,网页可能还是加载不出来,可能是因为对未加密的流量不信任,在 AndroidManifest.xmlapplication 中添加一个属性:android:usesCleartextTraffic="true"。如下:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
        <application 
            ...
            android:usesCleartextTraffic="true">
            ...
        </application>
    </manifest>
    

五、参考链接


六、Demo 地址

jsbridge-example

如果有所帮助,欢迎 Star!

2017-09-15 00:15:00 weixin_30367945 阅读数 19
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    8012 人正在学习 去看看 秦子恒

iOS与H5界面JSBridge交互Demo

最近公司需要加活动和新闻模块, boss看同样的设计稿, 我们iOS做一遍, 安卓做一遍, 小程序又做一遍; 所以决定用H5页面. 但我们Native不仅仅加载URL就行, 还需要跟H5有交互, 安卓大哥跟我慢慢填坑…

我用了一个library(GCWebviewJSBridge-iOS), github网址:github.com/wheying/GCWebviewJSBridge-iOS

他的Demo不太容易看得懂, 看得我一脸懵逼, 我写了一个简洁明了的Demo

首先做好准工作, 建立一些基本的视图
iOS的准备工作
// 1.新建WebView
self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];

// 2.加载网页
NSString *indexPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString *appHtml = [NSString stringWithContentsOfFile:indexPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseUrl = [NSURL fileURLWithPath:indexPath];
[self.webView loadHTMLString:appHtml baseURL:baseUrl];

// 3.开启日志
[GCWebviewJSBridge setEnableLogging];

// 4.给webView建立JS和OC的沟通桥梁
_bridge = [GCWebviewJSBridge bridgeForWebView:self.webView];
[_bridge setwebViewDelegate:self];

JS的准备工作

之前是只写一套, 发现iOS行了Android又不行了; Android行了iOS又不行了. 最后才知道需要写两套

// 这段代码是固定的,必须要放到js中
function setupWebViewJavascriptBridge(callback) {
   //Android
   if (window.GCWebviewAndroidJSBridge) {
       callback(GCWebviewAndroidJSBridge)
   } else {
       document.addEventListener(
         'GCWebviewAndroidJSBridgeReady'
         , function() {
         callback(GCWebviewAndroidJSBridge)
         },
         false
     );
   }

   //iOS
   if (window.GCWebviewJSBridge) {
       return callback(GCWebviewJSBridge);
   }
   if (window.KBWVJSBCallBacks) {
       return window.KBWVJSBCallBacks.push(callback);
   }
   window.KBWVJSBCallBacks = [callback];
   var GCWVJSBIframe = document.createElement('iframe');
   GCWVJSBIframe.style.display = 'none';
   GCWVJSBIframe.src = 'gcwvjsbscheme://__GC_BRIDGE_LOADED__';
   document.documentElement.appendChild(GCWVJSBIframe);
   setTimeout(function() { document.documentElement.removeChild(GCWVJSBIframe) }, 0);
}
一. iOS注册方法提供给JS调用
iOS注册访问相册方法
[_bridge registerObjCHandler:@"openCamera" handler:^(id data, GCWVJSBResponseCallback responseCallback) {
    NSLog(@"需要%@图片", data[@"count"]);
    UIImagePickerController *imageVC = [[UIImagePickerController alloc] init];
    imageVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentViewController:imageVC animated:YES completion:nil];
}];

 

JS调用该方法的代码片段

JS调用打开相册方法
bridge.callHandler('openCamera', {'count':'10张'}, function responseCallback(responseData) {
   console.log("OC中返回的参数:", responseData)
});
二. JS注册方法提供给iOS调用
iOS注册提供用户信息方法
/* JS给OC提供公开的API, 在OC中可以手动调用此API, 并且可以接收OC中传过来的参数,同时可回调OC */
// 获取用户信息
bridge.registerHandler('getUserInfo', function(data, responseCallback) {
   console.log("OC中传递过来的参数:", data);
   // 把处理好的结果返回给OC
   responseCallback({"userID":"DX001", "userName":"旋之华", "age":"18", "otherName":"旋之华"})
});

iOS调用JS中的方法, 获得用户信息

// 调用JS中的API
[self.bridge callHandler:@"getUserInfo" data:@{@"userId":@"DX001"} responseCallback:^(id responseData) {
    NSString *userInfo = [NSString stringWithFormat:@"%@,姓名:%@,年龄:%@", responseData[@"userID"], responseData[@"userName"], responseData[@"age"]];
}];

文章写得不详细, 可以以下我的Demo直接看代码:Demo下载地址

哎~ 这种方式实现,需要三方配合测试, 真的是很麻烦啊~

转载于:https://www.cnblogs.com/moxiaoyan33/p/7524123.html

IOS 原生与HTML交互

阅读数 10127

WKWebView与h5的交互

阅读数 3489

没有更多推荐了,返回首页