iOS、Android 与 Vue的交互(使用DSBridge第三方库)

ddd.jpeg

图片来自网络

首先我是一个半吊子的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号的最新版。

版本号
WeChate0ec540c345d45d646d95e124e86207b.png

我的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中,如图下所示:

WeChatee0daa179be946f9aaaef9b65a01e972.png

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 交互

文章就写到了这里。有什么问题的可以评论讨论交流。感谢!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容