圖片來自網絡
首先我是一個半吊子的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 交互。
文章就寫到了這里。有什么問題的可以評論討論交流。感謝!!!