UIWebView控件中加载资源的方法 |
- (void)loadData:(NSData *)data
MIMEType:(NSString *)MIMEType
textEncodingName:(NSString *)encodingName
baseURL:(NSURL *)baseURL
|
- (void)loadHTMLString:(NSString*)string
baseURL:(NSURL*)baseURL
|
- (void)loadRequest:(NSURLRequest*)request |
下面我们就利用这些方法,在iOS平台上使用UIWebView控件来访问叶小钗兄所提供的web页面。
//ViewController.h @interface ViewController : UIViewController { UIWebView *webView; } //ViewController.m - (void)viewDidLoad { [super viewDidLoad]; webView = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; //load yexiaochai's html NSBundle *thisBundle = [NSBundle mainBundle]; NSString *path = [thisBundle pathForResource:@"webapp/hotel/index" ofType:@"html"]; NSURL *baseURL = [NSURL fileURLWithPath:path]; NSURLRequest *urlReq = [NSURLRequest requestWithURL:baseURL]; [self.view addSubview: webView]; [webView loadRequest:urlReq];
UIWebView控件中涉及Native和Web交互的方法 |
- (NSString*)stringByEvaluatingJavaScriptFromString:(NSString *)script |
- (BOOL)webView:(UIWebView*)webView
shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
|
除此之外,iOS的UIWebView还有一些页面能否前进后退的属性以及控制它们前进后退的方法:
UIWebView控件中关于页面前进后退的属性和方法 |
canGoBack |
canGoForward |
- (void)goBack |
- (void)goForward |
<uses-permissionandroid:name="android.permission.INTERNET" />
WebView加载资源的方法 |
public void loadUrl(String url); |
public void loadUrl(String url,Map<String, String> additionalHttpHeaders); |
public void loadData(String data,String mimeType, String encoding); |
public voidloadDataWithBaseURL(String baseUrl, String data, String mimeType, Stringencoding, String historyUrl); |
<?xml version="1.0" encoding="utf-8"?> <WebView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" />
当然,除了在layout中添加<WebView>元素之外,我们可以直接通过代码在Activity设置为WebView,
WebView webview =new WebView(this);[/align][align=left]setContentView(webview);
WebView myWebView = (WebView)findViewById(R.id.webview); myWebView.loadUrl("file:///android_asset/webapp/hotel/index.html");
WebView myWebView = (WebView)findViewById(R.id.webview); WebSettings webSettings =myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
//ViewController.h @interface ViewController : UIViewController { UIWebView *webView; NSMutableString *msg; UITextField *msgText; UIButton *nativeCallJsBtn; } //ViewController.m - (void)createNativeCallJsSample{ [webView loadHTMLString:@"<html><head><script language = 'JavaScript'>function msg(text){alert(text);}</script></head><body style=\"background-color: #0ff000; color: #FFFFFF; font-family: Helvetica; font-size: 10pt; width: 300px; word-wrap: break-word;\"><button type='button' onclick=\"msg('Js调用')\" style=\"margin:30 auto;width:100;height:25;\">web button</button></body></html>" baseURL:nil]; //创建一个UITextField,用来在native调用js时向js的函数传送参数 [self createNativeTextField]; //创建一个按钮,用来演示Native调用js [self createNativeCallJsButton]; } ... //native 调用 js - (void)btnClickMsg{ [msg setString:@"msg('"]; [msg appendString:@"native调用js:"]; [msg appendString:[msgText text]]; [msg appendString:@"')"]; [webView stringByEvaluatingJavaScriptFromString:msg]; }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); //开启js支持 webSettings.setJavaScriptEnabled(true); myWebView.loadData("<html><head><script language = 'JavaScript'>function msg(text){alert(text);}</script></head><body><button type='button' onclick= 'msg()'>web button</button></body></html>", "text/html", "utf-8"); evaluateJavascript(myWebView); } .... //Native调用JS public static void evaluateJavascript(WebView mWebview) { //判断版本调用不同的方法 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { mWebview.evaluateJavascript("msg('native call js')", null); } else { mWebview.loadUrl("msg('native call js')"); } }
Hybrid交互设计
我想行文至此,各位应该已经明白了两大平台(iOS和Android)的Native端是如何调用JS代码的了。那么本小节则主要来聊一聊Web是如何调用Native的。Web和Native之间交互的第一步便是要约定好格式。由于我直接使用了叶小钗兄的Web部分,因此按照他设计的Web请求Native的模型:
requestHybrid({ //创建一个新的webview对话框窗口 tagname: 'hybridapi', //请求参数,会被Native使用 param: {}, //Native处理成功后回调前端的方法 callback: function (data) { } }); //index.html中的实际例子 requestHybrid({ tagname: 'forward', param: { topage: 'webapp/flight/index', type: 'webview' } });
hybrid://forward?t=1447949881120¶m=%7B%22topage%22%3A%22webapp%2Fflight%2Findex%22%2C%22type%22%3A%22webview%22%7D
十分清楚,这里我们交互使用的schema是hybrid://,在Native部分会监控Webview发出的所有schema://请求,然后分发到“控制器”hybridapi处理程序,Native控制器处理时会需要param提供的参数。下面就让我们来分别看一下iOS和Android是如何使用Web调用Native的吧。(这里我只是简单的实现了和叶小钗兄web交互的iOS部分,Android部分演示的是一个简单的Web调用Native的例子)。
iOS Web调用Native
在iOS平台,我们会用到shoudStartLoadWithRequest这个方法来捕获Web所发出的请求。下面我们就来看一段简单的演示吧。
//按照和web端规定的格式,获取数据 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL * url = [request URL]; if ([[url scheme] isEqualToString:@"hybrid"]) { NSString *actionType = request.URL.host; //从url中获取web传来的参数 NSDictionary *actionDict = [self getDicFromUrl : url]; //根据web的指示,native端相应的做出回应 [self doActionType:actionType : actionDict]; return NO; } return YES; } //从url中获取web传来的参数 - (NSDictionary *) getDicFromUrl : (NSURL *)url{ NSArray* paramArray = [[url query] componentsSeparatedByString:@"param="]; NSString* paramStr = paramArray[1]; NSString *jsonDictString = [paramStr stringByRemovingPercentEncoding]; NSData *jsonData = [jsonDictString dataUsingEncoding:NSUTF8StringEncoding]; NSError *e; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e]; return dict; } //根据web的指示,native端相应的做出回应 -(void) doActionType : (NSString*) type : (NSDictionary*) dict{ if ([type isEqualToString:@"forward"]) { [webView goForward]; } //打开一个新的Web if([dict[@"type"] isEqualToString: @"webview"]){ [self web2Web: dict[@"topage"]]; } //打开一个Native页面(我简化为了控件) else if ([dict[@"type"] isEqualToString: @"native"]){ [self web2Native]; } }
最左边的图是最开始的Web页面,点击“新开webview...”按钮之后,Native端又打开了一个新的Web页面,即中间的图所示。
最右边的图演示的是点击“跳转native...”按钮之后,Native端创建了一个Native的UI控件。
Android Web调用Native
下面就让我们演示一个小例子,不让Web调用JS的alert,相反使用Web调用Native的Dialog来显示提示吧。
首先我们要在Android应用中引入JavaScriptInterface。
import android.webkit.JavascriptInterface; public class WebAppInterface {Context mContext; WebAppInterface(Context c) { mContext = c; } @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); }}
之后,我们使用WebView的 addJavascriptInterface()方法将这个类和JS代码绑定,作为Web调用Native的桥梁。
WebView webView =(WebView) findViewById(R.id.webview);[/align][align=left]webView.addJavascriptInterface(newWebAppInterface(this), "Android");
最后,在Web端也做相应的实现。点击Web中的button会调用Native的showToast方法。
<inputtype="button" value="Say hello"onClick="showAndroidToast('Hello Android!')" /> <scripttype="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>