hbuilder支持java插件_HBuilder 第三方插件开发
本人最近開發(fā)了 HBulider 集成極光推送(JPush)的插件,鑒于 HBuilder 官網(wǎng)上缺少 iOS 的示例 ,而且官網(wǎng)也只給出了 JavaScript 調(diào)用 native 代碼的接口,對于 native 調(diào)用 JavaScript 并且向 JavaScript 發(fā)送 event 事件的方法卻在 native層 進行了封裝。筆者在踩過了一些小坑之后,終于成功的開發(fā)了插件,并且 實現(xiàn)了 JavaScript 和 native 的雙向溝通 。特此跟大家分享一下在 HBuilder 插件開發(fā)過程中的經(jīng)驗和關(guān)鍵代碼。
JPush 實例展示
實例及功能展示
以上即為根據(jù)本文內(nèi)容開發(fā)出的實例
如您需使用極光推送產(chǎn)品請至此 [極光推送官方網(wǎng)站]
新插件配置
配置 manifest.json
首先用源碼的方式打開工程 /Pandora/ 目錄下的 manifest.json ,在 "permissions" 中添加新的插件名稱:
"permissions": {
"Push":{
"description": "極光推送插件"
}
},
配置 feature.plist
在 Xcode 中打開 /PandoraApi.bundle/ 目錄下的 feature.plist ,為插件添加新的 item:
feature.plist
其中需要注意的是:
最頂部的 key 值 Push ,必須跟 manifest.json 中配置的插件名一致
class 的值需要跟 native 代碼中的類名一致,此處為 JPushPlugin
因為本插件拓展自 HBuilder 已經(jīng)封裝好的 PGPush ,故 baseclass 為父類
通過以上配置,就可以在 JavaScript 中通過 Push --> JPushPlugin 的對應(yīng)關(guān)系,調(diào)用 native 代碼了。
JavaScript 調(diào)用本地代碼的實現(xiàn)
這部分在 [HBuilder 官網(wǎng)插件開發(fā)指導] 中已經(jīng)給出了較詳細的說明,這里就不再贅述,附上關(guān)鍵代碼:
document.addEventListener("plusready", function() {
var _BARCODE = 'Push'; // 插件名稱
var B = window.plus.bridge;
var JPushPlugin = {
callNative : function(fname, args, successCallback) {
var callbackId = this.getCallbackId(successCallback, this.errorCallback);
if (args != null) {
args.unshift(callbackId);
} else {
var args = [callbackId];
}
return B.exec(_BARCODE, fname, args);
},
getCallbackId : function(successCallback) {
var success = typeof successCallback !== 'function' ? null : function(args)
{
successCallback(args);
};
callbackId = B.callbackId(success, this.errorCallback);
return callbackId;
},
errorCallback : function(errorMsg) {
console.log("Javascript callback error: " + errorMsg);
},
jsHello : function(args){
this.callNative("nativeHello", args, null);
},
window.plus.Push = JPushPlugin;
}, true);
其中 callNative 為封裝好用于調(diào)用 native 代碼的方法,參數(shù)如下:
fname:要調(diào)用的 native 的方法名
args:傳給 native 的參數(shù),必須是數(shù)組
successCallback:成功回調(diào),null 為沒有
以上代碼最后面的 "jsHello" 方法,即為封裝好的 js 方法,在工程的其他文件里通過
window.plus.Push.jsHello(args);
的方式即可調(diào)用本地的 "nativeHello" 方法。
Objective-C 調(diào)用 js 的實現(xiàn)
與 Phonegap 的差異
在 HBuilder 官方文檔中并沒有提及 OC 調(diào)用 js 的方法,從 OC 中的類名(PGPlugin 等)可以看出,其應(yīng)該是對 Phonegap 的封裝,但是卻并沒有提供 Phonegap 中直接調(diào)用 js 的接口,例如:
NSString *evalString = [NSString stringWithFormat:@"jsFunction(%@)",args];
[self.commandDelegate evalJs:evalString];
也無法向 js 發(fā)送 event ,例如:
NSString *evalString = [NSString stringWithFormat:@"cordova.fireDocumentEvent('event_name',%@)",args];
[self.commandDelegate evalJs:evalString];
其中 self 為繼承自 CDVPlugin 的插件類實例。
經(jīng)過筆者的查找,發(fā)現(xiàn)在 HBuilder 提供的 PDRCoreAppFrame(:PDRNView :UIView) 類中,有如下方法可以調(diào)用 js 代碼:
/**
@brief 在當前頁面同步執(zhí)行Javascript
@param js javasrcipt 腳本
@return NSString* 執(zhí)行結(jié)果
*/
- (NSString*)stringByEvaluatingJavaScriptFromString:(NSString*)js;
獲取 PDRCoreAppFrame 對象
其中 PDRCoreAppFrame 為控制 webView 的實例,數(shù)量可能為多個,且在視圖層級中的位置不確定,故需要通過遍歷 app 中所有 view ,來找出 PDRCoreAppFrame ,以下是通過 遞歸 找出所有 PDRCoreAppFrame 的方法:
-(NSMutableArray*)searchViews:(NSArray*)views{
NSMutableArray *frames = [NSMutableArray array];
for (UIView *temp in views) {
if ([temp isMemberOfClass:[PDRCoreAppFrame class]]) {
[frames addObject:temp];
}
if ([temp subviews]) {
NSMutableArray *tempArray = [self searchViews:[temp subviews]];
for (UIView *tempView in tempArray) {
if ([tempView isMemberOfClass:[PDRCoreAppFrame class]]) {
[frames addObject:tempView];
}
}
}
}
return frames;
}
其中:
參數(shù) views 為同一層級中的 views
返回值 frames 為從該層級中找到的 PDRCoreAppFrame
調(diào)用 js
這樣我們就可以用上述方法獲取到所有的 PDRCoreAppFrame 進而調(diào)用 js 代碼了:
-(void)evaluatingJavaScriptFromString:(NSString*)string{
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
NSArray *views = [[[window rootViewController] view] subviews];
//調(diào)用上述方法
NSArray *frames = [self searchViews:views];
for (PDRCoreAppFrame *appFrame in frames) {
dispatch_async(dispatch_get_main_queue(), ^{
[appFrame stringByEvaluatingJavaScriptFromString:string];
});
}
}
調(diào)用示例:
NSString *evalString = @"alert("make a js call");";
[self evaluatingJavaScriptFromString:evalString];
但是并不建議用這種方式,因為該方法會強制向每個 webView 的頁面都發(fā)送一條執(zhí)行語句,有時會出現(xiàn)并不希望的結(jié)果。因此,建議使用下面發(fā)送 event 的方式,并在 js 中接收后進行處理。
向 js 發(fā)送 event
筆者對上述方法再次進行了封裝:
-(void)fireEvent:(NSString*)event args:(id)args{
NSString *evalString = nil;
NSError *error = nil;
NSString *argsString = nil;
if (args) {
if ([args isKindOfClass:[NSString class]]) {
argsString = args;
}else{
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:args options:0 error:&error];
argsString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
if (error) {
NSLog(@"%@",error);
}
}
evalString = [NSString stringWithFormat:@"\
var jpushEvent = document.createEvent('HTMLEvents');\
jpushEvent.initEvent('%@', true, true);\
jpushEvent.eventType = 'message';\
jpushEvent.arguments = '%@';\
document.dispatchEvent(jpushEvent);",event,argsString];
}else{
evalString = [NSString stringWithFormat:@"\
var jpushEvent = document.createEvent('HTMLEvents');\
jpushEvent.initEvent('%@', true, true);\
jpushEvent.eventType = 'message';\
document.dispatchEvent(jpushEvent);",event];
}
//調(diào)用上述方法
[self evaluatingJavaScriptFromString:evalString];
}
其中對傳入的 args 進行了簡單的處理。
最后我們通過調(diào)用一行代碼即可做到向 js 發(fā)送 event :
[self fireEvent:@"event_name" args:args];
js 接收 event 并處理
在上一步中發(fā)送了 "event_name" 的事件之后,可以在 html 的 script 中通過以下方式捕獲:
document.addEventListener("event_name", onEventFunc, false);
function onEventFunc(args){
var obj = JSON.parese(args);
window.setTimeout(function(){
alert(obj);
},0);
}
至此,就徹底實現(xiàn)了 Objective-C 向 js 的溝通
* 如您對本文有任何疑問或建議,歡迎交流
版權(quán)印為您的作品印上版權(quán)
總結(jié)
以上是生活随笔為你收集整理的hbuilder支持java插件_HBuilder 第三方插件开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php html 伪静态,php 伪静态
- 下一篇: Leetcode怎么调试java代码,在