全部产品
Search
文档中心

SuperApp:自定义JSAPI参考

更新时间:Jan 23, 2025

WindVane容器提供的JSAPI,如果不能满足您的业务需求,您可以通过自定义JSAPI,实现特定的功能特性。本文介绍在Android/iOS平台自定义JSAPI的详细操作。

Android端

本文以如何扩展一个Toast为例进行说明。

  1. 首先加入您的原生插件实现。

    public class CustomToastPlugin extends WVApiPlugin {
        @Override
        protected boolean execute(Stringaction, String params, WVCallBackContext wvCallBackContext) {
            JSONObject jsonObject = null;
            try {
                jsonObject = new JSONObject(params);
                String content =jsonObject.optString("content");
                if("long".equals(action)) {
                    Toast.makeText(mContext,content, Toast.LENGTH_LONG).show();
                } else if("short".equals(action)) {
                    Toast.makeText(mContext,content, Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
            return true;
        }
    }
  2. 调用插件管理器注册该插件。

    EmasHybridApi.registerPlugin("Toast", CustomToastPlugin.class);

这样就成功注册了一个叫做Toast的插件,它含有两个函数shortlong两个JSAPI,需要前端传递叫做content的参数,即Toast需要显示的内容。

iOS端

  1. 注册JSAPI。容器提供了两种注册方案:动态注册和静态注册。

    • 动态注册:无需主动注册给WindVane容器,使用简单方便。但是要求类名与JSAPI调用时的ClassName相同。

    • 静态注册:需要调用WindVane容器的注册方法,使用操作复杂。不要求特定的类名,会更加灵活。

      总之,只要JSAPI调用的ClassName并没有被占用,那么建议使用动态注册的方式。

  2. iOS动态注册JSAPI。

    WindVane容器提供了新版本的用法,在WVBridgeCallbackContext中统一提供了JSAPI需要的所有功能。

    假设需要实现JSAPI:WVPay.pay,那么JSAPI的ClassName是WVPay,HandlerName是pay。

    • 创建一个WVPay类(动态注册要求与JSBridge调用时的ClassName相同),需要确保不会有同名类。

    • 令WVPay类继承自WVDynamicHandler(引入头文件<WindVaneCore/WindVaneCore.h>)。

    • 实现pay方法,要求方法的签名必须为+ (void)pay:(NSDictionary *)params withWVBridgeContext:(id<WVBridgeCallbackContext>)context,其中:

      • 方法可以是静态方法,也可以是动态方法。实例方法会直接调用,实例方法会先创建一个实例,然后在实例上调用。

      • 方法名与JSAPI调用的HandlerName相同,这里为pay。

      • 第一个参数为NSDictionary *,是JS传入的参数对象。

      • 第二个参数为 id<WVBridgeCallbackContext>,是JSBridge的调用上下文。

    • 在方法中实现JSAPI的逻辑,使用[context callbackSuccess:RESULT]/[context callbackFailure:RET withResult:RESULT]来输出执行成功/失败的结果返回给JSAPI调用方。请保证任何情况下都会调用、且只会调用一次[context callbackXXX]系列方法。

      说明
      • JSAPI总是在主线程调用,如果有耗时操作,请务必自行切换线程。

      • 您提供的服务可能带有多个阶段输出性,请使用[context dispatchEvent:eventName withParam:param]将结果通过事件的方式输出给JSBridge调用方。

      • 当你的JSAPI逻辑执行完毕,可以主动调用[context releaseHandler:self]方法来主动释放内存,否则就只能等到页面销毁的时候才会释放。注意在dealloc中调用是没有意义的,因为此时对象已经被释放了。

      @interface WVPay : WVDynamicHandler
      @end
      
      @implementation WVPay
      + (void)pay:(NSDictionary *)params withWVBridgeContext:(id<WVBridgeCallbackContext>)context {
          NSString * merchant = [params wvStringValue:@"merchant"];
          
          if ([NSString wvIsBlank:merchant]) {
              [context callbackFailure:WMBridgeStatusParamError withResult:@{@"message": @"Empty merchant"}];
          } else {
              //后续操作
              [context callbackSuccess:nil];
          }
      }
      
      @objc(WVPay)
      class WVPay: WVDynamicHandler {
          
          @objc static func pay(_ params: [String: Any], withWVBridgeContext context: WVBridgeCallbackContext) {
              if let merchant = params["merchant"] as? String, merchant.count > 0{
                  //后续操作
                  context.callbackSuccess(nil)
                  
              }else {
                  context.callbackFailure(WMBridgeStatus.paramError, withResult: ["message":"Empty merchant"])
              }
          }
      
      }
      

      动态注册的JSAPI,要求类名不能重复。若希望扩展现有ClassName,可以使用JSAPI别名。

  3. iOS静态注册。

    WindVane容器允许注册到全局,可以在任意 WebView 中调用。

    #import <WindmillBridge/WMBridgeProtocol.h>
    
    WMBridgeHandler handler = ^(NSDictionary * params, id<WMBridgeCallbackContext> context) {
    	[context callbackSuccess:nil];
    };
    
    WMBridgeRegisterHandler(@"WVPay.pay", handler);
    
    let handler: WMBridgeHandler = { (params:Dictionary?, context: WMBridgeCallbackContext) in
                        
         context.callbackSuccess(nil)
     }
     WMBridgeRegisterHandler("WVPay.pay", handler)
    

前端

前端需集成windvane.js,在Android或iOS中添加相应接口后,则可以在前端业务代码里直接调用自定义JSAPI,示例代码如下。

window.WindVane.call(
  'WVPay', 
  'pay', 
  {merchant: ''}, 
  function(e) {
    alert('success:' + JSON.stringify(e));
  }, function(e) {
        alert('failure:' + JSON.stringify(e));
});