HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

Android平台以Widget方式集成HTML5+SDK方法

SDK

5+ SDKWidget方式集成WebView方式集成 将不再继续维护支持,相关功能已迁移到uni小程序 SDK,因此建议开发者尽快将应用升级到uni-app项目。

最新SDK下载地址
HTML5+ SDK 可以按照“独立应用”和“单页面”两种种方式进行集成,两种集成方式各有优点。

  • 独立应用集成方式:即Widget集成方式,开发者在集成后可在需要时启动HTML5+ SDK,显示指定目录下的5+ WebAPP。原生App中集成uni-app也需使用本集成方式。

  • 单页面集成方式:即Webview集成方式,用户可在需要时显示一个支持5+扩展API的Webview页面。使用单页面方式集成5+ SDK,在页面内不能调用plus.webview的API创建新的页面,其他5+API的使用不受影响。

集成代码请参考SDK内HBuilder-Integrate工程 点击下载最新SDK

集成步骤

一 将5+SDK导入现有原生工程

点击下载最新 5+ SDK
开发者需要根据WebApp中将要用到的5+API,将涉及的5+SDK的jar包和资源文件导入到现有的Android原生工程中,并根据需求修改工程的Androidmanifest.xml文件。
注意:集成SDK时需要将DCloudApplication配置到AndroidManifest.xml 的application节点中。也可继承DCloudApplication实现自己的application并配置。不配置DCloudApplication会导致SDK中业务逻辑无法正常运行!!!!

<application  
        android:name="io.dcloud.application.DCloudApplication" >

各API需要导入的资源和AndroidManifest.xml文件需要修改地方请点击查看以下文档
基础插件配置
推送插件配置
分享插件配置
授权登陆插件配置
地图插件配置
支付插件配置
定位插件配置

二 将WebApp导入现有原生工程

5+Webapp的导入现有工程的方法可以参考Android平台离线打包配置文档

三 5+SDK集成代码编写

1 创建一个继承自ICoreStatusListener的类,并实现其中的方法

ICoreStatusListener类用来监听5+内核的运行事件,当5+内核运行状态发生变化时会触发相应的方法,包含以下几个方法:

void onCoreReady(ICore arg0)
说明:
5+内核开始初始化时触发
SDK的方法必须在调用SDK.init()之后才可以调用,在使用中通常在onCoreReady方法触发时初始化5+SDK。
代码示例:

@Override  
    public void onCoreReady(ICore coreHandler) {  
        // 调用SDK的初始化接口,初始化5+ SDK  
        SDK.initSDK(coreHandler);  
        // 设置当前应用可使用的5+ API  
        SDK.requestAllFeature();  
    }

void onCoreInitEnd(ICore arg0)
说明:
5+内核初始化完成时触发
开发者要在5+内核初始化完成后才能调用SDK.startWebApp()等接口启动指定目录下的5+Webapp

boolean onCoreStop()
说明:
5+内核关闭时触发

Object onCreateSplash(Context pContextWrapper)
说明:
Splash页面创建时触发

void onCloseSplash()
说明:
Splash页面关闭时触发

2 调用SDK.startWebApp方法创建并启动5+WebApp

在5+内核初始化完毕后可调用SDK.startWebApp() 方法启动5+WebApp,方法会创建并返回一个IApp对象。开发者可通过调用IApp对象的方法获取该应用内已经打开的页面的IWebView对象也可以关闭这个5+WebApp。

应用创建后需要将应用的主页面添加到要显示该应用的父View中。

在调用startWebApp方法时可以传入一个IWebviewStateListener用来监听WebApp首页面加载的进度。

IApp对象创建成功后我们可以添加一个IAppStatusListener用来监听当前创建的IAPP对象的运行状态。

代码示例

    class WebappModeListener implements ICoreStatusListener, IOnCreateSplashView {  
    Activity activity;  
    View splashView = null;  
    ViewGroup rootView;  
    IApp app = null;  
    ProgressDialog pd = null;  

    public WebappModeListener(Activity activity, ViewGroup rootView) {  
        this.activity = activity;  
        this.rootView = rootView;  
    }  

    @Override  
    public void onCoreInitEnd(ICore coreHandler) {  

        // 表示Webapp的路径在 file:///android_asset/apps/HelloH5  
        String appBasePath = "/apps/HelloH5";  

        // 设置启动参数,可在页面中通过plus.runtime.arguments;方法获取到传入的参数  
        String args = "{url:'http://www.baidu.com'}";  

        // 启动启动独立应用的5+ Webapp  
        app = SDK.startWebApp(activity, appBasePath, args, new IWebviewStateListener() {  
            // 设置Webview事件监听,可在监监听内获取WebIvew加载内容的进度  
            @Override  
            public Object onCallBack(int pType, Object pArgs) {  
                switch (pType) {  
                case IWebviewStateListener.ON_WEBVIEW_READY:  
                    // WebApp准备加载事件  
                    // 准备完毕之后添加webview到显示父View中,  
                    // 设置排版不显示状态,避免显示webview时html内容排版错乱问题  
                    View view = ((IWebview) pArgs).obtainApp().obtainWebAppRootView().obtainMainView();  
                    view.setVisibility(View.INVISIBLE);  
                    rootView.addView(view, 0);  
                    break;  
                case IWebviewStateListener.ON_PAGE_STARTED:  
                    pd = ProgressDialog.show(activity, "加载中", "0/100");  
                    break;  
                case IWebviewStateListener.ON_PROGRESS_CHANGED:  
                    // WebApp首页面加载进度变化事件  
                    if (pd != null) {  
                        pd.setMessage(pArgs + "/100");  
                    }  
                    break;  
                case IWebviewStateListener.ON_PAGE_FINISHED:  
                    // WebApp首页面加载完成事件  
                    if (pd != null) {  
                        pd.dismiss();  
                        pd = null;  
                    }  
                    // 页面加载完毕,设置显示webview  
                    app.obtainWebAppRootView().obtainMainView().setVisibility(View.VISIBLE);  
                    break;  
                }  
                return null;  
            }  
        }, this);  

        app.setIAppStatusListener(new IAppStatusListener() {  
            // 设置APP运行事件监听  
            @Override  
            public boolean onStop() {  
                // 应用运行停止时调用  
                rootView.removeView(app.obtainWebAppRootView().obtainMainView());  
                // TODO Auto-generated method stub  
                return false;  
            }  

            @Override  
            public void onStart() {  
                // 独立应用启动时触发事件  
            }  

            @Override  
            public void onPause(IApp arg0, IApp arg1) {  
                // WebApp暂停运行时触发事件  

            }  
        });  
    }  

    @Override  
    public void onCoreReady(ICore coreHandler) {  
        // 初始化SDK并将5+引擎的对象设置给SDK  
        SDK.initSDK(coreHandler);  
        //   
        SDK.requestAllFeature();  
    }  

    @Override  
    public boolean onCoreStop() {  
        // 当返回false时候回关闭activity  
        return false;  
    }  

    @Override  
    public Object onCreateSplash(Context pContextWrapper) {  
        splashView = new FrameLayout(activity);  
        splashView.setBackgroundResource(RInformation.DRAWABLE_SPLASH);  
        rootView.addView(splashView);  
        return null;  
    }  

    @Override  
    public void onCloseSplash() {  
        rootView.removeView(splashView);  
    }  
}

3 启动5+ 内核

5+SDK在使用前首先要进行5+内核的初始化,在启动时需要添加一个ICoreStatusListener用来监听5+内核启动状态。io.dcloud.feature.internal.sdk.SDK类的方法需要在5+内核初始化后才能够调用。

同时还需要在5+内核初始化后指定当前将要使用那种集成方式。独立应用集成方式使用SDK.IntegratedMode.WEBAPP 参数指定当前SDK将使用独立应用方式启动5+WebApp。

示例中5+ SDK是在Activity的onCreate方法中初始化,在具体使用中可在任意时刻初始化5+内核。

public class SDK_WebApp extends Activity {  

    boolean doHardAcc = true;  
    EntryProxy mEntryProxy = null;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        if (mEntryProxy == null) {  
            FrameLayout f = new FrameLayout(this);  
            // 创建5+内核运行事件监听  
            WebappModeListener wm = new WebappModeListener(this, f);  
            // 初始化5+内核  
            mEntryProxy = EntryProxy.init(this, wm);  
            // 启动5+内核  
            mEntryProxy.onCreate(this, savedInstanceState, SDK.IntegratedMode.WEBAPP, null);  
            setContentView(f);  
        }  
    }  
}

4 传递Activity事件给5+ SDK

开发者在集成5+SDK时可根据需要将Activity的事件传递给5+SDK引擎,5+引擎会将事件传递给监听事件的Webview,由Webview进行事件处理。

@Override  
    public boolean onCreateOptionsMenu(Menu menu) {  
        return mEntryProxy.onActivityExecute(this, SysEventType.onCreateOptionMenu, menu);  
    }  

    @Override  
    public void onPause() {  
        super.onPause();  
        mEntryProxy.onPause(this);  
    }  

    @Override  
    public void onResume() {  
        super.onResume();  
        mEntryProxy.onResume(this);  
    }  

    public void onNewIntent(Intent intent) {  
        super.onNewIntent(intent);  
        if (intent.getFlags() != 0x10600000) {  
        // 非点击icon调用activity时才调用newintent事件  
            mEntryProxy.onNewIntent(this, intent);  
        }  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mEntryProxy.onStop(this);  
    }  

    @Override  
    public boolean onKeyDown(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyDown, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyDown(keyCode, event);  
    }  

    @Override  
    public boolean onKeyUp(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyUp, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyUp(keyCode, event);  
    }  

    @Override  
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyLongPress, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyLongPress(keyCode, event);  
    }  

    public void onConfigurationChanged(Configuration newConfig) {  
        try {  
            int temp = this.getResources().getConfiguration().orientation;  
            if (mEntryProxy != null) {  
                mEntryProxy.onConfigurationChanged(this, temp);  
            }  
            super.onConfigurationChanged(newConfig);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
        mEntryProxy.onActivityExecute(this, SysEventType.onActivityResult, new Object[] { requestCode, resultCode, data });  
    }  

Android 平台5+SDK常用接口说明

Android 平台5+SDK常用接口及使用示例请点击

继续阅读 »

5+ SDKWidget方式集成WebView方式集成 将不再继续维护支持,相关功能已迁移到uni小程序 SDK,因此建议开发者尽快将应用升级到uni-app项目。

最新SDK下载地址
HTML5+ SDK 可以按照“独立应用”和“单页面”两种种方式进行集成,两种集成方式各有优点。

  • 独立应用集成方式:即Widget集成方式,开发者在集成后可在需要时启动HTML5+ SDK,显示指定目录下的5+ WebAPP。原生App中集成uni-app也需使用本集成方式。

  • 单页面集成方式:即Webview集成方式,用户可在需要时显示一个支持5+扩展API的Webview页面。使用单页面方式集成5+ SDK,在页面内不能调用plus.webview的API创建新的页面,其他5+API的使用不受影响。

集成代码请参考SDK内HBuilder-Integrate工程 点击下载最新SDK

集成步骤

一 将5+SDK导入现有原生工程

点击下载最新 5+ SDK
开发者需要根据WebApp中将要用到的5+API,将涉及的5+SDK的jar包和资源文件导入到现有的Android原生工程中,并根据需求修改工程的Androidmanifest.xml文件。
注意:集成SDK时需要将DCloudApplication配置到AndroidManifest.xml 的application节点中。也可继承DCloudApplication实现自己的application并配置。不配置DCloudApplication会导致SDK中业务逻辑无法正常运行!!!!

<application  
        android:name="io.dcloud.application.DCloudApplication" >

各API需要导入的资源和AndroidManifest.xml文件需要修改地方请点击查看以下文档
基础插件配置
推送插件配置
分享插件配置
授权登陆插件配置
地图插件配置
支付插件配置
定位插件配置

二 将WebApp导入现有原生工程

5+Webapp的导入现有工程的方法可以参考Android平台离线打包配置文档

三 5+SDK集成代码编写

1 创建一个继承自ICoreStatusListener的类,并实现其中的方法

ICoreStatusListener类用来监听5+内核的运行事件,当5+内核运行状态发生变化时会触发相应的方法,包含以下几个方法:

void onCoreReady(ICore arg0)
说明:
5+内核开始初始化时触发
SDK的方法必须在调用SDK.init()之后才可以调用,在使用中通常在onCoreReady方法触发时初始化5+SDK。
代码示例:

@Override  
    public void onCoreReady(ICore coreHandler) {  
        // 调用SDK的初始化接口,初始化5+ SDK  
        SDK.initSDK(coreHandler);  
        // 设置当前应用可使用的5+ API  
        SDK.requestAllFeature();  
    }

void onCoreInitEnd(ICore arg0)
说明:
5+内核初始化完成时触发
开发者要在5+内核初始化完成后才能调用SDK.startWebApp()等接口启动指定目录下的5+Webapp

boolean onCoreStop()
说明:
5+内核关闭时触发

Object onCreateSplash(Context pContextWrapper)
说明:
Splash页面创建时触发

void onCloseSplash()
说明:
Splash页面关闭时触发

2 调用SDK.startWebApp方法创建并启动5+WebApp

在5+内核初始化完毕后可调用SDK.startWebApp() 方法启动5+WebApp,方法会创建并返回一个IApp对象。开发者可通过调用IApp对象的方法获取该应用内已经打开的页面的IWebView对象也可以关闭这个5+WebApp。

应用创建后需要将应用的主页面添加到要显示该应用的父View中。

在调用startWebApp方法时可以传入一个IWebviewStateListener用来监听WebApp首页面加载的进度。

IApp对象创建成功后我们可以添加一个IAppStatusListener用来监听当前创建的IAPP对象的运行状态。

代码示例

    class WebappModeListener implements ICoreStatusListener, IOnCreateSplashView {  
    Activity activity;  
    View splashView = null;  
    ViewGroup rootView;  
    IApp app = null;  
    ProgressDialog pd = null;  

    public WebappModeListener(Activity activity, ViewGroup rootView) {  
        this.activity = activity;  
        this.rootView = rootView;  
    }  

    @Override  
    public void onCoreInitEnd(ICore coreHandler) {  

        // 表示Webapp的路径在 file:///android_asset/apps/HelloH5  
        String appBasePath = "/apps/HelloH5";  

        // 设置启动参数,可在页面中通过plus.runtime.arguments;方法获取到传入的参数  
        String args = "{url:'http://www.baidu.com'}";  

        // 启动启动独立应用的5+ Webapp  
        app = SDK.startWebApp(activity, appBasePath, args, new IWebviewStateListener() {  
            // 设置Webview事件监听,可在监监听内获取WebIvew加载内容的进度  
            @Override  
            public Object onCallBack(int pType, Object pArgs) {  
                switch (pType) {  
                case IWebviewStateListener.ON_WEBVIEW_READY:  
                    // WebApp准备加载事件  
                    // 准备完毕之后添加webview到显示父View中,  
                    // 设置排版不显示状态,避免显示webview时html内容排版错乱问题  
                    View view = ((IWebview) pArgs).obtainApp().obtainWebAppRootView().obtainMainView();  
                    view.setVisibility(View.INVISIBLE);  
                    rootView.addView(view, 0);  
                    break;  
                case IWebviewStateListener.ON_PAGE_STARTED:  
                    pd = ProgressDialog.show(activity, "加载中", "0/100");  
                    break;  
                case IWebviewStateListener.ON_PROGRESS_CHANGED:  
                    // WebApp首页面加载进度变化事件  
                    if (pd != null) {  
                        pd.setMessage(pArgs + "/100");  
                    }  
                    break;  
                case IWebviewStateListener.ON_PAGE_FINISHED:  
                    // WebApp首页面加载完成事件  
                    if (pd != null) {  
                        pd.dismiss();  
                        pd = null;  
                    }  
                    // 页面加载完毕,设置显示webview  
                    app.obtainWebAppRootView().obtainMainView().setVisibility(View.VISIBLE);  
                    break;  
                }  
                return null;  
            }  
        }, this);  

        app.setIAppStatusListener(new IAppStatusListener() {  
            // 设置APP运行事件监听  
            @Override  
            public boolean onStop() {  
                // 应用运行停止时调用  
                rootView.removeView(app.obtainWebAppRootView().obtainMainView());  
                // TODO Auto-generated method stub  
                return false;  
            }  

            @Override  
            public void onStart() {  
                // 独立应用启动时触发事件  
            }  

            @Override  
            public void onPause(IApp arg0, IApp arg1) {  
                // WebApp暂停运行时触发事件  

            }  
        });  
    }  

    @Override  
    public void onCoreReady(ICore coreHandler) {  
        // 初始化SDK并将5+引擎的对象设置给SDK  
        SDK.initSDK(coreHandler);  
        //   
        SDK.requestAllFeature();  
    }  

    @Override  
    public boolean onCoreStop() {  
        // 当返回false时候回关闭activity  
        return false;  
    }  

    @Override  
    public Object onCreateSplash(Context pContextWrapper) {  
        splashView = new FrameLayout(activity);  
        splashView.setBackgroundResource(RInformation.DRAWABLE_SPLASH);  
        rootView.addView(splashView);  
        return null;  
    }  

    @Override  
    public void onCloseSplash() {  
        rootView.removeView(splashView);  
    }  
}

3 启动5+ 内核

5+SDK在使用前首先要进行5+内核的初始化,在启动时需要添加一个ICoreStatusListener用来监听5+内核启动状态。io.dcloud.feature.internal.sdk.SDK类的方法需要在5+内核初始化后才能够调用。

同时还需要在5+内核初始化后指定当前将要使用那种集成方式。独立应用集成方式使用SDK.IntegratedMode.WEBAPP 参数指定当前SDK将使用独立应用方式启动5+WebApp。

示例中5+ SDK是在Activity的onCreate方法中初始化,在具体使用中可在任意时刻初始化5+内核。

public class SDK_WebApp extends Activity {  

    boolean doHardAcc = true;  
    EntryProxy mEntryProxy = null;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        if (mEntryProxy == null) {  
            FrameLayout f = new FrameLayout(this);  
            // 创建5+内核运行事件监听  
            WebappModeListener wm = new WebappModeListener(this, f);  
            // 初始化5+内核  
            mEntryProxy = EntryProxy.init(this, wm);  
            // 启动5+内核  
            mEntryProxy.onCreate(this, savedInstanceState, SDK.IntegratedMode.WEBAPP, null);  
            setContentView(f);  
        }  
    }  
}

4 传递Activity事件给5+ SDK

开发者在集成5+SDK时可根据需要将Activity的事件传递给5+SDK引擎,5+引擎会将事件传递给监听事件的Webview,由Webview进行事件处理。

@Override  
    public boolean onCreateOptionsMenu(Menu menu) {  
        return mEntryProxy.onActivityExecute(this, SysEventType.onCreateOptionMenu, menu);  
    }  

    @Override  
    public void onPause() {  
        super.onPause();  
        mEntryProxy.onPause(this);  
    }  

    @Override  
    public void onResume() {  
        super.onResume();  
        mEntryProxy.onResume(this);  
    }  

    public void onNewIntent(Intent intent) {  
        super.onNewIntent(intent);  
        if (intent.getFlags() != 0x10600000) {  
        // 非点击icon调用activity时才调用newintent事件  
            mEntryProxy.onNewIntent(this, intent);  
        }  
    }  

    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        mEntryProxy.onStop(this);  
    }  

    @Override  
    public boolean onKeyDown(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyDown, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyDown(keyCode, event);  
    }  

    @Override  
    public boolean onKeyUp(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyUp, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyUp(keyCode, event);  
    }  

    @Override  
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {  
        boolean _ret = mEntryProxy.onActivityExecute(this, SysEventType.onKeyLongPress, new Object[] { keyCode, event });  
        return _ret ? _ret : super.onKeyLongPress(keyCode, event);  
    }  

    public void onConfigurationChanged(Configuration newConfig) {  
        try {  
            int temp = this.getResources().getConfiguration().orientation;  
            if (mEntryProxy != null) {  
                mEntryProxy.onConfigurationChanged(this, temp);  
            }  
            super.onConfigurationChanged(newConfig);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
        mEntryProxy.onActivityExecute(this, SysEventType.onActivityResult, new Object[] { requestCode, resultCode, data });  
    }  

Android 平台5+SDK常用接口说明

Android 平台5+SDK常用接口及使用示例请点击

收起阅读 »

Android平台以WebView方式集成HTML5+SDK方法

SDK

5+ SDKWidget方式集成WebView方式集成 将不再继续维护与支持!仅支持离线打包APP

具体参考离线打包

5+ SDKWidget方式集成WebView方式集成 将不再继续维护与支持!仅支持离线打包APP

具体参考离线打包

crosswalk可以作为插件集成进来吗,和5+runtime各有什么优劣?

crosswalk

更新于2017年2月,intel官方已经宣布终止crosswalk项目。
此问题没有继续讨论的必要了。

====================================================================

有不少开发者问到crosswalk是否可以作为插件集成到HBuilder中。
首先,通过我们的原生插件集成方案,使用HBuilder的离线打包和插件开发模型,可以把crosswalk当作一个原生插件集成进来。
但是需要一点原生开发的知识,在问答系统里搜索"插件开发"就有教程。
注意即使集成后crosswalk的webview和5+的webview并不能同时出现,一个app里的某个页面,要不用cw渲染,要不用5+渲染。
其次,我们曾有想法要把crosswalk做一个标准插件,在cw上扩展5+的api,包括Native.js,但到了2016年后,团队已经放弃了这个想法,投入产出太低。

crosswalk的技术路线:是集成chromium内核替换Android webkit浏览器内核,由于chomuin的执行效率高于webkit,所以性能也得到提升。
cw主要解决的问题有2个:

  1. Android4.0-Android4.3之间的webview性能差的问题,主要是div动画、canvas、webgl。Android4以前用不了cw,Android4.4起用不着cw。
  2. 浏览器的兼容性问题。

对于5+而言,这2个问题并非本质问题。

  1. Android4.4已经成为主流,Android6.0也在快速增长,Android4.0-4.3之间的canvas、webgl改进价值虽然存在,但越来越弱。而div动画低效的问题在5+里一直是用原生view动画来解决,性能体验更好。
    目前如果是为了优化canvas,可以采用的一个方案是:把canvas界面独立出来,把cw通过sdk方式进入,然后独立的界面用cw渲染,如果需要5+api,通过跨窗体通信让其他webview执行5+api。
  2. 浏览器兼容性问题在手机上并不严重,都是webkit内核,不要用太新的css3语法,一般不会有兼容性问题。HBuilder也有浏览器兼容性语法提示,写代码时注意看下代码助手右侧的提示。

但引入cw进5+的问题很多:

  1. cw上扩展plus和Native.js工作量非常大
  2. cw上真机运行、云打包、sdk配套的工作量非常大
  3. cw的体积最小也得9M。而目前HBuilder基座如果不带个推那些插件,才1m的体积。

利弊权衡,我们决定放弃引入cw的计划,把精力投入到更容易产生效果的地方。

继续阅读 »

更新于2017年2月,intel官方已经宣布终止crosswalk项目。
此问题没有继续讨论的必要了。

====================================================================

有不少开发者问到crosswalk是否可以作为插件集成到HBuilder中。
首先,通过我们的原生插件集成方案,使用HBuilder的离线打包和插件开发模型,可以把crosswalk当作一个原生插件集成进来。
但是需要一点原生开发的知识,在问答系统里搜索"插件开发"就有教程。
注意即使集成后crosswalk的webview和5+的webview并不能同时出现,一个app里的某个页面,要不用cw渲染,要不用5+渲染。
其次,我们曾有想法要把crosswalk做一个标准插件,在cw上扩展5+的api,包括Native.js,但到了2016年后,团队已经放弃了这个想法,投入产出太低。

crosswalk的技术路线:是集成chromium内核替换Android webkit浏览器内核,由于chomuin的执行效率高于webkit,所以性能也得到提升。
cw主要解决的问题有2个:

  1. Android4.0-Android4.3之间的webview性能差的问题,主要是div动画、canvas、webgl。Android4以前用不了cw,Android4.4起用不着cw。
  2. 浏览器的兼容性问题。

对于5+而言,这2个问题并非本质问题。

  1. Android4.4已经成为主流,Android6.0也在快速增长,Android4.0-4.3之间的canvas、webgl改进价值虽然存在,但越来越弱。而div动画低效的问题在5+里一直是用原生view动画来解决,性能体验更好。
    目前如果是为了优化canvas,可以采用的一个方案是:把canvas界面独立出来,把cw通过sdk方式进入,然后独立的界面用cw渲染,如果需要5+api,通过跨窗体通信让其他webview执行5+api。
  2. 浏览器兼容性问题在手机上并不严重,都是webkit内核,不要用太新的css3语法,一般不会有兼容性问题。HBuilder也有浏览器兼容性语法提示,写代码时注意看下代码助手右侧的提示。

但引入cw进5+的问题很多:

  1. cw上扩展plus和Native.js工作量非常大
  2. cw上真机运行、云打包、sdk配套的工作量非常大
  3. cw的体积最小也得9M。而目前HBuilder基座如果不带个推那些插件,才1m的体积。

利弊权衡,我们决定放弃引入cw的计划,把精力投入到更容易产生效果的地方。

收起阅读 »

HBuilder支持php吗?php插件怎么用?

PHP

工具-插件安装,选php插件,可以编辑php文档。
支持php高亮着色、代码提示、转到定义。

  1. 插件安装失败?
    插件安装过程中万一出问题导致插件安装失败,请点击工具-插件安装,点里面的卸载插件链接,然后在新窗体选择aptana php插件。卸载并重启,然后再重新安装。

  2. 插件安装成功但仍然php不高亮?
    如果确定安装了php插件,但php文档打开还是不高亮,说明仍然是使用了HTML编辑器打开了php文档,那么在工具-选项,搜索文件关联,在里面配置php文件和PHP Editor的关联。
    也可以在项目管理器里对文件点右键,打开方式,里面选PHP Editor。

  3. php无法运行?使用ctrl+r运行在浏览器或使用ctrl+p运行在边改边看下不能识别?
    HBuilder内置的web服务器只能看简单的HTML、js、css,不具备php解析能力,需要配置外部专业web服务器才能解析php。
    需要在工具-选项里搜索web服务器,新建一个外部web服务器,配置tomcat等外部web服务器的参数。

继续阅读 »

工具-插件安装,选php插件,可以编辑php文档。
支持php高亮着色、代码提示、转到定义。

  1. 插件安装失败?
    插件安装过程中万一出问题导致插件安装失败,请点击工具-插件安装,点里面的卸载插件链接,然后在新窗体选择aptana php插件。卸载并重启,然后再重新安装。

  2. 插件安装成功但仍然php不高亮?
    如果确定安装了php插件,但php文档打开还是不高亮,说明仍然是使用了HTML编辑器打开了php文档,那么在工具-选项,搜索文件关联,在里面配置php文件和PHP Editor的关联。
    也可以在项目管理器里对文件点右键,打开方式,里面选PHP Editor。

  3. php无法运行?使用ctrl+r运行在浏览器或使用ctrl+p运行在边改边看下不能识别?
    HBuilder内置的web服务器只能看简单的HTML、js、css,不具备php解析能力,需要配置外部专业web服务器才能解析php。
    需要在工具-选项里搜索web服务器,新建一个外部web服务器,配置tomcat等外部web服务器的参数。

收起阅读 »

如何设置缩进符、tab制表符为2个空格

HBuilder

hb在工具-选项-常规-编辑器-文本编辑器右侧有制表符长度设置。
hx在工具-设置里修改。
默认是tab,长度为4。
hx里这个设置会自动同步给格式化插件,也就是设置调整后,格式化插件的配置也会遵循这个策略。
但注意预置的代码块的缩进是tab而不是空格。

hb在工具-选项-常规-编辑器-文本编辑器右侧有制表符长度设置。
hx在工具-设置里修改。
默认是tab,长度为4。
hx里这个设置会自动同步给格式化插件,也就是设置调整后,格式化插件的配置也会遵循这个策略。
但注意预置的代码块的缩进是tab而不是空格。

如何调整编码?如何解决GB1312中文乱码?

乱码 编码 HBuilder

整体工程配置编码:
资源管理中对着文件或者整个项目点右键,点属性(快捷键是Alt+Enter)。
在文件编码处选其他,选择或输入你需要的编码,比如GBK。

单独文件配置编码:
也可以在文件->其他编码方式打开,选择需要的编码即可。

注意,不在HBuilder中建项目而单独打开的文件,无法调整编码。

注意,HBuilder不支持调整文件的本身的编码格式,仅支持以某种编码方式打开该文件。
需要转码可使用其他文本编辑器或搜索eclipse、nodejs插件来解决。

继续阅读 »

整体工程配置编码:
资源管理中对着文件或者整个项目点右键,点属性(快捷键是Alt+Enter)。
在文件编码处选其他,选择或输入你需要的编码,比如GBK。

单独文件配置编码:
也可以在文件->其他编码方式打开,选择需要的编码即可。

注意,不在HBuilder中建项目而单独打开的文件,无法调整编码。

注意,HBuilder不支持调整文件的本身的编码格式,仅支持以某种编码方式打开该文件。
需要转码可使用其他文本编辑器或搜索eclipse、nodejs插件来解决。

收起阅读 »

查找搜索Ctrl+F的逻辑及建议使用一键搜索

搜索 查找 HBuilder

Ctrl+F并非总是弹出查找框,在不同场景下,为了更方便的使用,它的逻辑会有不同。

  • 光标在代码区时,按Ctrl+F为显示/隐藏搜索条,若搜索条未显示,则显示,若搜索条已存在,则隐藏
  • 光标在代码区时,选中代码按Ctrl+F,把选中的文字自动放入搜索框,并将光标置焦到搜索条
  • 焦点在搜索条时,按Ctrl+F,查找定位到下一个匹配字符
  • 焦点在搜索条时,按Esc,隐藏搜索条

另外Ctrl+H是高级搜索,功能更多,查询结果是单独列一个视图。

但是最好用的,其实还是一键搜索。
双击ctrl,光标自动进入右上角的一键搜索框里,敲不同的参数会有不同的搜索范围,鼠标放在输入框那里会有tips显示。
比如直接敲文本,就是在当前文档里搜文本。
敲/+文件名,就是搜索文件名;
敲@+变量名,就是搜索变量、函数、样式、id;
敲:+数字,就是转到某行;
敲!+功能名称,就是操作某功能,比如搜!+插件;
敲?+内容,就是搜索ask系统;

官方的策略是强化一键搜索,ctrl+f为了向下兼容暂时也不去掉,但不排除某天去掉此功能,建议大家多用一键搜索。

此文针对老HBuilder,不适用于HBuilderX。

继续阅读 »

Ctrl+F并非总是弹出查找框,在不同场景下,为了更方便的使用,它的逻辑会有不同。

  • 光标在代码区时,按Ctrl+F为显示/隐藏搜索条,若搜索条未显示,则显示,若搜索条已存在,则隐藏
  • 光标在代码区时,选中代码按Ctrl+F,把选中的文字自动放入搜索框,并将光标置焦到搜索条
  • 焦点在搜索条时,按Ctrl+F,查找定位到下一个匹配字符
  • 焦点在搜索条时,按Esc,隐藏搜索条

另外Ctrl+H是高级搜索,功能更多,查询结果是单独列一个视图。

但是最好用的,其实还是一键搜索。
双击ctrl,光标自动进入右上角的一键搜索框里,敲不同的参数会有不同的搜索范围,鼠标放在输入框那里会有tips显示。
比如直接敲文本,就是在当前文档里搜文本。
敲/+文件名,就是搜索文件名;
敲@+变量名,就是搜索变量、函数、样式、id;
敲:+数字,就是转到某行;
敲!+功能名称,就是操作某功能,比如搜!+插件;
敲?+内容,就是搜索ask系统;

官方的策略是强化一键搜索,ctrl+f为了向下兼容暂时也不去掉,但不排除某天去掉此功能,建议大家多用一键搜索。

此文针对老HBuilder,不适用于HBuilderX。

收起阅读 »

三方统计插件配置

5+App开发 统计 统计插件

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-statistic

注:uni-app自带uni统计,无需使用三方统计。三方统计增加包体积且无法做到自带的免埋点采集行为数据。详见https://tongji.dcloud.io/

如确定使用友盟统计,则继续阅读下文。

App云端打包友盟统计功能,需要到友盟开发平台申请应用后获取相关配置参数:
友盟统计

配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

HBuilderX中配置统计

从友盟统计平台申请获取配置参数后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

配置使用统计模块

打开应用的manifest.json文件,在“模块权限配置”项中勾选“Statistic(统计)”:

配置统计参数

在应用manifest.json文件的“SDK配置”页面,勾选“友盟统计”项,并输入从友盟统计平台申请的参数。

可视化界面配置

切换到“(App)SDK配置”页面:


appkey_ios:友盟统计平台申请应用获取的iOS平台appkey;
channelid_ios:iOS平台的渠道字符串,可输入任意字符串;
appkey_android:友盟统计平台申请应用获取的Android平台appkey;
channelid_android:Android平台的渠道字符串,可输入任意字符串。

源码视图配置

切换到“源码视图”

配置使用统计模块

  • uni-app项目
    在"app-plus" -> "modules" 节点下添加 Statistic 节点
  • 5+ APP(WAP2APP)项目
    在 "plus" -> "permissions" 节点下添加 Statistic 节点
"Statistic" : {  
    "des": "统计模块"  
}

配置友盟统计参数

  • uni-app项目
    在 "app-plus" -> "distribute" -> "sdkConfigs" 节点下添加 statics节点
  • 5+ APP(WAP2APP)项目
    在 "plus" -> "distribute" -> "plugins" 节点下添加 statics 节点

statics节点数据格式如下

        "statics": {  
          "umeng": {  
            "appkey_ios": "友盟统计平台申请应用获取的iOS平台appkey",  
            "channelid_ios": "iOS平台的渠道字符串,可输入任意字符串",  
            "appkey_android": "友盟统计平台申请应用获取的Android平台appkey",  
            "channelid_android": "Android平台的渠道字符串,可输入任意字符串"  
          }  
        },  
        //...

Ctrl+S保存,并提交云端打包生效。

注意:

IDFA说明

从HBuilderX2.2.5版本之后(含2.2.5),基座里集成了友盟v6.0.5统计SDK,因友盟官方,从组件化产品开始,【友盟+】SDK默认采集idfa标识,用来更准确的分析核对数据。对于应用本身没有获取idfa的情况,建议将应用提交至AppStore时按如下方式配置:(以避免被苹果以“应用不含广告功能,但获取了广告标示符IDFA”的而拒绝其上架。)

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-statistic

注:uni-app自带uni统计,无需使用三方统计。三方统计增加包体积且无法做到自带的免埋点采集行为数据。详见https://tongji.dcloud.io/

如确定使用友盟统计,则继续阅读下文。

App云端打包友盟统计功能,需要到友盟开发平台申请应用后获取相关配置参数:
友盟统计

配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

HBuilderX中配置统计

从友盟统计平台申请获取配置参数后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

配置使用统计模块

打开应用的manifest.json文件,在“模块权限配置”项中勾选“Statistic(统计)”:

配置统计参数

在应用manifest.json文件的“SDK配置”页面,勾选“友盟统计”项,并输入从友盟统计平台申请的参数。

可视化界面配置

切换到“(App)SDK配置”页面:


appkey_ios:友盟统计平台申请应用获取的iOS平台appkey;
channelid_ios:iOS平台的渠道字符串,可输入任意字符串;
appkey_android:友盟统计平台申请应用获取的Android平台appkey;
channelid_android:Android平台的渠道字符串,可输入任意字符串。

源码视图配置

切换到“源码视图”

配置使用统计模块

  • uni-app项目
    在"app-plus" -> "modules" 节点下添加 Statistic 节点
  • 5+ APP(WAP2APP)项目
    在 "plus" -> "permissions" 节点下添加 Statistic 节点
"Statistic" : {  
    "des": "统计模块"  
}

配置友盟统计参数

  • uni-app项目
    在 "app-plus" -> "distribute" -> "sdkConfigs" 节点下添加 statics节点
  • 5+ APP(WAP2APP)项目
    在 "plus" -> "distribute" -> "plugins" 节点下添加 statics 节点

statics节点数据格式如下

        "statics": {  
          "umeng": {  
            "appkey_ios": "友盟统计平台申请应用获取的iOS平台appkey",  
            "channelid_ios": "iOS平台的渠道字符串,可输入任意字符串",  
            "appkey_android": "友盟统计平台申请应用获取的Android平台appkey",  
            "channelid_android": "Android平台的渠道字符串,可输入任意字符串"  
          }  
        },  
        //...

Ctrl+S保存,并提交云端打包生效。

注意:

IDFA说明

从HBuilderX2.2.5版本之后(含2.2.5),基座里集成了友盟v6.0.5统计SDK,因友盟官方,从组件化产品开始,【友盟+】SDK默认采集idfa标识,用来更准确的分析核对数据。对于应用本身没有获取idfa的情况,建议将应用提交至AppStore时按如下方式配置:(以避免被苹果以“应用不含广告功能,但获取了广告标示符IDFA”的而拒绝其上架。)

收起阅读 »

自定义Webview的404等错误页面,Webview窗口加载页面错误时显示

wap2app 错误页面 5+App开发 error.html

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-webview-error

当Webview窗口加载错误地址(如本地页面不存在)或者访问网络资源失败(如无法访问网络)时会自动显示默认错误页面:


可以通过以下方法自定义Webview的404等错误页面。

设置应用全局默认错误页面

  • 5+App和wap2app
    在应用的manifest.json文件的"plus"->"error"节点的url属性可配置自定义错误页面替换默认的错误页面。
    打开manifest.json文件,切换到代码视图,添加以下数据:

    "plus": {  
        "error": {  
            "url": "error.html"  
        },  
        //...  
    },  
    //...

    其中url地址推荐使用本地地址,相对于应用根目录。
    设置为“none”则关闭跳转到错误页面功能,此时页面显示Webview默认的错误页面内容。

  • uni-app项目

    "app-plus": {  
        "error": {  
            "url": "hybrid/html/error.html"  
        },  
        //...  
    },  
    //...

    error.html需要放到根目录下的hybrid/html目录下,否则不会被编译进去

单独设置Webview窗口的错误页面

如果需要单独自定义某个Webview窗口的错误页面,则需要在创建时通过WebviewStyle对象的errorPage属性控制:

var styles = {errorPage:"error.html"}; // 设置为“none”则关闭此Webview窗口的跳转到错误页面功能  
var webview = plus.webview.create( "url", "id", styles );     
webview.show();

错误页面中监听事件

在定义的error.html页面中可以通过监听"error"事件获取更多错误信息:

// 获取错误信息  
document.addEventListener("error",function(e){  
    var url = e.url;  // 错误页面的url地址  
    var href = e.href; // 错误页面的完整路径(包括完整的协议头)  
},false);

注意
Android平台使用iframe时如果无法加载页面在不同版本系统上存在差异:
5.0及以上版本:Webview窗口对象不会加载错误页面,仅iframe节点显示无法加载页面;
5.0以下版本:Webview窗口对象会加载错误页面。

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-webview-error

当Webview窗口加载错误地址(如本地页面不存在)或者访问网络资源失败(如无法访问网络)时会自动显示默认错误页面:


可以通过以下方法自定义Webview的404等错误页面。

设置应用全局默认错误页面

  • 5+App和wap2app
    在应用的manifest.json文件的"plus"->"error"节点的url属性可配置自定义错误页面替换默认的错误页面。
    打开manifest.json文件,切换到代码视图,添加以下数据:

    "plus": {  
        "error": {  
            "url": "error.html"  
        },  
        //...  
    },  
    //...

    其中url地址推荐使用本地地址,相对于应用根目录。
    设置为“none”则关闭跳转到错误页面功能,此时页面显示Webview默认的错误页面内容。

  • uni-app项目

    "app-plus": {  
        "error": {  
            "url": "hybrid/html/error.html"  
        },  
        //...  
    },  
    //...

    error.html需要放到根目录下的hybrid/html目录下,否则不会被编译进去

单独设置Webview窗口的错误页面

如果需要单独自定义某个Webview窗口的错误页面,则需要在创建时通过WebviewStyle对象的errorPage属性控制:

var styles = {errorPage:"error.html"}; // 设置为“none”则关闭此Webview窗口的跳转到错误页面功能  
var webview = plus.webview.create( "url", "id", styles );     
webview.show();

错误页面中监听事件

在定义的error.html页面中可以通过监听"error"事件获取更多错误信息:

// 获取错误信息  
document.addEventListener("error",function(e){  
    var url = e.url;  // 错误页面的url地址  
    var href = e.href; // 错误页面的完整路径(包括完整的协议头)  
},false);

注意
Android平台使用iframe时如果无法加载页面在不同版本系统上存在差异:
5.0及以上版本:Webview窗口对象不会加载错误页面,仅iframe节点显示无法加载页面;
5.0以下版本:Webview窗口对象会加载错误页面。

收起阅读 »

代码格式化如何自定义和扩展?jsbeautify插件能不能改?

格式化

HBuilder的js代码格式化使用的是jsbeautify插件,地址如下:https://github.com/beautify-web/js-beautify
配置css格式化后在一行,参考http://ask.dcloud.net.cn/article/628

如果想预览整体的css列表,HBuilder有大纲视图,在菜单-跳转里有转到大纲。
非要在一行,就参考上面的链接,在配置文件里修改配置。

HBuilderX的格式化配置另见文档:https://ask.dcloud.net.cn/article/36529

继续阅读 »

HBuilder的js代码格式化使用的是jsbeautify插件,地址如下:https://github.com/beautify-web/js-beautify
配置css格式化后在一行,参考http://ask.dcloud.net.cn/article/628

如果想预览整体的css列表,HBuilder有大纲视图,在菜单-跳转里有转到大纲。
非要在一行,就参考上面的链接,在配置文件里修改配置。

HBuilderX的格式化配置另见文档:https://ask.dcloud.net.cn/article/36529

收起阅读 »

支付插件配置

5+App开发

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-payment

plus的支付API,支持支付宝App支付(移动快捷支付)、微信支付和苹果的IAP应用内支付。
配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

开发指导

传统支付流程如下:
支付流程图

如果使用uniCloud,则搭配uniPay会大幅简化开发,详见:https://ext.dcloud.net.cn/plugin?id=1835
如不使用uniCloud,可以继续往下看。

申请开通支付

在使用支付前,需要向各支付平台申请开通支付功能,如已申请可跳过此章节。

Apple应用内支付(IAP)

苹果应用内置流程与其它三方支付平台存在差异,请单独参考iOS 平台使用Apple应用内支付文档:
http://ask.dcloud.net.cn/article/497

注意事项:
iOS平台苹果审核规范要求,应用中虚拟物品交易必需使用Apple应用内支付,实物交易才能使用第三方支付(支付宝和微信支付)

支付宝支付

登录支付宝账号,创建应用接入支付宝App支付能力,包括以下步骤:

  1. 创建应用(获取appid)
  2. 开通App支付功能
  3. 配置密钥(获取公钥、私钥)

详情可参考支付宝官方文档App支付快速接入

服务端生成支付订单

在App端调用支付功能时,需要先在服务器生成支付订单,下面是简单的参考示例。
参考示例代码支付宝App支付生成支付订单(PHP)
老版本“移动快捷支付”参考示例代码支付宝移动快捷支付(PHP)
C#生成支付宝订单示例

微信支付

  1. 使用微信支付功能需到微信开放平台申请移动应用并开通支付功能
    微信APP支付接入商户服务中心
    申请应用后可以获取AppID和AppSecret值。

  2. 开通支付功能后可获取支付业务服务器配置数据
    PARTNER:财付通商户号
    PARTNER_KEY:财付通密钥
    PAYSIGNKEY:支付签名密钥

服务端生成支付订单

在App端调用支付功能时,需要先在服务器生成支付订单,下面是简单的参考示例。
参考示例代码微信支付V3(PHP)

HBuilderX中配置使用支付功能

从微信开放平台申请获取配置参数(Apple应用内支付和支付宝无需配置)后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

打开项目的manifest.json文件,在“App模块配置”项中勾选“Payment(支付)”:

勾选后会显示支持的支付模块,可根据应用需要进行选择配置

Apple应用内支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“Apple应用内支付”项

仅iOS平台支持。

支付宝支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“支付宝支付”项

可根据需要选择支持Android及iOS平台

微信支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“微信支付”项

可根据需要选择支持Android及iOS平台

应用中调用支付功能

plus API使用步骤:

  1. 调用plus.payment.getChannels()获取系统支持的支付通道;
  2. 调用plus.payment.request()发起支付请求。

示例代码

var channel=null;  
// 1. 获取支付通道  
function plusReady(){ //uni-app中将此function里的代码放入vue页面的onLoad生命周期中  
    // 获取支付通道  
    plus.payment.getChannels(function(channels){  
        channel=channels[0];  
    },function(e){  
        alert("获取支付通道失败:"+e.message);  
    });  
}  
document.addEventListener('plusready',plusReady,false);//uni-app不需要此代码  

var ALIPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/alipay.php?total=';  
var WXPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/wxpay.php?total=';  
// 2. 发起支付请求  
function pay(id){  
    // 从服务器请求支付订单  
    var PAYSERVER='';  
    if(id=='alipay'){  
        PAYSERVER=ALIPAYSERVER;  
    }else if(id=='wxpay'){  
        PAYSERVER=WXPAYSERVER;  
    }else{  
        plus.nativeUI.alert("不支持此支付通道!",null,"捐赠");  
        return;  
    }  
    var xhr=new plus.net.XMLHttpRequest(); //uni-app中请使用uni的request api联网  
    xhr.onreadystatechange=function(){  
        switch(xhr.readyState){  
            case 4:  
            if(xhr.status==200){  
                plus.payment.request(channel,xhr.responseText,function(result){  
                    plus.nativeUI.alert("支付成功!",function(){  
                        back();  
                    });  
                },function(error){  
                    plus.nativeUI.alert("支付失败:" + error.code);  
                });  
            }else{  
                alert("获取订单信息失败!");  
            }  
            break;  
            default:  
            break;  
        }  
    }  
    xhr.open('GET',PAYSERVER);  
    xhr.send();  
}

注:第二步中获取到的支付订单数据需要业务服务器生成,参考前面章节中的服务端生成支付订单

继续阅读 »

此文档将不再维护,请参考新文档:https://uniapp.dcloud.io/tutorial/app-payment

plus的支付API,支持支付宝App支付(移动快捷支付)、微信支付和苹果的IAP应用内支付。
配置参数需要提交云端打包后才能生效,如果需要真机运行生效请使用自定义基座

开发指导

传统支付流程如下:
支付流程图

如果使用uniCloud,则搭配uniPay会大幅简化开发,详见:https://ext.dcloud.net.cn/plugin?id=1835
如不使用uniCloud,可以继续往下看。

申请开通支付

在使用支付前,需要向各支付平台申请开通支付功能,如已申请可跳过此章节。

Apple应用内支付(IAP)

苹果应用内置流程与其它三方支付平台存在差异,请单独参考iOS 平台使用Apple应用内支付文档:
http://ask.dcloud.net.cn/article/497

注意事项:
iOS平台苹果审核规范要求,应用中虚拟物品交易必需使用Apple应用内支付,实物交易才能使用第三方支付(支付宝和微信支付)

支付宝支付

登录支付宝账号,创建应用接入支付宝App支付能力,包括以下步骤:

  1. 创建应用(获取appid)
  2. 开通App支付功能
  3. 配置密钥(获取公钥、私钥)

详情可参考支付宝官方文档App支付快速接入

服务端生成支付订单

在App端调用支付功能时,需要先在服务器生成支付订单,下面是简单的参考示例。
参考示例代码支付宝App支付生成支付订单(PHP)
老版本“移动快捷支付”参考示例代码支付宝移动快捷支付(PHP)
C#生成支付宝订单示例

微信支付

  1. 使用微信支付功能需到微信开放平台申请移动应用并开通支付功能
    微信APP支付接入商户服务中心
    申请应用后可以获取AppID和AppSecret值。

  2. 开通支付功能后可获取支付业务服务器配置数据
    PARTNER:财付通商户号
    PARTNER_KEY:财付通密钥
    PAYSIGNKEY:支付签名密钥

服务端生成支付订单

在App端调用支付功能时,需要先在服务器生成支付订单,下面是简单的参考示例。
参考示例代码微信支付V3(PHP)

HBuilderX中配置使用支付功能

从微信开放平台申请获取配置参数(Apple应用内支付和支付宝无需配置)后,需在HBuilderX中配置并提交云端打包才能生效。
老版本HBuilder配置界面有差异,逻辑是一样的,建议更新使用HBuilderX

打开项目的manifest.json文件,在“App模块配置”项中勾选“Payment(支付)”:

勾选后会显示支持的支付模块,可根据应用需要进行选择配置

Apple应用内支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“Apple应用内支付”项

仅iOS平台支持。

支付宝支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“支付宝支付”项

可根据需要选择支持Android及iOS平台

微信支付

在manifest.json文件“App模块配置”项的“Payment(支付)”下,勾选“微信支付”项

可根据需要选择支持Android及iOS平台

应用中调用支付功能

plus API使用步骤:

  1. 调用plus.payment.getChannels()获取系统支持的支付通道;
  2. 调用plus.payment.request()发起支付请求。

示例代码

var channel=null;  
// 1. 获取支付通道  
function plusReady(){ //uni-app中将此function里的代码放入vue页面的onLoad生命周期中  
    // 获取支付通道  
    plus.payment.getChannels(function(channels){  
        channel=channels[0];  
    },function(e){  
        alert("获取支付通道失败:"+e.message);  
    });  
}  
document.addEventListener('plusready',plusReady,false);//uni-app不需要此代码  

var ALIPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/alipay.php?total=';  
var WXPAYSERVER='http://demo.dcloud.net.cn/helloh5/payment/wxpay.php?total=';  
// 2. 发起支付请求  
function pay(id){  
    // 从服务器请求支付订单  
    var PAYSERVER='';  
    if(id=='alipay'){  
        PAYSERVER=ALIPAYSERVER;  
    }else if(id=='wxpay'){  
        PAYSERVER=WXPAYSERVER;  
    }else{  
        plus.nativeUI.alert("不支持此支付通道!",null,"捐赠");  
        return;  
    }  
    var xhr=new plus.net.XMLHttpRequest(); //uni-app中请使用uni的request api联网  
    xhr.onreadystatechange=function(){  
        switch(xhr.readyState){  
            case 4:  
            if(xhr.status==200){  
                plus.payment.request(channel,xhr.responseText,function(result){  
                    plus.nativeUI.alert("支付成功!",function(){  
                        back();  
                    });  
                },function(error){  
                    plus.nativeUI.alert("支付失败:" + error.code);  
                });  
            }else{  
                alert("获取订单信息失败!");  
            }  
            break;  
            default:  
            break;  
        }  
    }  
    xhr.open('GET',PAYSERVER);  
    xhr.send();  
}

注:第二步中获取到的支付订单数据需要业务服务器生成,参考前面章节中的服务端生成支付订单

收起阅读 »

选项卡页面如何实现后退返回上一个活跃的子选项卡

选项卡 mui

webview模式的选项卡页面,其实是将多个子选项卡对应的webview合并到了一个主webview中,点击选项卡时,动态显示、隐藏对应子webview页面,所有页面是一个整体,通常情况下得逻辑是,返回按键时,关闭主页面;

但若用户希望实现,点击返回时,返回到上一次活跃的子选项卡页面,则需简单定制,实现逻辑很简单:

  1. 每次点击时,记录上一次活跃的选项卡;
  2. 自定义返回函数,返回时隐藏当前选项卡,显示上一次活跃的选项卡页面;

如下为示例代码:

    //当前激活选项,默认为第一个;  
    var activeTab = subpages[0];  
    var lastActiveTabs = new Array();  
    //选项卡点击事件  
    mui('.mui-bar-tab').on('tap', 'a', function(e) {  
        var targetTab = this.getAttribute('href');  
        if (targetTab == activeTab) {  
            return;  
        }  

        //先隐藏当前的  
        plus.webview.hide(activeTab);  
        //再显示目标  
        plus.webview.show(targetTab);  
        //记录上次活跃的选项卡  
        lastActiveTabs.push(activeTab);  
        //更改当前活跃的选项卡  
        activeTab = targetTab;  
    });  
    mui.back = function(){  
        if(lastActiveTabs.length>0){  
            var last = lastActiveTabs.pop();  
            //先隐藏当前的  
            plus.webview.hide(activeTab);  
            //取消当前选项卡的高亮样式  
            document.querySelector(".mui-bar-tab .mui-active").classList.remove("mui-active");  
            //再显示历史页面  
            plus.webview.show(last);  
            //历史选项卡增加高亮样式  
            document.querySelector(".mui-bar-tab a[href='http://ask.dcloud.net.cn/"+last+"']").classList.add("mui-active");  
            //更改当前活跃的选项卡  
            activeTab = last;  
        }else{  
            //不能再退了  
        }  
    }
继续阅读 »

webview模式的选项卡页面,其实是将多个子选项卡对应的webview合并到了一个主webview中,点击选项卡时,动态显示、隐藏对应子webview页面,所有页面是一个整体,通常情况下得逻辑是,返回按键时,关闭主页面;

但若用户希望实现,点击返回时,返回到上一次活跃的子选项卡页面,则需简单定制,实现逻辑很简单:

  1. 每次点击时,记录上一次活跃的选项卡;
  2. 自定义返回函数,返回时隐藏当前选项卡,显示上一次活跃的选项卡页面;

如下为示例代码:

    //当前激活选项,默认为第一个;  
    var activeTab = subpages[0];  
    var lastActiveTabs = new Array();  
    //选项卡点击事件  
    mui('.mui-bar-tab').on('tap', 'a', function(e) {  
        var targetTab = this.getAttribute('href');  
        if (targetTab == activeTab) {  
            return;  
        }  

        //先隐藏当前的  
        plus.webview.hide(activeTab);  
        //再显示目标  
        plus.webview.show(targetTab);  
        //记录上次活跃的选项卡  
        lastActiveTabs.push(activeTab);  
        //更改当前活跃的选项卡  
        activeTab = targetTab;  
    });  
    mui.back = function(){  
        if(lastActiveTabs.length>0){  
            var last = lastActiveTabs.pop();  
            //先隐藏当前的  
            plus.webview.hide(activeTab);  
            //取消当前选项卡的高亮样式  
            document.querySelector(".mui-bar-tab .mui-active").classList.remove("mui-active");  
            //再显示历史页面  
            plus.webview.show(last);  
            //历史选项卡增加高亮样式  
            document.querySelector(".mui-bar-tab a[href='http://ask.dcloud.net.cn/"+last+"']").classList.add("mui-active");  
            //更改当前活跃的选项卡  
            activeTab = last;  
        }else{  
            //不能再退了  
        }  
    }
收起阅读 »