图片来自网络
首先我是一个半吊子的Vue开发者,也是一个半吊子的Android开发者,iOS才是我的主业,只不过现在是我都有在弄。写这个文章,主要还是记录并分享给第一次用Vue 和 Android、iOS交互的人使用。网上资料也是参差不齐。很多都是复制别人的。没有成系统性。
一、 Vue方面的集成及使用
1、在Vue项目中使用npm命令安装DSBridge 将DSBridge集成到你的项目中
npm install dsbridge
2、再main.js中补充代码
var dsBridge = require('dsbridge')
Vue.prototype.$bridge = dsBridge;
3、测试代码编写(以下是我完整的测试代码)
<template>
<rt-view>
<rt-button type="primary" size="large" @click.native="handleOKClick">确定</rt-button>
</rt-view>
</template>
<script>
export default {
data() {
return {};
},
mounted() {
// 这是重点,涉及到Vue的域问题,如果想要将传进的参数进其他函数的使用,就必须将this 赋值给 一个常量保存起来,再调用其methds中的函数,将其参数进行使用
let than = this;
// 注册 javascript API
dsBridge.register('callJsFunction',function(data1, data2) {
console.log("登录信息打印:" + data1);
console.log("用户信息打印:" + data2);
// 将传进来的参数交给 methods 进行处理(如果在mounthed中进行处理,会报错)
than.addUserInfoAndToken(data1, data2);
return "调用Vue函数回调文字";
})
},
methods: {
// 处理 注册事件(注册后,客户端iOS-Android就能调用你的函数)
addUserInfoAndToken(str, str1) {
console.log("打印了,就意味着被调用了");
const auth = JSON.parse(str);
this.$store.commit('UPDATE_AUTH', auth);
this.$store.commit('UPDATE_USER', str1);
this.$router.push({
name: "main"
});
},
// 按钮点击事件(点击后能够调用客户端-iOS、Android的函数)
handleOKClick() {
console.log("打印了,就意味着调用iOS程序了");
// 同步调用(调用后客户端给的反馈是同步进行的)(函数名需要跟客户端约定好)
var str = dsBridge.call("echo.testSyn","syn");
// 异步调用(调用后客户端给的反馈是异步进行的-也就是可能客户端会过一会才给你回复他处理好了)(函数名需要跟客户端约定好)
dsBridge.call("echo.testAsyn","asyn", function (v) {
console.log("打印了,就意味着客户端回调了");
console.log(v);
})
}
}
};
</script>
<style scoped>
</style>
至此Vue的代码集成已经写好,请大家重点看代码中的注释。里面有些小细节很重要。
二、 Android 方面的集成及使用
我使用的Android Studio版本是 2021年10月12号的最新版。
我的build.gradle配置为:
defaultConfig {
applicationId "XXXXX"
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
minSdkVersion 24
targetSdkVersion 31
}
dependencies {
// 集成 DSBridge
implementation 'com.github.wendux:DSBridge-Android:3.0-SNAPSHOT'
}
因为我使用的这个Android 版本所以我的 jitpack.io 是加在 settings.gradle中,如图下所示:
maven { url 'https://jitpack.io' }
配置好了后,将包下载下来。接下来进入代码使用环节。
在xml中定义一个组件:
<wendu.dsbridge.DWebView
android:id="@+id/main_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
新建一个 JsEchoApi 的class类,这个类主要用于注册Vue调用Android 的函数。代码如下
public class JsEchoApi {
@JavascriptInterface
public Object testSyn(Object args) throws JSONException {
LogTool.simplenessLog("我调用了,是同步调用");
return args;
}
@JavascriptInterface
public void testAsyn(Object args, CompletionHandler handler) {
LogTool.simplenessLog("我调用了,是异步调用");
handler.complete(args);
}
}
之后在Activity中使用它。
public class WebViewActivity extends BaseActivity {
private DWebView webView;
private String sLoginData, sUserInfo;
@SuppressLint("WrongViewCast")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
StatusBarUtil.setColor(WebViewActivity.this, Color.parseColor("#db2c42"), 1);
// 上层传递过来的封装数据的对象
sLoginData = (String)this.getIntent().getSerializableExtra("LoginData");
sUserInfo = (String)this.getIntent().getSerializableExtra("UserInfo");
// 定义WebView组件
webView = findViewById(R.id.main_webview);
// 开启Debug调试模式
DWebView.setWebContentsDebuggingEnabled(true);
// 重点:注册API,其中echo为API的空间名(这个JsEchoApi 的 class 里面的函数就是 给 Vue调用 Android 的函数)
webView.addJavascriptObject(new JsEchoApi(), "echo");
monitoring();
setWebViewConfig(webView, this);
// 加载一个网页
webView.loadUrl("http://172.19.23.47:8080");
}
// 监控WebView的回调
public void monitoring() {
webView.setWebViewClient(new WebViewClient() {
// 在页面加载结束时调用。
@Override
public void onPageFinished(WebView view, String url) {
// 设定加载结束的操作
LogTool.simplenessLog("在页面加载结束时调用");
// 重点(这个是在页面加载结束时才调用Vue里面的函数)(这个callJsFunction就是 Android 调用 Vue的函数)
webView.callHandler("callJsFunction", new Object[]{sLoginData, sUserInfo}, new OnReturnValue<String>() {
@Override
public void onValue(String retValue) {
LogTool.simplenessLog(retValue);
}
});
}
}
}
这样一来 Android 在 onPageFinished 调用后,使用callJsFunction 就能调用到 Vue中的函数。完成了Android-Vue 交互。
同时点击网页的确认按钮后,就能调用到 Android 中的函数。完成了Vue-Android 交互。
三、 iOS 方面的集成及使用
先在 CocoaPods 中集成
pod "dsBridge"
新建一个 JSApi 的 NSObject 类,代码如下
@implementation JSApi
// 同步API
- (NSString *)testSyn:(NSString *)msg {
Log(@"我被调用了,是同步调用%@", msg);
return [msg stringByAppendingString:@"[syn call]"];
}
// 异步API
- (void)testAsyn:(NSString *)msg :(JSCallback)completionHandler {
Log(@"我被调用了,是异步调用%@", msg);
completionHandler([msg stringByAppendingString:@"[asyn call]"], YES);
}
@end
之后在Controller使用它
#import "DZWebViewController.h"
#import <WebKit/WebKit.h>
#import "DWKWebView.h"
#import "JSApi.h"
@interface DZWebViewController () <WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler>
@property (nonatomic, strong) DWKWebView *dwebview;
//@property (nonatomic, strong) WKWebView *dwebview;
@end
@implementation DZWebViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.dwebview = [[DWKWebView alloc] initWithFrame:CGRectZero];
// 开启Debug调试模式
[self.dwebview setDebugMode:true];
self.dwebview.DSUIDelegate = self;
// 导航代理
self.dwebview.navigationDelegate = self;
// 是否允许手势左滑返回上一级, 类似导航控制的左滑返回
self.dwebview.allowsBackForwardNavigationGestures = YES;
[self.view addSubview:self.dwebview];
[self.dwebview mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view.mas_left);
make.right.equalTo(self.view.mas_right);
make.top.equalTo(self.vNavigation.mas_bottom);
make.bottom.equalTo(self.view.mas_bottom);
}];
// 重点:注册API,其中echo为API的空间名(这个JSApi 的 NSObject 里面的函数就是 给 Vue调用 iOS 的函数)
[self.dwebview addJavascriptObject:[[JSApi alloc] init] namespace:@"echo"];
[self.dwebview loadUrl:@"http://172.19.23.47:8080"];
// 让Xcode的控制台可以打印HTML的console.log
[self catchJsLog];
}
// 重写html的Log打印方法,因为在网页中的打印不会在Xcode的控制台出现。所以重写方法后,让其打印可以在Xcode的控制台出现.
- (void)catchJsLog{
if(DEBUG){
NSString *sJS = @"console.log = (function(oriLogFunc){return function(str){oriLogFunc.call(console,str);window.webkit.messageHandlers.log.postMessage(str);}})(console.log);";
WKUserScript *script = [[WKUserScript alloc] initWithSource:sJS injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.dwebview.configuration.userContentController addUserScript:script];
[self.dwebview.configuration.userContentController addScriptMessageHandler:self name:@"log"];
}
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"log"]) {
Log(@"Web页面打印:%@", message.body);
}
}
#pragma mark - WKNavigationDelegate
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
Log(@"页面开始加载时调用");
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {
Log(@"页面加载失败时调用");
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
Log(@"当内容开始返回时调用");
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
Log(@"页面加载完成之后调用");
// 重点(这个是在页面加载结束时才调用Vue里面的函数)(这个callJsFunction就是 iOS 调用 Vue的函数)
[self.dwebview callHandler:@"callJsFunction" arguments:@[@"我是登录信息",@"我是用户信息"] completionHandler:^(NSNumber* value){
Log(@"%@",value);
}];
}
@end
这样一来 iOS 在 didFinishNavigation 调用后,使用callJsFunction 就能调用到 Vue中的函数。完成了iOS-Vue 交互。
同时点击网页的确认按钮后,就能调用到 iOS 中的函数。完成了Vue-iOS 交互。
文章就写到了这里。有什么问题的可以评论讨论交流。感谢!!!
网友评论