美文网首页
iOS、Android 与 Vue的交互(使用DSBridge第

iOS、Android 与 Vue的交互(使用DSBridge第

作者: 郑莫轩 | 来源:发表于2021-10-12 11:20 被阅读0次
    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 交互

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

    相关文章

      网友评论

          本文标题:iOS、Android 与 Vue的交互(使用DSBridge第

          本文链接:https://www.haomeiwen.com/subject/mxjdoltx.html