zoukankan      html  css  js  c++  java
  • native.js是什么且如何使用

    native.js是什么且如何使用

    一、总结

    一句话总结:Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。Native.js不是一个js库,不需要下载引入到页面的script中,也不像nodejs那样有单独的运行环境,Native.js的运行环境是集成在5+runtime里的,使用HBuilder打包的app或流应用都可以直接使用Native.js。

    二、Native.js使用入门

    1、概述

    Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。如果说Node.js把js扩展到服务器世界,那么Native.js则把js扩展到手机App的原生世界。HTML/JS/Css全部语法只有7万多,而原生语法有几十万,Native.js大幅提升了HTML5的能力。NJS突破了浏览器的功能限制,也不再需要像Hybrid那样由原生语言开发插件才能补足浏览器欠缺的功能。NJS编写的代码,最终需要在HBuilder里打包发行为App安装包,或者在支持Native.js技术的浏览器里运行。目前Native.js技术不能在普通手机浏览器里直接运行。

    • NJS大幅扩展了HTML5的能力范围,原本只有原生或Hybrid App的原生插件才能实现的功能如今可以使用JS实现。
    • NJS大幅提升了App开发效率,将iOS、Android、Web的3个工程师组队才能完成的App,变为1个web工程师就搞定。
    • NJS不再需要配置原生开发和编译环境,调试、打包均在HBuilder里进行。没有mac和xcode一样可以开发iOS应用。
    • 如果不熟悉原生API也没关系,我们汇总了很多NJS的代码示例,复制粘贴就可以用。http://ask.dcloud.net.cn/article/114

         再次强调,Native.js不是一个js库,不需要下载引入到页面的script中,也不像nodejs那样有单独的运行环境,Native.js的运行环境是集成在5+runtime里的,使用HBuilder打包的app或流应用都可以直接使用Native.js。

    技术要求

       由于NJS是直接调用Native API,需要对Native API有一定了解,知道所需要的功能调用了哪些原生API,能看懂原生代码并参考原生代码修改为JS代码。否则只能直接copy别人写好的NJS代码。

    2、开始使用

    2.1、判断平台

    Native API具有平台依赖性,所以需要通过以下方式判断当前的运行平台:

    1. function judgePlatform(){  
    2.     switch ( plus.os.name ) {  
    3.         case "Android":  
    4.         // Android平台: plus.android.*  
    5.         break;  
    6.         case "iOS":  
    7.         // iOS平台: plus.ios.*  
    8.         break;  
    9.         default:  
    10.         // 其它平台  
    11.         break;  
    12.     }  
    13. }  

    2.2、类型转换

    在NJS中调用Native API或从Native API返回数据到NJS时会自动转换数据类型。

    类型转换表

    类型Objective-CJavaJavaScript
    基本数据 byte/short/int/long/float/double/... byte/short/int/long/float/double/... Number
    字符 char char String
    字符串 NSString/@"" String/"" String
    数组 @[1,2,3]/NSArray new XXX[] InstanceObject
    @interface class ClassObject
    对象(实例) * * InstanceObject
    空对象 nil null null
    其它 Protocol Interface Object(JSON)

    2.3、其他转换

    • Android原生应用的主Activity对象 转为plus.android.runtimeMainActivity()
      Android的主Activity对象是启动应用时自动创建的,不是代码创建,此时通过plus.android.runtimeMainActivity()方法获取该Activity对象
    • Objective-C方法冒号剔除
      [pos setPositionX:(int)x Y:(int)y;] 转为 pos.setPositionXY(x,y);
      OC语法中方法的定义格式为:
      “(返回值类型) 函数名: (参数1类型) 形参1 参数2名称: (参数2类型) 形参2”
      方法的完整名称为: “函数名:参数2名称:”。
      如:“(void)setPositionX:(int)x Y:(int)y;”,方法的完整名称为“setPositionX:Y:”,调用时语法为:“[pos setPositionX:x Y:y];”。
      在JS语法中函数名称不能包含“:”字符,所以OC对象的方法名映射成NJS对象方法名时将其中的“:”字符自动删除,上面方法名映射为“setPositionXY”,在NJS调用的语法为:“pos.setPositionXY(x,y);”。
    • 文件路径转换
      Web开发里使用的image/1.png是该web工程的相对路径,而原生API中经常需要使用绝对路径,比如/sdcard/apptest/image/1.png,此时使用这个扩展方法来完成转换:plus.io.convertLocalFileSystemURL("image/1.png")

     2.4、概念

     2.4.1、类对象

    由于JavaScript中本身没有类的概念,为了使用Native API层的类,在NJS中引入了类对象(ClassObject)的概念,用于对Native中的类进行操作,如创建类的实例对象、访问类的静态属性、调用类的静态方法等。其原型如下:

     
    1. Interface ClassObject {  
    2.     function Object plusGetAttribute( String name );  
    3.     function void plusSetAttribute( String name, Object value );  
    4. }  

    2.4.2、获取类对象
          在iOS平台我们可以通过plus.ios.importClass(name)方法导入类对象,参数name为类的名称;在Android平台我们可以通过plus.android.importClass(name)方法导入类对象,其参数name为类的名称,必须包含完整的命名空间。

    示例:

     
    1. // iOS平台导入NSNotificationCenter类  
    2. var NSNotificationCenter = plus.ios.importClass("NSNotificationCenter");  
    3.   
    4. // Android平台导入Intent类  
    5. var Intent = plus.android.importClass("android.content.Intent");  

         获取类对象后,可以通过类对象“.”操作符获取类的静态常量属性、调用类的静态方法,类的静态非常量属性需通过plusGetAttribute、plusSetAttribute方法操作。

    实例对象

    在JavaScript中,所有对象都是Object,为了操作Native层类的实例对象,在NJS中引入了实例对象(InstanceObject)的概念,用于对Native中的对象进行操作,如操作对象的属性、调用对象的方法等。其原型如下:

     
    1. Interface InstanceObject {  
    2.     function Object plusGetAttribute( String name );  
    3.     function void plusSetAttribute( String name, Object value );  
    4. }  

    2.4.3、获取实例对象
    有两种方式获取类的实例对象,一种是调用Native API返回值获取,另一种是通过new操作符来创建导入的类对象的实例,如下:

     
    1. // iOS平台导入NSDictionary类  
    2. var NSDictionary = plus.ios.importClass("NSDictionary");  
    3. // 创建NSDictionary的实例对象  
    4. var ns = new NSDictionary();  
    5.   
    6. // Android平台导入Intent类  
    7. var Intent = plus.android.importClass("android.content.Intent");  
    8. // 创建Intent的实例对象  
    9. var intent = new Intent();  

    获取实例对象后,可以通过实例对象“.”操作符获取对象的常量属性、调用对象的成员方法,实例对象的非常量属性则需通过plusGetAttribute、plusSetAttribute方法操作。

    操作对象的属性方法

    • 常量属性
      获取对象后就可以通过“.”操作符获取对象的常量属性,如果是类对象则获取的是类的静态常量属性,如果是实例对象则获取的是对象的成员常量属性。

       
    • 非常量属性
      如果Native层对象的属性值在原生环境下被更改,此时使用“.”操作符获取到对应NJS对象的属性值就可能不是实时的属性值,而是该Native层对象被映射为NJS对象那一刻的属性值。
      为获取获取Native层对象的实时属性值,需调用NJS对象的plusGetAttribute(name)方法,参数name为属性的名称,返回值为属性的值。调用NJS对象的plusSetAttribute(name,value)方法设置Native层对象的非常量属性值,参数name为属性的名称,value为要设置新的属性值。
      注意:使用plusGetAttribute(name)方法也可以获取Native层对象的常量属性值,但不如直接使用“.”操作符来获取性能高。

    • 方法
      获取对象后可以通过“.”操作符直接调用Native层方法,如果是类对象调用的是Native层类的静态方法,如果是实例对象调用的是Native层对象的成员方法。
      注意:在iOS平台由于JS语法的原因,Objective-C方法名称中的“:”字符转成NJS对象的方法名称后将会被忽略,因此在NJS中调用的方法名需去掉所有“:”字符。

    • 类的继承
      Objective-C和Java中类如果存在继承自基类,在NJS中对应的对象会根据继承关系递归将所有基类的公有方法一一换成NJS对象的方法,所有基类的公有属性也可以通过其plusGetAttribute、plusSetAttribute方法访问。

       

    3、开始写NJS

    使用NJS调用Native API非常简单,基本步骤如下:
    a. 导入要使用到的类;
    b. 创建类的实例对象(或者调用类的静态方法创建);
    c. 调用实例对象的方法;

    以下例子使用NJS调用iOS和Android的原生弹出提示框(类似但不同于js的alert)。

    Android

    以下代码在Android平台展示调用Native API显示系统提示框。
    首先是Android原生 Java代码,用于比对参考:

    1. import android.app.AlertDialog;  
    2. //...  
    3. // 创建提示框构造对象,Builder是AlertDialog的内部类。参数this指代Android的主Activity对象,该对象启动应用时自动生成  
    4. AlertDialog.Builder dlg = new AlertDialog.Builder(this);  
    5. // 设置提示框标题  
    6. dlg.setTitle("自定义标题");  
    7. // 设置提示框内容  
    8. dlg.setMessage("使用NJS的原生弹出框,可自定义弹出框的标题、按钮");  
    9. // 设置提示框按钮  
    10. dlg.setPositiveButton("确定(或者其他字符)", null);  
    11. // 显示提示框  
    12. dlg.show();  
    13. //...  

    Native.js代码:

    1. /** 
    2.  * 在Android平台通过NJS显示系统提示框 
    3.  */  
    4. function njsAlertForAndroid(){  
    5.     // 导入AlertDialog类  
    6.     var AlertDialog = plus.android.importClass("android.app.AlertDialog");  
    7.     // 创建提示框构造对象,构造函数需要提供程序全局环境对象,通过plus.android.runtimeMainActivity()方法获取  
    8.     var dlg = new AlertDialog.Builder(plus.android.runtimeMainActivity());  
    9.     // 设置提示框标题  
    10.     dlg.setTitle("自定义标题");  
    11.     // 设置提示框内容  
    12.     dlg.setMessage("使用NJS的原生弹出框,可自定义弹出框的标题、按钮");  
    13.     // 设置提示框按钮  
    14.     dlg.setPositiveButton("确定(或者其他字符)",null);  
    15.     // 显示提示框  
    16.     dlg.show();  
    17. }  
    18. //...  

    注意:NJS代码中创建提示框构造对象要求传入程序全局环境对象,可通过plus.android.runtimeMainActivity()方法获取应用的主Activity对象,它是Html5+应用运行期自动创建的程序全局环境对象。

    Android设备上运行效果图:
    Android Native.js示例运行效果图
    `注意:其实HTML5+规范已经封装过原生提示框消息API:plus.ui.alert( message, alertCB, title, buttonCapture)。此处NJS的示例仅为了开发者方便理解,实际使用时调用plus.ui.alert更简单,性能也更高。**

    iOS

    以下代码在iOS平台展示调用Native API显示系统提示对话框。
    iOS原生Objective-C代码,用于比对参考:

    1. #import <UIKit/UIKit.h>  
    2. //...  
    3. // 创建UIAlertView类的实例对象  
    4. UIAlertView *view = [UIAlertView alloc];  
    5. // 设置提示对话上的内容  
    6. [view initWithTitle:@"自定义标题" // 提示框标题  
    7.     message:@"使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容  
    8.     delegate:nil // 点击提示框后的通知代理对象,nil类似js的null,意为不设置  
    9.     cancelButtonTitle:@"确定(或者其他字符)" // 提示框上取消按钮的文字  
    10.     otherButtonTitles:nil]; // 提示框上其它按钮的文字,设置为nil表示不显示  
    11. // 调用show方法显示提示对话框,在OC中使用[]语法调用对象的方法  
    12. [view show];  
    13. //...  

    Native.js代码:

     
    1. /** 
    2.  * 在iOS平台通过NJS显示系统提示框 
    3.  */  
    4. function njsAlertForiOS(){  
    5.     // 导入UIAlertView类  
    6.     var UIAlertView = plus.ios.importClass("UIAlertView");  
    7.     // 创建UIAlertView类的实例对象  
    8.     var view = new UIAlertView();  
    9.     // 设置提示对话上的内容  
    10.     view.initWithTitlemessagedelegatecancelButtonTitleotherButtonTitles("自定义标题" // 提示框标题  
    11.         , "使用NJS的原生弹出框,可自定义弹出框的标题、按钮" // 提示框上显示的内容  
    12.         , null // 操作提示框后的通知代理对象,暂不设置  
    13.         , "确定(或者其他字符)" // 提示框上取消按钮的文字  
    14.         , null ); // 提示框上其它按钮的文字,设置为null表示不显示  
    15.     // 调用show方法显示提示对话框,在JS中使用()语法调用对象的方法  
    16.     view.show();  
    17. }  
    18. //...  

    注意:在OC语法中方法的定义格式为:
    “(返回值类型) 函数名: (参数1类型) 形参1 参数2名称: (参数2类型) 形参2”
    方法的完整名称为: “函数名:参数2名称:”。
    如:“(void)setPositionX:(int)x Y:(int)y;”,方法的完整名称为“setPositionX:Y:”
    调用时语法为:“[pos setPositionX:x Y:y];”。
    在JS语法中函数名称不能包含“:”字符,所以OC对象的方法名映射成NJS对象方法名时将其中的“:”字符自动删除,上面方法名映射为“setPositionXY”,在NJS调用的语法为:“pos.setPositionXY(x,y);”。

    iOS设备上运行效果图:
    iOS Native.js示例运行效果图
    `注意:其实HTML5+规范已经封装过原生提示框消息API:plus.ui.alert( message, alertCB, title, buttonCapture)。此处NJS的示例仅为了开发者方便理解,实际使用时调用plus.ui.alert更简单、性能也更高。

    在HBuilder自带的Hello H5+模板应用中“Native.JS”(plus/njs.html)页面有完整的源代码,可真机运行查看效果。

    ------------------

    转载 :http://blog.csdn.net/qq_27626333/article/details/51853039

     

    三、Native.js示例汇总

    Native.js虽然强大和开放,但很多web开发者因为不熟悉原生API而难以独立完成。
    这篇帖子的目的就是汇总各种写好的NJS代码,方便web开发者。
    众人拾柴火焰高,有能力的开发者多多提交NJS代码,大家都会给你点赞的,我们也会为每位共享NJS代码的朋友送上200积分。

    Android平台

    调用Android本地分享

    http://ask.dcloud.net.cn/article/134

    直接拨打电话

    http://ask.dcloud.net.cn/question/4035

    将程序切换到后台

    http://ask.dcloud.net.cn/question/2484

    强制弹出软键盘

    http://ask.dcloud.net.cn/question/2324

    获取安卓设备device.uuid

    http://ask.dcloud.net.cn/question/3510

    获取内存及CPU信息

    http://ask.dcloud.net.cn/question/2202

    开启关闭蓝牙

    http://ask.dcloud.net.cn/question/4720

    监听蓝牙开关状态

    http://ask.dcloud.net.cn/article/274

    获取蓝牙设备列表

    http://ask.dcloud.net.cn/question/8265

    蓝牙连接票据打印机完整代码

    http://ask.dcloud.net.cn/article/643

    NFC数据读取

    http://ask.dcloud.net.cn/question/6726

    截屏

    http://ask.dcloud.net.cn/question/5344

    获取MAC地址

    http://ask.dcloud.net.cn/question/1511

    获取设备当前网速

    http://ask.dcloud.net.cn/article/773

    打开网络设置

    http://ask.dcloud.net.cn/question/1475

    打开各种系统设置界面

    http://ask.dcloud.net.cn/question/14732

    获取WIFI列表

    http://ask.dcloud.net.cn/question/12113

    调用系统控件播放视频

    http://ask.dcloud.net.cn/question/614

    调用os通讯录选择控件

    http://ask.dcloud.net.cn/question/5783

    原生日历提醒插入

    http://ask.dcloud.net.cn/article/215

    调用系统控件裁剪图片

    http://ask.dcloud.net.cn/question/8314

    复制内容到系统粘贴板

    http://ask.dcloud.net.cn/question/2034

    调用讯飞的文字转语音功能(TTS)

    http://ask.dcloud.net.cn/question/6473

    调用其它Activity后通过startActivityForResult获取返回结果

    http://ask.dcloud.net.cn/question/5783

    接收系统广播消息,如监听安装卸载apk的事件

    http://ask.dcloud.net.cn/article/222

    判断app是否安装

    http://ask.dcloud.net.cn/question/7604

    以监听手机飞行模式开关为例说明如何使用Native.js进行BroadcastReceiver广播

    http://ask.dcloud.net.cn/question/7661

    常驻Android通知栏,不用个推实现本地消息推送(Local Notification)

    http://ask.dcloud.net.cn/question/2464

    调用原生的socket连接

    http://ask.dcloud.net.cn/question/60

    启动一个原生service

    http://ask.dcloud.net.cn/question/433

    基于native.js的文件系统管理功能实现

    http://ask.dcloud.net.cn/article/809

    打开闪光灯

    http://ask.dcloud.net.cn/question/19379

    停止、开启个推推送功能

    var pushManager = plus.android.importClass("com.igexin.sdk.PushManager");
    var context = plus.android.runtimeMainActivity();
    function enable() {
        pushManager.getInstance().turnOnPush(context);
    }
    
    function disable() {
        pushManager.getInstance().turnOffPush(context);
    }
    

    感谢yeahcheung分享

    利用native.js获取手机gps是否开启

    http://ask.dcloud.net.cn/question/11890

    通过native.js设置系统墙纸

    http://ask.dcloud.net.cn/article/651

    监听短信验证码

    http://ask.dcloud.net.cn/article/676

    限制手机录像时间

    http://ask.dcloud.net.cn/question/45756

    iOS平台

    获取包名

    var NSBundle = plus.ios.importClass('NSBundle');
    var bundle = NSBundle.mainBundle();
    console.log(bundle.bundleIdentifier());
    plus.ios.deleteObject(bundle);
    

    获取设备名

    http://ask.dcloud.net.cn/question/14691

    测试是否安装某应用

    http://ask.dcloud.net.cn/question/14430

    调用iOS打印API

    http://ask.dcloud.net.cn/question/4226

    通过native.js登入game center

    见Hello H5+里Native.js部分演示及源码。
    或在这里搜索“game center”,http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/88

    设置获取内容到系统粘贴板

    http://ask.dcloud.net.cn/question/3720

    打开页面默认弹出键盘

    http://ask.dcloud.net.cn/question/2324

    播放提示音

    http://ask.dcloud.net.cn/question/3962

    调用ios的文字转语音(TTS)

    http://ask.dcloud.net.cn/question/4175

    把base64数据保存为图片

    http://ask.dcloud.net.cn/question/6190

    设置webview滑动减速度

    var webview = plus.ios.currentWebview();
    var scrollView = webview.plusGetAttribute("scrollView");
    scrollView.plusSetAttribute("decelerationRate:",0.99);
    

    打开ios的Wifi设置页面

    http://ask.dcloud.net.cn/question/7797

    判断是否开启消息通知

    http://ask.dcloud.net.cn/question/4497

    检测iOS是否允许使用相机(感谢小闹分享)

    http://ask.dcloud.net.cn/article/188

    ios获取系统的时区id

    var NSTimeZone = plus.ios.importClass("NSTimeZone");
    var sys = NSTimeZone.systemTimeZone();
    console.log(sys.plusGetAttribute("name"));
    

    状态栏显示网络请求雪花

    var UIApplication = plus.ios.import("UIApplication");
    var sharedApplication = UIApplication.sharedApplication();
    sharedApplication.setNetworkActivityIndicatorVisible(true);
    plus.ios.deleteObject(sharedApplication);
    

    获取GPS授权状态

    var CLLocationManager = plus.ios.import("CLLocationManager");
    var authorizationStatus = CLLocationManager.authorizationStatus();
    switch(authorizationStatus) {
          case 0:
          /// User has not yet made a choice with regards to this application
          break;
          case 1:
          // This application is not authorized to use location services.  Due
        // to active restrictions on location services, the user cannot change
        // this status, and may not have personally denied authorization
          break;
          case 2:
            // User has explicitly denied authorization for this application, or
        // location services are disabled in Settings.
          break;
          case 3:
            // User has granted authorization to use their location at any time,
        // including monitoring for regions, visits, or significant location changes.
          break;
          case 4:
           // User has granted authorization to use their location only when your app
        // is visible to them (it will be made visible to them if you continue to
        // receive location updates while in the background).  Authorization to use
        // launch APIs has not been granted.
          break;
          case 5:
         // This value is deprecated, but was equivalent to the new -Always value.
          break;
          defalut:
          break;
    }
    

    获取手机存储空间

    var BundleClass = plus.ios.importClass("NSBundle");
    var BundleObj = BundleClass.mainBundle();
    var filenamagerobj = plus.ios.newObject("NSFileManager");
    var FileAttr = plus.ios.invoke(filenamagerobj,"attributesOfFileSystemForPath:error:",BundleObj.bundlePath(),null);
    // NSFileSystemFreeSize 参数获取剩余空间
    // NSFileSystemSize  获取手机总存储空间
    var freeSpace = plus.ios.invoke(FileAttr,"objectForKey:","NSFileSystemFreeSize");
    var numberFormatterObj = plus.ios.newObject("NSNumberFormatter");
    var FreeSpaceStr = plus.ios.invoke(numberFormatterObj,"stringFromNumber:",freeSpace);
    var freeSpace = FreeSpaceStr / 1024/1024/1024;
    

    打开/关闭手机的闪光灯

    function turnonLight(isOn) {
        if(plus.os.name == "iOS") {
            var avcaptClass = plus.ios.importClass("AVCaptureDevice");
            if(avcaptClass) {
                var device = avcaptClass.defaultDeviceWithMediaType("vide");
                plus.ios.invoke(device, "lockForConfiguration:", null);
                if(isOn) {
                    plus.ios.invoke(device, "setTorchMode:", 1);
                    plus.ios.invoke(device, "setFlashMode:", 1);
                } else {
                    plus.ios.invoke(device, "setTorchMode:", 0);
                    plus.ios.invoke(device, "setFlashMode:", 0);
                }
                plus.ios.invoke(device, "unlockForConfiguration");
            }
        }
    };
    

    显示应用内的ViewController

    // NewViewController为应用内创建的原生的ViewController类名,所调用页面的内容需要在原生代码中完成
    var newVCobj = plus.ios.newObject("NewViewController");
    var UIApplicationClass = plus.ios.importClass("UIApplication");
    var UIAppObj = UIApplicationClass.sharedApplication();
    var del = plus.ios.invoke(UIAppObj,"delegate");
    // 如果当前应用delegate对象包含UIWindow对象并且变量名命名为“window”可以这么写,
    // 否则需要根据实际代码情况修改
    // 应用的delegate对象也可以添加一个返回UIViewController的方法
    var appWindowObj = plus.ios.invoke(del,"window");
    var appRootController = plus.ios.invoke(appWindowObj,"rootViewController");
    plus.ios.invoke(appRootController,"presentViewController:animated:completion:",newVCobj,"YES",null);

    参考:Native.js示例汇总 - DCloud问答
    http://ask.dcloud.net.cn/article/114

     
  • 相关阅读:
    CLR(Common Language Runtime)
    六个经典的英语面试问题
    XML基本知识(三)
    vc++中各种字符串(转载)
    winform窗体间传值
    jQuery实现按比例缩放图片
    .net中几个名词解释
    XML Schema 定义
    C#中TreeView组件使用方法初步
    微软电话面试题
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/9381873.html
Copyright © 2011-2022 走看看