Home

hogen

Follow Excellence. Success will chase you.

Home About Github Email

利用 Native.js 实现 Android 与 HTML 数据的交互

Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术,由DCloud(数字天堂)公司开发。说人话就是:通过 native.js, 你可以在 html 代码的<script></script>标签中用 native.js语法直接调用 Android 原生 API。

本次文章主要目的是学习如何利用 Native.js 实现在 HTML 中获取 Android 原生代码的数据,很多人一看到”html与Android数据交互”可能都会想到WebView,在 webview 中使用 jsBridge,是的,我一开始也是这个念头,遗憾的是我当时的项目使用的是 DCloud 的 MUI 框架,所有页面都是由 html+js 组成,几乎没怎么用到 Android 原生控件,所以这个方法行不通,当然现在的hybrid 模式的框架,原理都是封装一层 JSBridge ,通过 JSBridge 去访问原生的硬件功能。

本次项目是从AndroidStudio 创建 Hybrid App工程项目基础修改而来,把AndroidStudio 创建 Hybrid App工程没有用到的 MainActivity 加上(如果被删掉了就再创建一个),大体思路就是在 MainActivity 数据持久化,然后在 html 页面通过 native.js 获取,MainActivity修改代码如下:

public class MainActivity extends ListActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //存放一些数据到SharePreferences
        initData();
        setListAdapter(new MyListAdapter());
        getListView().setTextFilterEnabled(true);
    }

    private void initData() {
        //Log.d(TAG, "initData: hello");
        SharedPreferences sharedPreferences = getSharedPreferences("data", Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sharedPreferences.edit();
        edit.putString("data1","aaaa").putString("data2","bbbb").apply();
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Intent intent = new Intent(this,activityInfos[position].clazz);
        startActivity(intent);
    }

    ActiviyInfo[] activityInfos = new ActiviyInfo[]{
            new ActiviyInfo("SDK_APP",SDK_Runtime.class),
            new ActiviyInfo("SDK_WEBAPP",SDK_WebApp.class)
    };
    class ActiviyInfo{
        String title;
        Class<? extends Activity> clazz;

        public ActiviyInfo(String title, Class<? extends Activity> clazz) {
            this.title = title;
            this.clazz = clazz;
        }
    }
    class MyListAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return activityInfos.length;
        }

        @Override
        public Object getItem(int position) {
            return activityInfos[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv = new TextView(parent.getContext());
            tv.setHeight(100);
            tv.setGravity(Gravity.CENTER);
            tv.setText(activityInfos[position].title);
            convertView = tv;
            return convertView;
        }
    }
}

上面代码我直接用了 Android-SDK 中 HBuilder-Integrate 中的代码,MainActivity 中的SDK_Runtime 和 SDK_Webapp 类 直接从 HBuilder-Integrate/src下拷贝过来的

image

当然,在AndroidManifest.xml中要配置 activity(这里贴出主要代码)

<application
    android:name="io.dcloud.application.DCloudApplication"
    android:allowClearUserData="true"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:largeHeap="true">
    <activity
        android:name="io.dcloud.PandoraEntry"
        android:configChanges="orientation|keyboardHidden|keyboard|navigation"
        android:hardwareAccelerated="true"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:screenOrientation="user"
        android:theme="@style/TranslucentTheme"
        android:windowSoftInputMode="adjustResize">
    </activity>
    <activity android:name=".MainActivity"
        android:theme="@style/AppTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="io.dcloud.PandoraEntryActivity"
        android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation|mcc|mnc|fontScale"
        android:hardwareAccelerated="true"
        android:label="5+Debug"
        android:launchMode="singleTask"
        android:screenOrientation="user"
        android:theme="@style/DCloudTheme"
        android:windowSoftInputMode="adjustResize">
    </activity>
    <activity
        android:name=".SDK_Runtime"
        android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation|mcc|mnc|fontScale"
        android:screenOrientation="sensor">
    </activity>
    <activity
        android:name=".SDK_WebApp"
        android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation|mcc|mnc|fontScale"
        android:screenOrientation="user"
        android:theme="@android:style/Theme.Translucent">
    </activity>
    <service
        android:name="io.dcloud.common.adapter.io.MiniServerService"
        android:exported="true" />
</application>

运行程序后界面是这样子

image3

接下来就是在html中取值了

  • 首先找到调用native.js的那部分html页面

  • 根据 DCloud 提供的如何使用 native.js 语法来写

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8"/>
        <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
        <title>Hello H5+</title>
        <link rel="stylesheet" href="../css/common.css">
        <script type="text/javascript" src="../js/common.js"></script>
        <script type="text/javascript">
            function njsAlertForAndroid(){
                <!--全局环境-->
                var mainActivity = plus.android.runtimeMainActivity();
                <!--导包-->
                var Toast = plus.android.importClass("android.widget.Toast");
                var Context = plus.android.importClass("android.content.Context");
                var SharedPreferences = plus.android.importClass("android.content.SharedPreferences");
                var sp = mainActivity.getSharedPreferences("data",Context.MODE_PRIVATE);
                <!--var a = sp.getString("a","");-->//这种写法不行
                <!--var b = sp.getString("b","");-->
                var value1 = plus.android.invoke(sp,"getString","data1","");
                var value2 = plus.android.invoke(sp,"getString","data2","");
                var toast = Toast.makeText(mainActivity,"data1:"+value1+"\n"+"data2:"+value2,Toast.LENGTH_SHORT);
                toast.show();
            }
        </script>
    </head>
    <body>
    <header id="header">
        <div class="nvbt iback" onclick="back(true);"></div>
        <div class="nvtt">Native.JS</div>
        <div class="nvbt idoc" onclick="openDoc('Native.JS Document','/doc/native.js.html')"></div>
    </header>
    <div id="dcontent" class="dcontent">
        <br/>
        <ul class="dlist">
            <li class="ditem" onclick="njsAlertForAndroid()">native.js调用Android原生代码数据</li>
            <li class="ditem" onclick="clicked('njs_efficient.html')">native.js高级API</li>
        </ul>
        <br/>
        <div class="button button-waring"
             onclick="plus.runtime.openURL('http://ask.dcloud.net.cn/article/114');">更多示例...
        </div>
    </div>
    <div id="output">
        Native.JS一种把操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。可通过plus.android.*和plus.ios.*提供的API分别调用Android和iOS平台的Native
        API。
    </div>
    </body>
    <script type="text/javascript" src="../js/immersed.js"></script>
    </html>
    

    注意,限于篇幅,我把njs.html的一些无关代码代码简化了

  • 运行程序,可以看到,值已经成功取出来了

更多关于使用 native.js的例子可以查看这里: Native.js示例汇总


hogen

2017-04-30
Home About Github Email