If the JavaScript APIs provided by WindVane cannot meet your business requirements, you can customize JavaScript APIs to implement specific features. This topic describes how to customize JavaScript APIs on Android and iOS devices.
Android
This topic shows an example on how to expand a plug-in for Toast messages.
Add your native plug-in implementation.
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; } }Call the plug-in manager to register the plug-in.
EmasHybridApi.registerPlugin("Toast", CustomToastPlugin.class);
A plug-in named Toast is registered. The plug-in contains two JavaScript APIs: short and long. The content parameter indicates the content of a Toast message to be displayed in the frontend.
iOS
Register a JavaScript API. EMAS provides two methods to register a JavaScript API: dynamic method and static method.
Dynamic method: This method is easy to use. You do not need to manually register a JavaScript API in WindVane. However, the class name that you use to register a JavaScript API must be the same as the class name that is used when the JavaScript API is called.
Static method: This method requires complex operations. You must use the registration method of WindVane to register a JavaScript API in WindVane. However, no limits are imposed on the class name. You can specify the class name based on your business requirements.
If the class name that is used when you call a JavaScript API is not used to register the JavaScript API, we recommend that you use the dynamic method.
Dynamically register a JavaScript API.
WindVane provides all the features required by JavaScript APIs in
WVBridgeCallbackContext.If you want to implement a JavaScript API named
WVPay.pay, set ClassName to WVPay and HandlerName to pay for the JavaScript API.Create a WVPay class. If you use the dynamic method, the name of the class must be the same as the class name that is used when JSBridge is called. Make sure that the class name is unique.
Import the <WindVaneCore/WindVaneCore.h> header file to ensure that the WVPay class inherits from the
WVDynamicHandlerclass.The signature of the method used to implement the pay method must be
+ (void)pay:(NSDictionary *)params withWVBridgeContext:(id<WVBridgeCallbackContext>)context.The method can be static or dynamic. If you use the dynamic method, the instance method is used to create an instance. Then, you can call the JavaScript API on the instance.
The method name is the same as the handler name that is used to call the JavaScript API. In this example, pay is used.
The first parameter is
NSDictionary *, which is equivalent to the objects passed in JavaScript.The second parameter is
id<WVBridgeCallbackContext>, which is the call context of JSBridge.
To implement the logic of the JavaScript API, you can use
[context callbackSuccess:RESULT]/[context callbackFailure:RET withResult:RESULT]to display the execution result and return the result to the JavaScript API caller. The result can be success or failure. Make sure that the[context callbackXXX]method is called only once to return a result.NoteThe JavaScript API is always called in the main thread. If you want to perform time-consuming operations, switch to a subthread.
If the service that is provided by your HTML5 app or miniapp returns results in phases, use
[context dispatchEvent:eventName withParam:param]to return the results as events to the JSBridge caller.When the JavaScript API is called and a result is returned, you can call the
[context releaseHandler:self]method to release memory. If you do not manually release memory, the memory is automatically released when the page is destroyed. Do not call the [contextreleaseHandler:self] method in the dealloc method because the JavaScript API is released.
@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 { //Subsequent Operations [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{ //Subsequent Operations context.callbackSuccess(nil) }else { context.callbackFailure(WMBridgeStatus.paramError, withResult: ["message":"Empty merchant"]) } } }If a JavaScript API is registered by using the dynamic method, the class name must be unique. If you want to extend the methods of an existing ClassName, you can use the JSAPI alias
Static method.
The WindVane container allows global registration and can be called in any 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)
Frontend
windvane.js is integrated in the frontend by default. After you add the implementation of a custom JavaScript API in your native Android or iOS app, you can directly call the API in the frontend business code. Sample code:
window.WindVane.call(
'WVPay',
'pay',
{merchant: ''},
function(e) {
alert('success:' + JSON.stringify(e));
}, function(e) {
alert('failure:' + JSON.stringify(e));
});