HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

跨域问题解决方案

跨域

解决No 'Access-Control-Allow-Origin' header is present on the requested resource.跨域问题

解决方法 通过服务端设置返回参数
1.在后台写一个过滤器过滤器来改写请求头,直接给出代码
public class CusFilter implements Filter {
//...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest)servletRequest;
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
String method = request.getMethod();
if(method.equalsIgnoreCase("OPTIONS")){
servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
}else{
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
2.在web.xml修改过滤器配置

继续阅读 »

解决No 'Access-Control-Allow-Origin' header is present on the requested resource.跨域问题

解决方法 通过服务端设置返回参数
1.在后台写一个过滤器过滤器来改写请求头,直接给出代码
public class CusFilter implements Filter {
//...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest)servletRequest;
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
String method = request.getMethod();
if(method.equalsIgnoreCase("OPTIONS")){
servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
}else{
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
2.在web.xml修改过滤器配置

收起阅读 »

Vue集成jpush之Android篇

Push mui Vue HBuilder

一、首先先参考极光官方集成指南
参考https://github.com/jpush/jpush-hbuilder-demo

HBuilder 项目集成第三方插件,需先参考 HBuilder 官方的离线打包教程,将您的 HBuilder 项目集成进 Android 工程中。另外,还需要在极光官网根据你的包名申请APPKey。以上工作完成之后再执行以下步骤:
1.拷贝demo中 ./android/app/src/main/java/io.dcloud.feature.jpush 文件夹至你 Android Studio 工程的 /src/main/java/ 目录下。注意:RInformation.java文件不需要拷贝过来。
2.拷贝 ./jpush.js 到你 Android Studio 工程的 /assets/apps/HBuilder应用名/js/ 下。
3.在 /assets/apps/你的应用名/www/manifest.json 文件中添加:

"Push": {  
  "description": "消息推送"  
}

4.在 /assets/data/dcloud_properties.xml 中添加(如果已存在 Push feature,可以直接修改):

<feature name="Push" value="io.dcloud.feature.jpush.JPushService" />

5.在 app/build.gradle 中添加:

android {  
    ...  
defaultConfig {  
        applicationId "com.***.***"// JPush上注册的包名  
        ...  
    ndk {  
            // 选择要添加的对应 cpu 类型的 .so 库。  
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'//,'arm64-v8a',  'x86_64', 'mips', 'mips64'  
            // 还可以添加 , 'x86_64', 'mips', 'mips64'  
        }  
        manifestPlaceholders = [  
                JPUSH_PKGNAME: applicationId,  
                JPUSH_APPKEY : "*****", // JPush上注册的包名对应的 appkey  
                JPUSH_CHANNEL: "developer-default", // 暂时填写默认值即可  
        ]  
    }  
    buildTypes {  
        release {  
            minifyEnabled false  
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  
        }  
    }  
...  
dependencies {  
    ...  
    compile 'cn.jiguang.sdk:jpush:3.1.8'  
    compile 'cn.jiguang.sdk:jcore:1.2.6'  
}

6.在 AndroidManifest.xml 中添加:

<receiver  
    android:name="io.dcloud.feature.jpush.JPushReceiver"  
    android:enabled="true"  
    android:exported="false">  
    <intent-filter>  
        <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!-- Required 用户注册SDK的 intent -->  
        <action android:name="cn.jpush.android.intent.UNREGISTRATION" />  
        <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required 用户接收SDK消息的 intent -->  
        <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required 用户接收SDK通知栏信息的 intent -->  
        <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏的 intent -->  
        <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!-- Optional 用户接受 Rich Push Javascript 回调函数的intent -->  
        <action android:name="cn.jpush.android.intent.CONNECTION" /> <!-- 接收网络变化 连接/断开 since 1.6.3 -->  
        <category android:name="${JPUSH_PKGNAME}" />  
    </intent-filter>  
</receiver>

二、添加相关处理代码
1.在vue中static文件加下新建jpush文件夹,然后将【一.2】中相同的jpush.js文件复制进来。
2.在Vue中,index.html中加入
<script src="static/jpush/jpush.js"></script>
然后加入相关方法,如下:

// 控制台输出日志  
function outLog(msg) {  
  console.log(msg);  
}  

// 界面弹出吐司提示  
function outLine(msg) {  
  mui.toast(msg);  
}  

var setTagsWithAlias = function () {  
  var tag1 = '...'  
  var tag2 = ''  
  var tag3 = ''  
  var alias = 'test'  
  var tags = []  

  if (tag1) {  
    tags.push(tag1)  
  }  
  if (tag2) {  
    tags.push(tag2)  
  }  
  if (tag3) {  
    tags.push(tag3)  
  }  
  window.plus.Push.setTagsWithAlias(tags, alias)  
}  

var getRegistrationID = function () {  
  window.plus.Push.getRegistrationID(function (data) {  
    if (data.length != 0) {  
      outLine('getRegistrationID>>>>' + data)  
    }  
  })  
}  

var getLaunchAppCacheNotification = function () {  
  if (mui.os.android) {  
    window.plus.Push.getLaunchAppCacheNotification(function (data) {  
      if (data.alert) {  
        outLine('cache:' + data.alert)  
      }  
    })  
  }  
}  

var receiveNotification = function (event) {  
  var content  
  if (mui.os.ios) {  
    content = window.plus.Push.receiveNotification.aps.alert  
  } else {  
    outLine('receiveNotification---else')  
    content = window.plus.Push.receiveNotification.alert  
  }  

  outLine(content)  
}  

var openNotification = function () {  
  var content  
  if (mui.os.ios) {  
    content = window.plus.Push.openNotification.aps.alert  
  } else {  
    content = window.plus.Push.openNotification.alert  
    window.plus.Push.clearLaunchAppCacheNotification()  
  }  

  outLine(content)  
}  

var receiveMessage = function () {  
  var msg  
  if (mui.os.ios) {  
    msg = window.plus.Push.receiveMessage.content  
  } else {  
    msg = window.plus.Push.receiveMessage.message  
  }  

  outLine(msg)  
}  

var onAliasAndTagsSet = function (event) {  
  var result = 'result code: ' + event.arguments.resultCode + ' '  
  result += 'tags: ' + event.arguments.tags + ' '  
  result += 'alias: ' + event.arguments.alias + ' '  
  mui.alert(result)  
  outLine(result)  
}  

var init = function () {  
  outLog('isInit:' + localStorage.getItem('isInit'))  
  outLine('isInit:' + localStorage.getItem('isInit'))  
  window.plus.Push.setDebugMode(true)  
  window.plus.Push.init()  
  getLaunchAppCacheNotification()  
  outLine('mui.os.android is ' + mui.os.android)  

  if (localStorage.getItem('isInit')) {  
    getRegistrationID()  
  } else {  
    localStorage.setItem('isInit', true)  
  }  
}  

document.addEventListener("plusready", init, false)  
document.addEventListener('jpush.onGetRegistrationId', (rId) => {  
  console.log('registration id: ' + rId)  
  outLine('jpush::registration id: ' + rId)  
  localStorage.setItem("registrationId", rId)  
  // setTagsWithAlias()  
}, false)  
document.addEventListener("jpush.receiveMessage", receiveMessage, false)  
document.addEventListener("jpush.receiveNotification", receiveNotification, false)  
document.addEventListener("jpush.openNotification", openNotification, false)  
document.addEventListener("jpush.setTagsWithAlias", onAliasAndTagsSet, false)

3.Android Studio,在manifest.json中permissions下,还需要添加以下代码

"Runtime": {  
  "description": "运行环境"  
},  
"XMLHttpRequest": {  
  "description": "跨域网络请求"  
},  
"NativeObj": {},  
"Device": {}

这些是我在项目里需要的,各人按自己的项目增减。若有提示未打包什么模块,参考hbuilder官网。
4.Android Studio,在JPushReceiver中onReceive方法下稍微改写一下,我改写是为了更好的查看日志,不改也可以,不影响集成。

@Override  
public void onReceive(Context context, Intent intent) {  
    String action = intent.getAction();  

    if (JPushInterface.ACTION_REGISTRATION_ID.equals(action)) {  
        String rId = JPushInterface.getRegistrationID(context);  
        Log.d(TAG, "regID:" + rId);  
        JPushService.transmitGetRegistrationId(rId);  
    } else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(action)) {  
        boolean state = JPushInterface.getConnectionState(context);  
        Log.d(TAG, "当前连接状态::" + state);  
    } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) {  
        handlingMessageReceive(intent);  
    } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) {  
        handlingNotificationReceive(context, intent);  
    } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) {  
        handlingNotificationOpen(context,   
intent);  
    } else {  
        Log.d(TAG, "Unhandled intent - " + action);  
    }  
}

当然,在app完全退出即进程被杀情况下,不能接收到推送,还有就是我还不知道怎么根据不同的通知跳转Vue中不同的页面,大家知道怎么做的话或者哪里写的不对,欢迎给我留言。
到这里,集成就结束了。这个排版我实在不太会排,第一次发分享,也不知道怎么贴图,要想看的清晰点可以查看附件。

继续阅读 »

一、首先先参考极光官方集成指南
参考https://github.com/jpush/jpush-hbuilder-demo

HBuilder 项目集成第三方插件,需先参考 HBuilder 官方的离线打包教程,将您的 HBuilder 项目集成进 Android 工程中。另外,还需要在极光官网根据你的包名申请APPKey。以上工作完成之后再执行以下步骤:
1.拷贝demo中 ./android/app/src/main/java/io.dcloud.feature.jpush 文件夹至你 Android Studio 工程的 /src/main/java/ 目录下。注意:RInformation.java文件不需要拷贝过来。
2.拷贝 ./jpush.js 到你 Android Studio 工程的 /assets/apps/HBuilder应用名/js/ 下。
3.在 /assets/apps/你的应用名/www/manifest.json 文件中添加:

"Push": {  
  "description": "消息推送"  
}

4.在 /assets/data/dcloud_properties.xml 中添加(如果已存在 Push feature,可以直接修改):

<feature name="Push" value="io.dcloud.feature.jpush.JPushService" />

5.在 app/build.gradle 中添加:

android {  
    ...  
defaultConfig {  
        applicationId "com.***.***"// JPush上注册的包名  
        ...  
    ndk {  
            // 选择要添加的对应 cpu 类型的 .so 库。  
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'//,'arm64-v8a',  'x86_64', 'mips', 'mips64'  
            // 还可以添加 , 'x86_64', 'mips', 'mips64'  
        }  
        manifestPlaceholders = [  
                JPUSH_PKGNAME: applicationId,  
                JPUSH_APPKEY : "*****", // JPush上注册的包名对应的 appkey  
                JPUSH_CHANNEL: "developer-default", // 暂时填写默认值即可  
        ]  
    }  
    buildTypes {  
        release {  
            minifyEnabled false  
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'  
        }  
    }  
...  
dependencies {  
    ...  
    compile 'cn.jiguang.sdk:jpush:3.1.8'  
    compile 'cn.jiguang.sdk:jcore:1.2.6'  
}

6.在 AndroidManifest.xml 中添加:

<receiver  
    android:name="io.dcloud.feature.jpush.JPushReceiver"  
    android:enabled="true"  
    android:exported="false">  
    <intent-filter>  
        <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!-- Required 用户注册SDK的 intent -->  
        <action android:name="cn.jpush.android.intent.UNREGISTRATION" />  
        <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required 用户接收SDK消息的 intent -->  
        <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required 用户接收SDK通知栏信息的 intent -->  
        <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏的 intent -->  
        <action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!-- Optional 用户接受 Rich Push Javascript 回调函数的intent -->  
        <action android:name="cn.jpush.android.intent.CONNECTION" /> <!-- 接收网络变化 连接/断开 since 1.6.3 -->  
        <category android:name="${JPUSH_PKGNAME}" />  
    </intent-filter>  
</receiver>

二、添加相关处理代码
1.在vue中static文件加下新建jpush文件夹,然后将【一.2】中相同的jpush.js文件复制进来。
2.在Vue中,index.html中加入
<script src="static/jpush/jpush.js"></script>
然后加入相关方法,如下:

// 控制台输出日志  
function outLog(msg) {  
  console.log(msg);  
}  

// 界面弹出吐司提示  
function outLine(msg) {  
  mui.toast(msg);  
}  

var setTagsWithAlias = function () {  
  var tag1 = '...'  
  var tag2 = ''  
  var tag3 = ''  
  var alias = 'test'  
  var tags = []  

  if (tag1) {  
    tags.push(tag1)  
  }  
  if (tag2) {  
    tags.push(tag2)  
  }  
  if (tag3) {  
    tags.push(tag3)  
  }  
  window.plus.Push.setTagsWithAlias(tags, alias)  
}  

var getRegistrationID = function () {  
  window.plus.Push.getRegistrationID(function (data) {  
    if (data.length != 0) {  
      outLine('getRegistrationID>>>>' + data)  
    }  
  })  
}  

var getLaunchAppCacheNotification = function () {  
  if (mui.os.android) {  
    window.plus.Push.getLaunchAppCacheNotification(function (data) {  
      if (data.alert) {  
        outLine('cache:' + data.alert)  
      }  
    })  
  }  
}  

var receiveNotification = function (event) {  
  var content  
  if (mui.os.ios) {  
    content = window.plus.Push.receiveNotification.aps.alert  
  } else {  
    outLine('receiveNotification---else')  
    content = window.plus.Push.receiveNotification.alert  
  }  

  outLine(content)  
}  

var openNotification = function () {  
  var content  
  if (mui.os.ios) {  
    content = window.plus.Push.openNotification.aps.alert  
  } else {  
    content = window.plus.Push.openNotification.alert  
    window.plus.Push.clearLaunchAppCacheNotification()  
  }  

  outLine(content)  
}  

var receiveMessage = function () {  
  var msg  
  if (mui.os.ios) {  
    msg = window.plus.Push.receiveMessage.content  
  } else {  
    msg = window.plus.Push.receiveMessage.message  
  }  

  outLine(msg)  
}  

var onAliasAndTagsSet = function (event) {  
  var result = 'result code: ' + event.arguments.resultCode + ' '  
  result += 'tags: ' + event.arguments.tags + ' '  
  result += 'alias: ' + event.arguments.alias + ' '  
  mui.alert(result)  
  outLine(result)  
}  

var init = function () {  
  outLog('isInit:' + localStorage.getItem('isInit'))  
  outLine('isInit:' + localStorage.getItem('isInit'))  
  window.plus.Push.setDebugMode(true)  
  window.plus.Push.init()  
  getLaunchAppCacheNotification()  
  outLine('mui.os.android is ' + mui.os.android)  

  if (localStorage.getItem('isInit')) {  
    getRegistrationID()  
  } else {  
    localStorage.setItem('isInit', true)  
  }  
}  

document.addEventListener("plusready", init, false)  
document.addEventListener('jpush.onGetRegistrationId', (rId) => {  
  console.log('registration id: ' + rId)  
  outLine('jpush::registration id: ' + rId)  
  localStorage.setItem("registrationId", rId)  
  // setTagsWithAlias()  
}, false)  
document.addEventListener("jpush.receiveMessage", receiveMessage, false)  
document.addEventListener("jpush.receiveNotification", receiveNotification, false)  
document.addEventListener("jpush.openNotification", openNotification, false)  
document.addEventListener("jpush.setTagsWithAlias", onAliasAndTagsSet, false)

3.Android Studio,在manifest.json中permissions下,还需要添加以下代码

"Runtime": {  
  "description": "运行环境"  
},  
"XMLHttpRequest": {  
  "description": "跨域网络请求"  
},  
"NativeObj": {},  
"Device": {}

这些是我在项目里需要的,各人按自己的项目增减。若有提示未打包什么模块,参考hbuilder官网。
4.Android Studio,在JPushReceiver中onReceive方法下稍微改写一下,我改写是为了更好的查看日志,不改也可以,不影响集成。

@Override  
public void onReceive(Context context, Intent intent) {  
    String action = intent.getAction();  

    if (JPushInterface.ACTION_REGISTRATION_ID.equals(action)) {  
        String rId = JPushInterface.getRegistrationID(context);  
        Log.d(TAG, "regID:" + rId);  
        JPushService.transmitGetRegistrationId(rId);  
    } else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(action)) {  
        boolean state = JPushInterface.getConnectionState(context);  
        Log.d(TAG, "当前连接状态::" + state);  
    } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) {  
        handlingMessageReceive(intent);  
    } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) {  
        handlingNotificationReceive(context, intent);  
    } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) {  
        handlingNotificationOpen(context,   
intent);  
    } else {  
        Log.d(TAG, "Unhandled intent - " + action);  
    }  
}

当然,在app完全退出即进程被杀情况下,不能接收到推送,还有就是我还不知道怎么根据不同的通知跳转Vue中不同的页面,大家知道怎么做的话或者哪里写的不对,欢迎给我留言。
到这里,集成就结束了。这个排版我实在不太会排,第一次发分享,也不知道怎么贴图,要想看的清晰点可以查看附件。

收起阅读 »

Android uni-app原生插件开发文档

原生插件 uniapp原生插件 uni原生插件 Android

uni-app原生插件开发教程 Android Studio 版

请移步新的文档 ,此文章已不再更新维护

uni-app原生插件开发教程 Android Studio 版

请移步新的文档 ,此文章已不再更新维护

iOS uni-app原生插件开发文档

iOS uni原生插件 原生插件 uniapp原生插件

请移步 新的文档 此文档已停止维护!!!

iOS uni-app原生插件开发文档

一、文档概述

本文档主要介绍如何在uni-app中基于WeexSDK 开发iOS原生插件。
更多说明请参考uni-app原生插件开发指南

1.1、阅读对象

在您阅读此文档时,首先要知道uni-app支持weex插件,同时我们假定您已经具备了相应iOS应用开发经验,学习过 weex 知识并能够理解相关概念。此外,您也应该对HTML,JavaScript,CSS等有一定的了解,并且熟悉在JavaScript和Objective-C环境下的JSON格式数据操作等。

1.2、开发前准备

  • OS X 10.14.0+
  • Xcode 11.0+
  • 学习weex 0.26.0版本框架API,weex扩展API for iOS
  • 下载开发插件需要的SDK包 最新版本的SDK包,找到里面的HBuilder-uniPluginDemo文件夹,里面包含HBuilder-uniPlugin插件开发工程,后面会用到。
  • 下载开发插件时会用到的js代码的开发工具HBuilderX(下载地址),下载哪个版本的HBuilderX需要注意下,保持和上条中提到的SDK包(在下载SDK包的下载界面中有版本相关的文字描述如下图),它提到的版本号一致。
  • 确定SDK包里的Xcode工程HBuilder-uniPlugin内是否引用了SDK包里的liblibWeex.a库和weex-main-jsfm.js文件

二、 插件开发(以RichAlert插件为例)

2.1、 首先用Xcode创建静态.a库工程libWeexDCRichAlert 或(静态Framework工程),如何创建静态库工程请自行百度,下面提供了2个连接供参考。

iOS如何制作.a库
iOS如何制作静态Framework库

2.2、 在下载的工程包里找到HBuilder-uniPluginDemo文件夹,然后打开HBuilder-uniPlugin工程,把刚创建的静态库工程引入到HBuilder-uniPlugin工程,引入后的样子如下图所示,至于如何把静态库工程引入到HBuilder-uniPlugin工程里去,请自行百度,很简单的。

然后,修改libWeexDCRichAlert工程的iOS Deployment Target为8.0,如下图所示:

然后,在静态库工程libWeexDCRichAlert的 Header Search Paths 中添加引用如下图所示:

然后,在HBuilder-uniPlugin工程的Link Binary With Libraries中添加libWeexDCRichAlert.a库;然后,在Target Dependencies 中,添加插件工程的libWeexDCRichAlert的targets,如下图所示:

2.3、 配置需要注册的插件,打开HBuilder-uniPlugin工程里的info.plist 文件 加入节点,需要严格按要求配置,如下图所示:

其中,hooksClass的值是类名,是给有些插件需要在app启动时做初始化或者获取系统事件用的,如果没有可以不填为空;
plugins下的每一项是weex扩展模块或组件能力相关的配置信息,里面包含name(填weex模块或组件类名对应的js层用到的字符串,js层中将通过该字符串来使用原生层的模块或组件),class(填weex模块或组件类名),type(填modulecomponent,一定不能配置错),注意不支持weex的handler扩展。

2.4 开始具体代码开发,分三步:其中第二步看情况(有需要在app启动时初始化或者获取系统事件用的,可以有第2步,如果没有则跳过这步)

第一步,在静态库libWeexDCRichAlert工程里,新建模块类DCRichAlertModule,注意命名加前缀防止冲突(如何具体开发模块或组件请参考,weex官方扩展iOS能力


第二步,在静态库libWeexDCRichAlert工程里,新建DCRichAlertProxy类(注意命名加前缀防止冲突),继承 NSObject
遵守UniPluginProtocol协议 ,用来在app启动时初始化或者获取系统事件用的,这个类里尽量不要有其他的过多代码逻辑。如下图:


第三步,用之前下载好的HBuilderX开发工具 新建uni-app项目,选择默认模版,然后在index.vue文件里面编写下面示例的js代码,也可以再创建一个.nvue文件编写下面示例的js代码。 注意:后缀为.vue的文件只支持使用module(module也只支持异步方法不支持同步方法),不支持使用component,但是后缀为.nvue的文件两者都可以使用并且module同步异步都支持

示例

 引用方式  
const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');  
 调用  
dcRichAlert.show({  
                    position: 'bottom',  
                    title: "提示信息",  
                    titleColor: '#FF0000',  
                    content: "<a href='https://uniapp.dcloud.io/' value='Hello uni-app'>uni-app</a> 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",  
                    contentAlign: 'left',  
                    checkBox: {  
                        title: '不再提示',  
                        isSelected: true  
                    },  
                    buttons: [{  
                            title: '取消'  
                        },  
                        {  
                            title: '否'  
                        },  
                        {  
                            title: '确认',  
                            color: '#3F51B5'  
                        }  
                    ]  
                }, result => {  
                    switch (result.type) {  
                        case 'button':  
                            console.log("callback---button--" + result.index);  
                            break;  
                        case 'checkBox':  
                            console.log("callback---checkBox--" + result.isSelected);  
                            break;  
                        case 'a':  
                            console.log("callback---a--" + JSON.stringify(result));  
                            break;  
                        case 'backCancel':  
                            console.log("callback---backCancel--");  
                            break;  
                    }  
                });

然后运行导出,可以得到编译后的代码,

然后把这些代码考到HBuilder-uniPlugin工程的Pandora目录下的www目录下

如下图,其中红矩形框起来的,control.xml里的appid和目录的名称都是appid,是从HBuilderX开发工具中导出来的 资源包里的manifest.json的id,三者值需要一致

三、本地调试插件的代码

然后就可以运行HBuilder-uniPlugin工程调试代码了,效果如下图所示:

如果调试过程中遇到问题,可能是原生的问题也可能是js代码的问题,如果是原生的问题,直接修改原生代码就可以了,但是如果是js代码的问题,需要修改.nvue或.vue的代码这个时候就需要重新导出编译后的代码(编译导出代码有可能会报错,注意控制台的日志信息,千万不要把有问题的资源拿去调试),拷贝到HBuilder-uniPlugin工程的Pandora目录下的www目录下,然后务必删除之前的app,再重新运行工程

如果运行测试没任何问题,就可以进行下面的生成插件包的步骤了。

四、生成插件包

此步骤应该在您插件所有接口封装完毕,并在调试工程中测试完成后,再进行以下操作,说明中均以示例插件libWeexDCRichAlert为例进行的操作。在实际操作时,需将所有出现的libWeexDCRichAlert替换成您自己的插件名字,而且在插件开发过程中给文件命名或类命名时提倡增加前缀,以避免和其它模块冲突
如示例中插件类Module的类名是“DCRichAlertModule” ,其中“DC”就是前缀(作者标识)!
Module扩展和Component扩展在引用中的name 需要前缀加入你自己的标识,防止插件冲突。
如示例中配置的name为“DCloud-RichAlert”,其中“DCloud”就是标识!

4.1 编译生成插件静态库.a文件

.a库必须是真机环境的,并且需要支持armv7和arm64架构,且Build Active Architecture Only设置为NO,您可以在终端用以下命令查看.a库支持的架构:
lipo -info libWeexDCRichAlert.a

4.2 编写package.json文件,按下列链接配置

点击查看详细配置说明
iOS平台 package.json 详细说明请查看这篇文档前面部分,会帮助您更好的理解如何配置 https://ask.dcloud.net.cn/article/35764

iOS 插件包 至少需要包含:package.json文件 和 ios文件夹(名称必须是小写的ios)里面包含 .a (.a库必须是lib开头命名,比如libWeexDCRichAlert.a)或framework。


4.3 生成.zip包

将DCloud-RichAlert文件夹打成zip包,zip包的名称为(DCloud-RichAlert.zip)然后准备提交插件市场,其中DCloud-RichAlert文件夹名称和package.json 里id的值一致,zip包的名称是id值

五、如果想要共享给其他开发者,把这个插件提交插件市场

不提交插件市场,也可以把生成的插件放到HBuilderX里,然后提交云端打包使用,提交到云端打包之前确保插件在本地是调试通的,否则云端打包出问题,增加排查问题的难度。

<a id="isPlatformVersionAtLeast"/>

六、编写原生代码时注意事项

目前 HBuilderX 正式版云端打包机使用的Xcode版本为 10.XXcode11.0 及以上版本对@available(, *)的实现做了调整打包后的.a库不兼容低版本的Xcode, 所以如果使用Xcode 11.0及以上版本开发插件并且插件中代码用到了@available(, *)关键字请按下图修改,否则可能导致打包失败。报错 Undefined symbols "___isPlatformVersionAtLeast"
(使用 HBuilderX alpha 版本没有此问题,正式版云端打包机近期会更新到最新的Xcode版本)

Tips

开发uni-app原生插件时注意不要开发广点通广告插件和穿山甲广告插件,目前不支持。

获取 UIViewController

因为 uni 框架机制,module 的 weexInstance 没有绑定 viewController,故 weexInstance.viewController 值为 nil,如果想通过 UIViewController 来跳转页面可使用下面的方法获取 UIViewController**

// 获取当前显示的 UIViewController  
+ (UIViewController *)dc_findCurrentShowingViewController {  
    //获得当前活动窗口的根视图  
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;  
    UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];  
    return currentShowingVC;  
}  
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc  
{  
    // 递归方法 Recursive method  
    UIViewController *currentShowingVC;  
    if ([vc presentedViewController]) {  
        // 当前视图是被presented出来的  
        UIViewController *nextRootVC = [vc presentedViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else if ([vc isKindOfClass:[UITabBarController class]]) {  
        // 根视图为UITabBarController  
        UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else if ([vc isKindOfClass:[UINavigationController class]]){  
        // 根视图为UINavigationController  
        UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else {  
        // 根视图为非导航类  
        currentShowingVC = vc;  
    }  

    return currentShowingVC;  
}

获取页面可访问图片资源存储路径 (vue页面需要注意,nvue页面不存这个问题)

有些插件可能需要返回本地的图片路径给页面来显示,如果页面是vue的话是使用 WKWebview 渲染,访问本地图片资源可能会存在跨域问题访问不到图片资源,所以需要将图片存放到指定路径下,按照下面的方法获取图片存储路径即可

原生端实现

// 引用头文件  
#import "PDRCoreApp.h"  
#import "PDRCoreAppManager.h"  
#import "PDRCoreAppInfo.h"  

// 获取路径信息  
PDRCoreAppInfo *appinfo = [PDRCore Instance].appManager.getMainAppInfo;  
// 将图片存储到 appinfo.documentPath 路径下即可,可以创建子目录;  
// 示例,原生图片存储路径为  
NSString *imgPath = [appinfo.documentPath stringByAppendingPathComponent:@"test.png"];

js 端获取图片路径有两种方式

// 1.使用相对路径  
var relativePath = "_doc/test.png"  

// 2.使用平台的绝对路径  
var docPath = plus.io.convertLocalFileSystemURL("_doc/");  
var absolutePath = docPath + 'test.png'

欢迎有原生开发能力的朋友入群一起交流学习(入群请提供注册邮箱):
DCloud原生开发者群:
1群:256775471(已满)
2群:814228233(已满)
3群:455763866

Android原生插件开发参考:https://ask.dcloud.net.cn/article/35416
更多uni-app原生插件文档参考:uni-app原生插件开发指南

继续阅读 »

请移步 新的文档 此文档已停止维护!!!

iOS uni-app原生插件开发文档

一、文档概述

本文档主要介绍如何在uni-app中基于WeexSDK 开发iOS原生插件。
更多说明请参考uni-app原生插件开发指南

1.1、阅读对象

在您阅读此文档时,首先要知道uni-app支持weex插件,同时我们假定您已经具备了相应iOS应用开发经验,学习过 weex 知识并能够理解相关概念。此外,您也应该对HTML,JavaScript,CSS等有一定的了解,并且熟悉在JavaScript和Objective-C环境下的JSON格式数据操作等。

1.2、开发前准备

  • OS X 10.14.0+
  • Xcode 11.0+
  • 学习weex 0.26.0版本框架API,weex扩展API for iOS
  • 下载开发插件需要的SDK包 最新版本的SDK包,找到里面的HBuilder-uniPluginDemo文件夹,里面包含HBuilder-uniPlugin插件开发工程,后面会用到。
  • 下载开发插件时会用到的js代码的开发工具HBuilderX(下载地址),下载哪个版本的HBuilderX需要注意下,保持和上条中提到的SDK包(在下载SDK包的下载界面中有版本相关的文字描述如下图),它提到的版本号一致。
  • 确定SDK包里的Xcode工程HBuilder-uniPlugin内是否引用了SDK包里的liblibWeex.a库和weex-main-jsfm.js文件

二、 插件开发(以RichAlert插件为例)

2.1、 首先用Xcode创建静态.a库工程libWeexDCRichAlert 或(静态Framework工程),如何创建静态库工程请自行百度,下面提供了2个连接供参考。

iOS如何制作.a库
iOS如何制作静态Framework库

2.2、 在下载的工程包里找到HBuilder-uniPluginDemo文件夹,然后打开HBuilder-uniPlugin工程,把刚创建的静态库工程引入到HBuilder-uniPlugin工程,引入后的样子如下图所示,至于如何把静态库工程引入到HBuilder-uniPlugin工程里去,请自行百度,很简单的。

然后,修改libWeexDCRichAlert工程的iOS Deployment Target为8.0,如下图所示:

然后,在静态库工程libWeexDCRichAlert的 Header Search Paths 中添加引用如下图所示:

然后,在HBuilder-uniPlugin工程的Link Binary With Libraries中添加libWeexDCRichAlert.a库;然后,在Target Dependencies 中,添加插件工程的libWeexDCRichAlert的targets,如下图所示:

2.3、 配置需要注册的插件,打开HBuilder-uniPlugin工程里的info.plist 文件 加入节点,需要严格按要求配置,如下图所示:

其中,hooksClass的值是类名,是给有些插件需要在app启动时做初始化或者获取系统事件用的,如果没有可以不填为空;
plugins下的每一项是weex扩展模块或组件能力相关的配置信息,里面包含name(填weex模块或组件类名对应的js层用到的字符串,js层中将通过该字符串来使用原生层的模块或组件),class(填weex模块或组件类名),type(填modulecomponent,一定不能配置错),注意不支持weex的handler扩展。

2.4 开始具体代码开发,分三步:其中第二步看情况(有需要在app启动时初始化或者获取系统事件用的,可以有第2步,如果没有则跳过这步)

第一步,在静态库libWeexDCRichAlert工程里,新建模块类DCRichAlertModule,注意命名加前缀防止冲突(如何具体开发模块或组件请参考,weex官方扩展iOS能力


第二步,在静态库libWeexDCRichAlert工程里,新建DCRichAlertProxy类(注意命名加前缀防止冲突),继承 NSObject
遵守UniPluginProtocol协议 ,用来在app启动时初始化或者获取系统事件用的,这个类里尽量不要有其他的过多代码逻辑。如下图:


第三步,用之前下载好的HBuilderX开发工具 新建uni-app项目,选择默认模版,然后在index.vue文件里面编写下面示例的js代码,也可以再创建一个.nvue文件编写下面示例的js代码。 注意:后缀为.vue的文件只支持使用module(module也只支持异步方法不支持同步方法),不支持使用component,但是后缀为.nvue的文件两者都可以使用并且module同步异步都支持

示例

 引用方式  
const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');  
 调用  
dcRichAlert.show({  
                    position: 'bottom',  
                    title: "提示信息",  
                    titleColor: '#FF0000',  
                    content: "<a href='https://uniapp.dcloud.io/' value='Hello uni-app'>uni-app</a> 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",  
                    contentAlign: 'left',  
                    checkBox: {  
                        title: '不再提示',  
                        isSelected: true  
                    },  
                    buttons: [{  
                            title: '取消'  
                        },  
                        {  
                            title: '否'  
                        },  
                        {  
                            title: '确认',  
                            color: '#3F51B5'  
                        }  
                    ]  
                }, result => {  
                    switch (result.type) {  
                        case 'button':  
                            console.log("callback---button--" + result.index);  
                            break;  
                        case 'checkBox':  
                            console.log("callback---checkBox--" + result.isSelected);  
                            break;  
                        case 'a':  
                            console.log("callback---a--" + JSON.stringify(result));  
                            break;  
                        case 'backCancel':  
                            console.log("callback---backCancel--");  
                            break;  
                    }  
                });

然后运行导出,可以得到编译后的代码,

然后把这些代码考到HBuilder-uniPlugin工程的Pandora目录下的www目录下

如下图,其中红矩形框起来的,control.xml里的appid和目录的名称都是appid,是从HBuilderX开发工具中导出来的 资源包里的manifest.json的id,三者值需要一致

三、本地调试插件的代码

然后就可以运行HBuilder-uniPlugin工程调试代码了,效果如下图所示:

如果调试过程中遇到问题,可能是原生的问题也可能是js代码的问题,如果是原生的问题,直接修改原生代码就可以了,但是如果是js代码的问题,需要修改.nvue或.vue的代码这个时候就需要重新导出编译后的代码(编译导出代码有可能会报错,注意控制台的日志信息,千万不要把有问题的资源拿去调试),拷贝到HBuilder-uniPlugin工程的Pandora目录下的www目录下,然后务必删除之前的app,再重新运行工程

如果运行测试没任何问题,就可以进行下面的生成插件包的步骤了。

四、生成插件包

此步骤应该在您插件所有接口封装完毕,并在调试工程中测试完成后,再进行以下操作,说明中均以示例插件libWeexDCRichAlert为例进行的操作。在实际操作时,需将所有出现的libWeexDCRichAlert替换成您自己的插件名字,而且在插件开发过程中给文件命名或类命名时提倡增加前缀,以避免和其它模块冲突
如示例中插件类Module的类名是“DCRichAlertModule” ,其中“DC”就是前缀(作者标识)!
Module扩展和Component扩展在引用中的name 需要前缀加入你自己的标识,防止插件冲突。
如示例中配置的name为“DCloud-RichAlert”,其中“DCloud”就是标识!

4.1 编译生成插件静态库.a文件

.a库必须是真机环境的,并且需要支持armv7和arm64架构,且Build Active Architecture Only设置为NO,您可以在终端用以下命令查看.a库支持的架构:
lipo -info libWeexDCRichAlert.a

4.2 编写package.json文件,按下列链接配置

点击查看详细配置说明
iOS平台 package.json 详细说明请查看这篇文档前面部分,会帮助您更好的理解如何配置 https://ask.dcloud.net.cn/article/35764

iOS 插件包 至少需要包含:package.json文件 和 ios文件夹(名称必须是小写的ios)里面包含 .a (.a库必须是lib开头命名,比如libWeexDCRichAlert.a)或framework。


4.3 生成.zip包

将DCloud-RichAlert文件夹打成zip包,zip包的名称为(DCloud-RichAlert.zip)然后准备提交插件市场,其中DCloud-RichAlert文件夹名称和package.json 里id的值一致,zip包的名称是id值

五、如果想要共享给其他开发者,把这个插件提交插件市场

不提交插件市场,也可以把生成的插件放到HBuilderX里,然后提交云端打包使用,提交到云端打包之前确保插件在本地是调试通的,否则云端打包出问题,增加排查问题的难度。

<a id="isPlatformVersionAtLeast"/>

六、编写原生代码时注意事项

目前 HBuilderX 正式版云端打包机使用的Xcode版本为 10.XXcode11.0 及以上版本对@available(, *)的实现做了调整打包后的.a库不兼容低版本的Xcode, 所以如果使用Xcode 11.0及以上版本开发插件并且插件中代码用到了@available(, *)关键字请按下图修改,否则可能导致打包失败。报错 Undefined symbols "___isPlatformVersionAtLeast"
(使用 HBuilderX alpha 版本没有此问题,正式版云端打包机近期会更新到最新的Xcode版本)

Tips

开发uni-app原生插件时注意不要开发广点通广告插件和穿山甲广告插件,目前不支持。

获取 UIViewController

因为 uni 框架机制,module 的 weexInstance 没有绑定 viewController,故 weexInstance.viewController 值为 nil,如果想通过 UIViewController 来跳转页面可使用下面的方法获取 UIViewController**

// 获取当前显示的 UIViewController  
+ (UIViewController *)dc_findCurrentShowingViewController {  
    //获得当前活动窗口的根视图  
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;  
    UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];  
    return currentShowingVC;  
}  
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc  
{  
    // 递归方法 Recursive method  
    UIViewController *currentShowingVC;  
    if ([vc presentedViewController]) {  
        // 当前视图是被presented出来的  
        UIViewController *nextRootVC = [vc presentedViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else if ([vc isKindOfClass:[UITabBarController class]]) {  
        // 根视图为UITabBarController  
        UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else if ([vc isKindOfClass:[UINavigationController class]]){  
        // 根视图为UINavigationController  
        UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];  
        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];  

    } else {  
        // 根视图为非导航类  
        currentShowingVC = vc;  
    }  

    return currentShowingVC;  
}

获取页面可访问图片资源存储路径 (vue页面需要注意,nvue页面不存这个问题)

有些插件可能需要返回本地的图片路径给页面来显示,如果页面是vue的话是使用 WKWebview 渲染,访问本地图片资源可能会存在跨域问题访问不到图片资源,所以需要将图片存放到指定路径下,按照下面的方法获取图片存储路径即可

原生端实现

// 引用头文件  
#import "PDRCoreApp.h"  
#import "PDRCoreAppManager.h"  
#import "PDRCoreAppInfo.h"  

// 获取路径信息  
PDRCoreAppInfo *appinfo = [PDRCore Instance].appManager.getMainAppInfo;  
// 将图片存储到 appinfo.documentPath 路径下即可,可以创建子目录;  
// 示例,原生图片存储路径为  
NSString *imgPath = [appinfo.documentPath stringByAppendingPathComponent:@"test.png"];

js 端获取图片路径有两种方式

// 1.使用相对路径  
var relativePath = "_doc/test.png"  

// 2.使用平台的绝对路径  
var docPath = plus.io.convertLocalFileSystemURL("_doc/");  
var absolutePath = docPath + 'test.png'

欢迎有原生开发能力的朋友入群一起交流学习(入群请提供注册邮箱):
DCloud原生开发者群:
1群:256775471(已满)
2群:814228233(已满)
3群:455763866

Android原生插件开发参考:https://ask.dcloud.net.cn/article/35416
更多uni-app原生插件文档参考:uni-app原生插件开发指南

收起阅读 »

uni-app原生插件(native plugin)格式说明

uni原生插件 原生插件 uniapp原生插件

新版原生插件开发文档已发布,请移步:https://nativesupport.dcloud.net.cn/

此文档将不再更新维护

uni-app原生插件(native plugin)提交DCloud插件市场需按以下目录格式配置:


上传时压缩为zip格式文件,压缩文件中必须包含目录名称,如下:

package.json

uni-app原生插件描述文件,完整格式如下
注:如果只有一端比如只包含android插件,请把ios节点删除掉,不能直接注释

{  
    "name": "插件名称",  
    "id": "插件标识",  
    "version": "插件版本号",  
    "description": "插件描述信息",  
    "_dp_type":"nativeplugin",  
    "_dp_nativeplugin":{  
        "android": {  
            "plugins": [  
                {  
                    "type": "module|component, 必填, 根据插件类型选择",  
                    "name": "必填, 注册插件的名称, 通常与插件标识一致",  
                    "class": "必填, 注册插件的类名"  
                }  
            ],  
            "hooksClass": "可选, 事件钩子注册类名",  
            "integrateType": "必填, 可取值aar|jar",  
            "dependencies": [  
                "可选, 依赖的库名称"  
            ],  
            "compileOptions": {  //可选,Java编译参数配置  
                "sourceCompatibility": "1.8",  
                "targetCompatibility": "1.8"  
            },  
            "abis": [  
                "可选, 支持的abi类型, 可取值armeabi-v7a|arm64-v8a|x86"  
            ],  
            "minSdkVersion": "可选,支持的Android最低版本,如21",  
            "permissions": [  
                "可选, 要使用的Android权限列表"  
            ],  
            "parameters": {  
                "插件需要配置的参数名称, 如appid": {  
                    "des": "参数描述",  
                    "key": "AndroidManifest.xml中添加meta-data节点的android:name属性值, 如GETUI_APPID",  
                    "placeholder": "build.gradle中添加到manifestPlaceholders中的字段名"  
                }  
            }  
        },  
        "ios": {  
            "plugins": [  
                {  
                    "type": "必填, module|component, 根据插件类型选择",  
                    "name": "必填, 注册插件的名称, 通常与插件标识一致",  
                    "class": "必填, 注册插件的类名"   
                }  
            ],  
            "integrateType": "必填, 可取值framework|library",  
            "hooksClass": "可选, 事件钩子注册类名",  
            "frameworks": [  
                "依赖的系统库(系统库有.framework和.tbd和.dylib类型),和第三方.framework动态库(.framework动态库也需要在这里配置);(第三方 .a 库或 .framework**静态库**直接放到ios根目录即可,不需要配置)"  
            ],  
            "embedFrameworks": [  
                "依赖的.framework动态库,(注意.framework动态库也需要在上面的 frameworks 节点添加配置,同样将动态库.framework文件放到 ios 根目录中)"  
            ],  
            "capabilities": {    // 配置应用的capabilities数据(根据XCode规范分别配置到entitlements和plist文件中)  
                "entitlements": {    // 合并到工程entitlements文件的数据(json格式)  
                },  
                "plists": {    // 合并到工程Info.plist文件的数据(json格式)  
                }  
            },  
            "plists": {    // 自定义配置工程Info.plist文件的数据(json格式),优先级高于capabilities->plists  
            },  
            "resources": [  
                "可选, 插件要使用的资源文件列表,相对于ios目录的路径"  
            ],  
            "assets": [    //HBuilderX2.3.4及以上版本支持  
                "可选,插件要使用的xcassets文件列表,相对于ios目录的路径"  
            ],  
            "privacies": [  
                "可选, 插件使用到的隐私列表,如NSPhotoLibraryUsageDescription"  
            ],  
            "deploymentTarget": "8.0, 可选,支持的iOS最低版本",  
            "validArchitectures": [    // 可选,支持的CPU架构类型  
                "arm64"    //支持多个值,可取值:arm64 arm64e armv7 armv7s x86_64  
            ],  
            "parameters": {  
                "插件需要配置的参数名称, 如appid": {  
                    "des": "参数描述信息",  
                    "key": "参数需要配置到info.plist中的键名, 嵌套时使用:分割,如getui:appid"  
                }  
            }  
        }  
    }  
}

name

插件名称,在插件市场(HBuilderX)中显示的名称。

id

插件标识,插件使用者引用插件时使用的名称,只能使用英文字符、数字、及字符(-、_),且必须以英文字符开头。
推荐使用"%开发者名称%-%插件名称%",如"DC-RichAlert"。

插件标识必须在对应android和ios节点下plugins中进行注册,与name字段值一致

android 端说明

uni-app原生插件Android平台资源,支持Android平台时必须添加此目录,所有Android平台相关的资源都放到此目录下。

  • aar文件,直接放到android目录下,云端打包会自动引用所有的aar文件
  • android\libs目录,所有需要使用的jar文件放到此目录,如果包含so文件,则放到libs下对应cpu类型目录
  • android\assets目录,Android平台需要assets资源
  • android\res目录,Android平台需要的res资源
    Android平台原生插件开发教程参考:https://ask.dcloud.net.cn/article/35416

<a id="dependencies"></a>

dependencies

用于配置插件依赖的仓储库
android插件中集成的第三方SDK 如果是jar或so放入到libs文件夹中即可,无需要配置到dependencies节点下。
gradle配置的第三方sdk 仓储名称方式的配置信息 需要在dependencies节点下填写。
云端打包仅支持从以下仓储下载依赖库,务必注意依赖库已提交到这些仓储中

  • google()
  • maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
  • maven { url 'https://jitpack.io' }
  • jcenter()

app.gradle 配置中dependencies节点信息如下。

dependencies {  
    implementation "com.android.support:recyclerview-v7:25.3.1"  
    implementation "com.android.support:support-v4:25.3.1"  
    implementation "com.android.support:appcompat-v7:25.3.1"  
    implementation "com.alibaba:fastjson:1.1.46.android"  
}

package.json的dependencies节点就需要配置如下信息

dependencies [  
    "com.android.support:recyclerview-v7:25.3.1",  
    "com.android.support:support-v4:25.3.1",  
    "com.android.support:appcompat-v7:25.3.1",  
    "com.alibaba:fastjson:1.1.46.android"  
]

!!!注意V7、V4、fastjson都已默认集成 不需要再次配置。这里仅是示例写法!!!

HBuilderX2.3.8+开始添加更灵活配置,支持源码写dependencies内容
dependencies中的值支持json对象,如下:

dependencies [//内容支持字符串或json格式,支持混写  
    {  
        "id": "com.android.support.test.espresso:espresso-contrib",  //可选,String类型,依赖库标识  
        "source": "implementation('com.android.support.test.espresso:espresso-contrib:2.2.2', {\r\nexclude group: 'com.android.support', module: 'support-v4'\r\n})"   //必选,String类型,依赖库源码  
    }  
]

JSON格式支持以下字段:

  • id
    依赖库的标识,使用多个uni原生插件时,都依赖相同的库时会根据此标识去重,避免产生冲突。
    不配置此值则不做去重处理。
  • source
    依赖库源码,直接将此内容配置到云端打包工程的build.gradle文件的dependencies中。
    只支持写引用公共仓储上的库。
    如上示例,将会在云端打包时将以下内容添加到build.gradle文件的dependencies中:
    implementation('com.android.support.test.espresso:espresso-contrib:2.2.2', {  
    exclude group: 'com.android.support', module: 'support-v4'  
    })

注意:换行符号需要转义为\r\n。

<a id="compileOptions"></a>

compileOptions

HBuilderX2.3.8+开始支持配置云端打包java编译参数。
格式如下:

"compileOptions": {  //可选,Java编译参数配置  
    "sourceCompatibility": "1.8",  
    "targetCompatibility": "1.8"  
},

云端打包使用的jdk版本为1.8,仅支持取值"1.6"、"1.7"、"1.8"。

<a id="abis"></a>

abis

Android平台支持的CPU类型,当插件中包含so库时需要配置插件支持的cpu类型。

"abis": [  
    "armeabi-v7a",  
    "x86"  
],

云端打包内置插件支持以下CPU类型:

  • "armeabi-v7a",7代及以上的ARM处理器(ARM 32位)
  • "arm64-v8a",第8代、64位ARM处理器(ARM 64位)
  • "x86",使用X86架构的处理器(X86 32位)

插件包含so库时至少要支持"armeabi-v7a"类型,从2019年9月开始提交的插件会检测支持CPU类型,不满足要求将无法上线
为了兼容更多的设备和应用市场要求,推荐支持"armeabi-v7a"、"arm64-v8a"、"x86"三种类型。

将aar文件作为zip解压,jni目录下包含的子目录就是其支持的CPU类型

parameters

如果插件使用时需配置参数,如appid、appkey时,可配置parameters字段进行定义,提交云端打包后将会根据配置把数据放到AndroidManifest.xml的meta-data中。
parameters下每个节点定义一个要配置的参数,参数名称为键名,以下为定义appid参数为示例:

"parameters": {  
    "android_appid": {  
        "des": "XXX插件的appid参数",  
        "key": "XXX_APPID",  
        "placeholder": "XXX_APPID",  
        "value": "TEST_${android_appid}"  
   }  
}
  • des 参数的描述信息
    可选,在HBuilderX中manifest.json的可视化界面中显示,用于提示插件使用者配置此参数的作用。
  • key 云端打包时原生层使用的键名称
    可选,与placeholder二选一配置。
    此值为AndroidManifest.xml中添加meta-data节点的android:name属性值,推荐使用“插件标识_键名”格式,如"DC-RichAlert_appid"。
  • placeholder HBuilderX2.5.6+版本支持
    可选,与key二选一配置。
    此值为在build.gradle中添加manifestPlaceholders的键名,为了避免与其它插件冲突推荐使用“插件标识_键名”格式,如"DC-RichAlert_appid"
  • value 云端打包时格式化的键值
    可选,如果需要对插件使用者配置的参数值做一些格式化处理(如添加固定的前缀或后缀)时才需要配置vlue字段。
    其中${android_appid}表示插件使用者配置的android_appid参数值;不配置此字段则键值为插件使用者配置的参数值。

插件使用时需在manifest.json的"app-plus"->"nativePlugins"->"插件标识"中配置(最新版HBuilderX已支持可视化配置)
以"DC-RichAlert"插件配置appid参数为示例:

"app-plus": {  
    "nativePlugins": {  
        "DC-RichAlert": {  
            "android_appid": "T1234567890"  
        }  
    }  
}

按上面的配置规则提交云端打包后将在AndroidManifest.xml中添加以下数据:

<meta-data android:name="XXX_APPID" android:value="TEST_T1234567890"/>

按上面的配置规则提交云端打包后将在manifestPlaceholders中添加以下数据:

"XXX_APPID": "TEST_T1234567890"

ios 端说明

uni-app原生插件iOS平台资源,支持iOS平台时必须添加此目录,所有iOS平台相关的资源都放到此目录下。
iOS平台原生插件开发教程参考:https://ask.dcloud.net.cn/article/35415

assets

HBuilderX2.3.4+开始支持配置插件的图片资源文件(xcassets)。
格式如下:

"assets": [  
    "myimage.xcassets"      //使用的xcassets文件列表  
]

"myimage.xcassets"为资源文件(xcassets)路径,相对于插件的ios目录。
注意:引擎本身已经有xcassets资源,插件的xcassets中不能包含已经存在的图片资源,避免冲突
基础图片:"app.imageset"、"AppIcon.appiconset"
视频播放控件(VideoPlayer)模块:"player_back.imageset"、"player_play.imageset"、"player_stop.imageset"、"control_brightness.imageset"、"exitfullscreen.imageset"、"full-screen.imageset、"video_ic_muteoff.imageset"、"video_ic_muteon.imageset"、"video_volume.imageset"

validArchitectures

HBuilderX2.6.0+开始支持配置插件支持的CPU架构类型
格式如下:

"validArchitectures": [  
    "arm64", "arm64e"  
]

支持配置多个值,取值范围:"arm64", "arm64e", "armv7", "armv7s", "x86_64"
不配置此值则认为支持上面所有类型。
云端打包时将会使用所有插件支持类型的交集。

parameters

如果插件使用时需配置参数,如appid、appkey时,可配置parameters字段进行定义,提交云端打包后将会根据配置把数据放到Info.plist中。
parameters下每个节点(josn)定义一个要配置的参数,参数名称为键名,以下定义appid参数为示例:

"parameters": {  
    "ios_appid": {  
        "des": "XXX插件的appid参数",  
        "key": "DC-RichAlert:appid",  
        "value": "TEST_${ios_appid}"  
   }  
}
  • des 参数的描述信息
    可选,在HBuilderX中manifest.json的可视化界面中显示,用于提示插件使用者配置此参数的作用。
  • key 云端打包时原生层使用的键名称
    必填,用于定义参数值在Info.plist文件中保存的键名。
    如果需要多层级嵌套可使用:分割,推荐使用“插件标识:键名”格式,如"DC-RichAlert:appid"。
  • value 云端打包时格式化的键值
    可选,如果需要对插件使用者配置的参数值做一些格式化处理(如添加固定的前缀或后缀)时才需要配置vlue字段。
    其中${ios_appid}表示插件使用者配置的ios_appid参数值;不配置此字段则键值为插件使用者配置的参数值。

插件使用时需在manifest.json的"app-plus"->"nativePlugins"->"插件标识"中配置(最新版HBuilderX已支持可视化配置)
以"DC-RichAlert"插件配置appid参数为示例:

"app-plus": {  
    "nativePlugins": {  
        "DC-RichAlert": {  
            "ios_appid": "T1234567890"  
        }  
    }  
}

按上面的配置规则提交云端打包后将在info.plist中添加以下数据:


<key>DC-RichAlert</key>  
<dict>  
        <key>appid</key>  
        <string>TEST_T1234567890</string>  
</dict>

示例

// package.json 中的配置  
"parameters": {  
                "appkey": {  
                    "des": "请填写Appkey",  
                    "key": "getui:appkey"  
                },  
                "appid":{  
                    "des": "请填写Appid",  
                    "key": "getui:appid"  
                }  
            }

HBuilderX 中可视化页面效果

提交云打包后 iOS 工程 info.plist 中添加的节点,这样就可以通过代码获取 info.plist 中配置的参数

插件配置完成后请作为本地uni-app原生插件提交云端打包进行测试验证插件是否配置正确

更多uni-app原生插件文档参考:uni-app原生插件开发指南

继续阅读 »

新版原生插件开发文档已发布,请移步:https://nativesupport.dcloud.net.cn/

此文档将不再更新维护

uni-app原生插件(native plugin)提交DCloud插件市场需按以下目录格式配置:


上传时压缩为zip格式文件,压缩文件中必须包含目录名称,如下:

package.json

uni-app原生插件描述文件,完整格式如下
注:如果只有一端比如只包含android插件,请把ios节点删除掉,不能直接注释

{  
    "name": "插件名称",  
    "id": "插件标识",  
    "version": "插件版本号",  
    "description": "插件描述信息",  
    "_dp_type":"nativeplugin",  
    "_dp_nativeplugin":{  
        "android": {  
            "plugins": [  
                {  
                    "type": "module|component, 必填, 根据插件类型选择",  
                    "name": "必填, 注册插件的名称, 通常与插件标识一致",  
                    "class": "必填, 注册插件的类名"  
                }  
            ],  
            "hooksClass": "可选, 事件钩子注册类名",  
            "integrateType": "必填, 可取值aar|jar",  
            "dependencies": [  
                "可选, 依赖的库名称"  
            ],  
            "compileOptions": {  //可选,Java编译参数配置  
                "sourceCompatibility": "1.8",  
                "targetCompatibility": "1.8"  
            },  
            "abis": [  
                "可选, 支持的abi类型, 可取值armeabi-v7a|arm64-v8a|x86"  
            ],  
            "minSdkVersion": "可选,支持的Android最低版本,如21",  
            "permissions": [  
                "可选, 要使用的Android权限列表"  
            ],  
            "parameters": {  
                "插件需要配置的参数名称, 如appid": {  
                    "des": "参数描述",  
                    "key": "AndroidManifest.xml中添加meta-data节点的android:name属性值, 如GETUI_APPID",  
                    "placeholder": "build.gradle中添加到manifestPlaceholders中的字段名"  
                }  
            }  
        },  
        "ios": {  
            "plugins": [  
                {  
                    "type": "必填, module|component, 根据插件类型选择",  
                    "name": "必填, 注册插件的名称, 通常与插件标识一致",  
                    "class": "必填, 注册插件的类名"   
                }  
            ],  
            "integrateType": "必填, 可取值framework|library",  
            "hooksClass": "可选, 事件钩子注册类名",  
            "frameworks": [  
                "依赖的系统库(系统库有.framework和.tbd和.dylib类型),和第三方.framework动态库(.framework动态库也需要在这里配置);(第三方 .a 库或 .framework**静态库**直接放到ios根目录即可,不需要配置)"  
            ],  
            "embedFrameworks": [  
                "依赖的.framework动态库,(注意.framework动态库也需要在上面的 frameworks 节点添加配置,同样将动态库.framework文件放到 ios 根目录中)"  
            ],  
            "capabilities": {    // 配置应用的capabilities数据(根据XCode规范分别配置到entitlements和plist文件中)  
                "entitlements": {    // 合并到工程entitlements文件的数据(json格式)  
                },  
                "plists": {    // 合并到工程Info.plist文件的数据(json格式)  
                }  
            },  
            "plists": {    // 自定义配置工程Info.plist文件的数据(json格式),优先级高于capabilities->plists  
            },  
            "resources": [  
                "可选, 插件要使用的资源文件列表,相对于ios目录的路径"  
            ],  
            "assets": [    //HBuilderX2.3.4及以上版本支持  
                "可选,插件要使用的xcassets文件列表,相对于ios目录的路径"  
            ],  
            "privacies": [  
                "可选, 插件使用到的隐私列表,如NSPhotoLibraryUsageDescription"  
            ],  
            "deploymentTarget": "8.0, 可选,支持的iOS最低版本",  
            "validArchitectures": [    // 可选,支持的CPU架构类型  
                "arm64"    //支持多个值,可取值:arm64 arm64e armv7 armv7s x86_64  
            ],  
            "parameters": {  
                "插件需要配置的参数名称, 如appid": {  
                    "des": "参数描述信息",  
                    "key": "参数需要配置到info.plist中的键名, 嵌套时使用:分割,如getui:appid"  
                }  
            }  
        }  
    }  
}

name

插件名称,在插件市场(HBuilderX)中显示的名称。

id

插件标识,插件使用者引用插件时使用的名称,只能使用英文字符、数字、及字符(-、_),且必须以英文字符开头。
推荐使用"%开发者名称%-%插件名称%",如"DC-RichAlert"。

插件标识必须在对应android和ios节点下plugins中进行注册,与name字段值一致

android 端说明

uni-app原生插件Android平台资源,支持Android平台时必须添加此目录,所有Android平台相关的资源都放到此目录下。

  • aar文件,直接放到android目录下,云端打包会自动引用所有的aar文件
  • android\libs目录,所有需要使用的jar文件放到此目录,如果包含so文件,则放到libs下对应cpu类型目录
  • android\assets目录,Android平台需要assets资源
  • android\res目录,Android平台需要的res资源
    Android平台原生插件开发教程参考:https://ask.dcloud.net.cn/article/35416

<a id="dependencies"></a>

dependencies

用于配置插件依赖的仓储库
android插件中集成的第三方SDK 如果是jar或so放入到libs文件夹中即可,无需要配置到dependencies节点下。
gradle配置的第三方sdk 仓储名称方式的配置信息 需要在dependencies节点下填写。
云端打包仅支持从以下仓储下载依赖库,务必注意依赖库已提交到这些仓储中

  • google()
  • maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
  • maven { url 'https://jitpack.io' }
  • jcenter()

app.gradle 配置中dependencies节点信息如下。

dependencies {  
    implementation "com.android.support:recyclerview-v7:25.3.1"  
    implementation "com.android.support:support-v4:25.3.1"  
    implementation "com.android.support:appcompat-v7:25.3.1"  
    implementation "com.alibaba:fastjson:1.1.46.android"  
}

package.json的dependencies节点就需要配置如下信息

dependencies [  
    "com.android.support:recyclerview-v7:25.3.1",  
    "com.android.support:support-v4:25.3.1",  
    "com.android.support:appcompat-v7:25.3.1",  
    "com.alibaba:fastjson:1.1.46.android"  
]

!!!注意V7、V4、fastjson都已默认集成 不需要再次配置。这里仅是示例写法!!!

HBuilderX2.3.8+开始添加更灵活配置,支持源码写dependencies内容
dependencies中的值支持json对象,如下:

dependencies [//内容支持字符串或json格式,支持混写  
    {  
        "id": "com.android.support.test.espresso:espresso-contrib",  //可选,String类型,依赖库标识  
        "source": "implementation('com.android.support.test.espresso:espresso-contrib:2.2.2', {\r\nexclude group: 'com.android.support', module: 'support-v4'\r\n})"   //必选,String类型,依赖库源码  
    }  
]

JSON格式支持以下字段:

  • id
    依赖库的标识,使用多个uni原生插件时,都依赖相同的库时会根据此标识去重,避免产生冲突。
    不配置此值则不做去重处理。
  • source
    依赖库源码,直接将此内容配置到云端打包工程的build.gradle文件的dependencies中。
    只支持写引用公共仓储上的库。
    如上示例,将会在云端打包时将以下内容添加到build.gradle文件的dependencies中:
    implementation('com.android.support.test.espresso:espresso-contrib:2.2.2', {  
    exclude group: 'com.android.support', module: 'support-v4'  
    })

注意:换行符号需要转义为\r\n。

<a id="compileOptions"></a>

compileOptions

HBuilderX2.3.8+开始支持配置云端打包java编译参数。
格式如下:

"compileOptions": {  //可选,Java编译参数配置  
    "sourceCompatibility": "1.8",  
    "targetCompatibility": "1.8"  
},

云端打包使用的jdk版本为1.8,仅支持取值"1.6"、"1.7"、"1.8"。

<a id="abis"></a>

abis

Android平台支持的CPU类型,当插件中包含so库时需要配置插件支持的cpu类型。

"abis": [  
    "armeabi-v7a",  
    "x86"  
],

云端打包内置插件支持以下CPU类型:

  • "armeabi-v7a",7代及以上的ARM处理器(ARM 32位)
  • "arm64-v8a",第8代、64位ARM处理器(ARM 64位)
  • "x86",使用X86架构的处理器(X86 32位)

插件包含so库时至少要支持"armeabi-v7a"类型,从2019年9月开始提交的插件会检测支持CPU类型,不满足要求将无法上线
为了兼容更多的设备和应用市场要求,推荐支持"armeabi-v7a"、"arm64-v8a"、"x86"三种类型。

将aar文件作为zip解压,jni目录下包含的子目录就是其支持的CPU类型

parameters

如果插件使用时需配置参数,如appid、appkey时,可配置parameters字段进行定义,提交云端打包后将会根据配置把数据放到AndroidManifest.xml的meta-data中。
parameters下每个节点定义一个要配置的参数,参数名称为键名,以下为定义appid参数为示例:

"parameters": {  
    "android_appid": {  
        "des": "XXX插件的appid参数",  
        "key": "XXX_APPID",  
        "placeholder": "XXX_APPID",  
        "value": "TEST_${android_appid}"  
   }  
}
  • des 参数的描述信息
    可选,在HBuilderX中manifest.json的可视化界面中显示,用于提示插件使用者配置此参数的作用。
  • key 云端打包时原生层使用的键名称
    可选,与placeholder二选一配置。
    此值为AndroidManifest.xml中添加meta-data节点的android:name属性值,推荐使用“插件标识_键名”格式,如"DC-RichAlert_appid"。
  • placeholder HBuilderX2.5.6+版本支持
    可选,与key二选一配置。
    此值为在build.gradle中添加manifestPlaceholders的键名,为了避免与其它插件冲突推荐使用“插件标识_键名”格式,如"DC-RichAlert_appid"
  • value 云端打包时格式化的键值
    可选,如果需要对插件使用者配置的参数值做一些格式化处理(如添加固定的前缀或后缀)时才需要配置vlue字段。
    其中${android_appid}表示插件使用者配置的android_appid参数值;不配置此字段则键值为插件使用者配置的参数值。

插件使用时需在manifest.json的"app-plus"->"nativePlugins"->"插件标识"中配置(最新版HBuilderX已支持可视化配置)
以"DC-RichAlert"插件配置appid参数为示例:

"app-plus": {  
    "nativePlugins": {  
        "DC-RichAlert": {  
            "android_appid": "T1234567890"  
        }  
    }  
}

按上面的配置规则提交云端打包后将在AndroidManifest.xml中添加以下数据:

<meta-data android:name="XXX_APPID" android:value="TEST_T1234567890"/>

按上面的配置规则提交云端打包后将在manifestPlaceholders中添加以下数据:

"XXX_APPID": "TEST_T1234567890"

ios 端说明

uni-app原生插件iOS平台资源,支持iOS平台时必须添加此目录,所有iOS平台相关的资源都放到此目录下。
iOS平台原生插件开发教程参考:https://ask.dcloud.net.cn/article/35415

assets

HBuilderX2.3.4+开始支持配置插件的图片资源文件(xcassets)。
格式如下:

"assets": [  
    "myimage.xcassets"      //使用的xcassets文件列表  
]

"myimage.xcassets"为资源文件(xcassets)路径,相对于插件的ios目录。
注意:引擎本身已经有xcassets资源,插件的xcassets中不能包含已经存在的图片资源,避免冲突
基础图片:"app.imageset"、"AppIcon.appiconset"
视频播放控件(VideoPlayer)模块:"player_back.imageset"、"player_play.imageset"、"player_stop.imageset"、"control_brightness.imageset"、"exitfullscreen.imageset"、"full-screen.imageset、"video_ic_muteoff.imageset"、"video_ic_muteon.imageset"、"video_volume.imageset"

validArchitectures

HBuilderX2.6.0+开始支持配置插件支持的CPU架构类型
格式如下:

"validArchitectures": [  
    "arm64", "arm64e"  
]

支持配置多个值,取值范围:"arm64", "arm64e", "armv7", "armv7s", "x86_64"
不配置此值则认为支持上面所有类型。
云端打包时将会使用所有插件支持类型的交集。

parameters

如果插件使用时需配置参数,如appid、appkey时,可配置parameters字段进行定义,提交云端打包后将会根据配置把数据放到Info.plist中。
parameters下每个节点(josn)定义一个要配置的参数,参数名称为键名,以下定义appid参数为示例:

"parameters": {  
    "ios_appid": {  
        "des": "XXX插件的appid参数",  
        "key": "DC-RichAlert:appid",  
        "value": "TEST_${ios_appid}"  
   }  
}
  • des 参数的描述信息
    可选,在HBuilderX中manifest.json的可视化界面中显示,用于提示插件使用者配置此参数的作用。
  • key 云端打包时原生层使用的键名称
    必填,用于定义参数值在Info.plist文件中保存的键名。
    如果需要多层级嵌套可使用:分割,推荐使用“插件标识:键名”格式,如"DC-RichAlert:appid"。
  • value 云端打包时格式化的键值
    可选,如果需要对插件使用者配置的参数值做一些格式化处理(如添加固定的前缀或后缀)时才需要配置vlue字段。
    其中${ios_appid}表示插件使用者配置的ios_appid参数值;不配置此字段则键值为插件使用者配置的参数值。

插件使用时需在manifest.json的"app-plus"->"nativePlugins"->"插件标识"中配置(最新版HBuilderX已支持可视化配置)
以"DC-RichAlert"插件配置appid参数为示例:

"app-plus": {  
    "nativePlugins": {  
        "DC-RichAlert": {  
            "ios_appid": "T1234567890"  
        }  
    }  
}

按上面的配置规则提交云端打包后将在info.plist中添加以下数据:


<key>DC-RichAlert</key>  
<dict>  
        <key>appid</key>  
        <string>TEST_T1234567890</string>  
</dict>

示例

// package.json 中的配置  
"parameters": {  
                "appkey": {  
                    "des": "请填写Appkey",  
                    "key": "getui:appkey"  
                },  
                "appid":{  
                    "des": "请填写Appid",  
                    "key": "getui:appid"  
                }  
            }

HBuilderX 中可视化页面效果

提交云打包后 iOS 工程 info.plist 中添加的节点,这样就可以通过代码获取 info.plist 中配置的参数

插件配置完成后请作为本地uni-app原生插件提交云端打包进行测试验证插件是否配置正确

更多uni-app原生插件文档参考:uni-app原生插件开发指南

收起阅读 »

在 uni-app 中使用 nvue 时编译报错的解决方案

weex uniapp

问题现象

在 uni-app 中使用 nvue 开发时,运行到 App 有时若遇到如下的问题:

Uncaught Error: module "common/vendor.js" is not defined  
20:31:58.664  Wed Jan 23 2019 20:33:31 GMT+0800 (CST) Page route 错误  
20:31:58.687  Page[pages/index/index] not found. May be caused by: 1. Forgot to add page route in pages.json. 2. Invoking Page() in async task.  
20:31:58.706  console.groupEnd

引发该问题的原因是,项目中的页面都使用了 nvue 文件。

临时解决办法

新建一个空白的页面,并且这个页面目录下只有同名的 .vue 文件,不要有同名的 .nvue 文件。
也就是说,使用 nvue 时,项目中一个没有 .nvue 文件的页面存在。

如下图所示:

block 页面就是用来占位的,实际应用中并不使用这个页面。

注意,如果是主动新建目录添加的话,pages.json 里面一定要补充 block 页面的配置。

继续阅读 »

问题现象

在 uni-app 中使用 nvue 开发时,运行到 App 有时若遇到如下的问题:

Uncaught Error: module "common/vendor.js" is not defined  
20:31:58.664  Wed Jan 23 2019 20:33:31 GMT+0800 (CST) Page route 错误  
20:31:58.687  Page[pages/index/index] not found. May be caused by: 1. Forgot to add page route in pages.json. 2. Invoking Page() in async task.  
20:31:58.706  console.groupEnd

引发该问题的原因是,项目中的页面都使用了 nvue 文件。

临时解决办法

新建一个空白的页面,并且这个页面目录下只有同名的 .vue 文件,不要有同名的 .nvue 文件。
也就是说,使用 nvue 时,项目中一个没有 .nvue 文件的页面存在。

如下图所示:

block 页面就是用来占位的,实际应用中并不使用这个页面。

注意,如果是主动新建目录添加的话,pages.json 里面一定要补充 block 页面的配置。

收起阅读 »

uni-app原生插件(native plugin)使用说明

插件 nativePlugin uni原生插件 原生插件

新版原生插件开发文档已发布,请移步:https://nativesupport.dcloud.net.cn/

此文档将不再更新维护

过去DCloud的app产品虽然也可以自行扩展原生能力,但文档和接口设计的不太好,也没有云打包原生插件的能力,也没有插件市场。
如今这些问题都解决了。
HBuilderX1.4起,提供了全新的插件开发方式(同weex插件),支持云打包原生插件,插件市场也同步上线。
按以下步骤操作使用原生插件

第一步:购买或下载uni-app原生插件

从HBuilderX1.9.0版本开始,uni原生插件支持设置为免费或收费,为了保护插件开发者权益,收费插件只支持云端打包,不提供插件下载

  • 使用前需先登录uni原生插件市场,在插件详情页中购买,免费插件也可以在插件市场0元购。购买后才能够云端打包使用插件
    购买插件时请选择正确的appid,以及绑定正确包名
  • 对于免费的uni原生插件,也可以先下载到本地再提交云端打包(不推荐)
    详情参考:本地uni-app原生插件提交云端打包

第二步:使用自定义基座打包uni原生插件 (注:请使用真机运行自定义基座)

使用uni原生插件必须先提交云端打包才能生效,购买插件后在应用的manifest.json页面的“App原生插件配置”项下点击“选择云端插件”,选择需要打包的插件:


如果插件已下载到本地,点击“选择本地插件”,选择需要打包的插件
直接云端打包后无法打log,不利于排错,所以一般先打一个自定义基座,把需要的原生插件打到真机运行基座里,然后在本地写代码调用调试。
注意,自定义基座不是正式版,真正发布时,需要再打正式包。使用自定义基座是无法正常升级替换apk的。

第三步:开发调试uni-app原生插件

  • 在vue页面或nvue页面引入这个原生插件。
    使用uni.requireNativePlugin的api,参数为插件的id。
    例如:
    const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert')
  • 根据插件市场的插件介绍页面的文档编写js代码,调用其能力
    注意如果前端代码需要给原生sdk传路径,则需要传手机文件的绝对路径。

第四步:打包发布

使用自定义基座开发调试uni-app原生插件后,不可直接将自定义基座apk作为正式版发布。
应该重新提交云端打包(不能勾选“自定义基座”)生成正式版本。

uni-app原生插件使用常见问题

如果你想自己开发原生插件,参考
uni-app原生插件开发指南
Android:https://ask.dcloud.net.cn/article/35416
iOS:https://ask.dcloud.net.cn/article/35415

更多uni-app原生插件文档参考:uni-app原生插件开发指南

继续阅读 »

新版原生插件开发文档已发布,请移步:https://nativesupport.dcloud.net.cn/

此文档将不再更新维护

过去DCloud的app产品虽然也可以自行扩展原生能力,但文档和接口设计的不太好,也没有云打包原生插件的能力,也没有插件市场。
如今这些问题都解决了。
HBuilderX1.4起,提供了全新的插件开发方式(同weex插件),支持云打包原生插件,插件市场也同步上线。
按以下步骤操作使用原生插件

第一步:购买或下载uni-app原生插件

从HBuilderX1.9.0版本开始,uni原生插件支持设置为免费或收费,为了保护插件开发者权益,收费插件只支持云端打包,不提供插件下载

  • 使用前需先登录uni原生插件市场,在插件详情页中购买,免费插件也可以在插件市场0元购。购买后才能够云端打包使用插件
    购买插件时请选择正确的appid,以及绑定正确包名
  • 对于免费的uni原生插件,也可以先下载到本地再提交云端打包(不推荐)
    详情参考:本地uni-app原生插件提交云端打包

第二步:使用自定义基座打包uni原生插件 (注:请使用真机运行自定义基座)

使用uni原生插件必须先提交云端打包才能生效,购买插件后在应用的manifest.json页面的“App原生插件配置”项下点击“选择云端插件”,选择需要打包的插件:


如果插件已下载到本地,点击“选择本地插件”,选择需要打包的插件
直接云端打包后无法打log,不利于排错,所以一般先打一个自定义基座,把需要的原生插件打到真机运行基座里,然后在本地写代码调用调试。
注意,自定义基座不是正式版,真正发布时,需要再打正式包。使用自定义基座是无法正常升级替换apk的。

第三步:开发调试uni-app原生插件

  • 在vue页面或nvue页面引入这个原生插件。
    使用uni.requireNativePlugin的api,参数为插件的id。
    例如:
    const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert')
  • 根据插件市场的插件介绍页面的文档编写js代码,调用其能力
    注意如果前端代码需要给原生sdk传路径,则需要传手机文件的绝对路径。

第四步:打包发布

使用自定义基座开发调试uni-app原生插件后,不可直接将自定义基座apk作为正式版发布。
应该重新提交云端打包(不能勾选“自定义基座”)生成正式版本。

uni-app原生插件使用常见问题

如果你想自己开发原生插件,参考
uni-app原生插件开发指南
Android:https://ask.dcloud.net.cn/article/35416
iOS:https://ask.dcloud.net.cn/article/35415

更多uni-app原生插件文档参考:uni-app原生插件开发指南

收起阅读 »

uni-app仿淘宝搜索,历史关键词,搜索候选关键词

uniapp

先上效果图,附件在最后。

代码仅供学习参考。
附件真机运行体验效果。

先上效果图,附件在最后。

代码仅供学习参考。
附件真机运行体验效果。

如何从插件市场下载使用组件

组件 插件市场

本文以 badge(数字角标) 为例,说明如何从插件市场下载并导入使用组件。

下载组件

从插件市场 badge详情页,点击“下载”按钮,下载完成后,解压到 uni-app 根目录。

导入组件

假设 page-a.vue 页面需要用到 badge,则在 page-a.vue 的 script 节点下导入 badge 组件,如下:

import uniBadge from "@/components/uni-badge/uni-badge.vue"

定义组件

在 components 选项中定义 badge 组件,如下:

export default {  
    data() {  
        return { /* ... */ }  
    },  
    components: {  
        uniBadge  
    }  
}

若从插件市场下载使用多个组件,则每个组件均需在 components 选项中定义,并以逗号分隔。

使用组件

在 template 节点按照组件使用说明,调用组件并传值,如下:

<uni-badge text="1"></uni-badge>  
<uni-badge text="2" type="success" @click="bindClick"></uni-badge>

完整代码示例如下:

<template>  
    <view>  
        <!-- 页面其它组件 -->  
        <uni-badge text="1"></uni-badge>  
        <uni-badge text="2" type="success" @click="bindClick"></uni-badge>  
        <!-- 页面其它组件 -->  
    </view>  
</template>  
<script>  
    import uniBadge from "@/components/uni-badge/uni-badge.vue"  
    /* import 导入的其它组件 */  

    export default {  
        data() {  
            return { /* ... */ }  
        },  
        components: {  
            uniBadge,  
            /* 其它组件定义 */  
        }  
    }  
</script>
继续阅读 »

本文以 badge(数字角标) 为例,说明如何从插件市场下载并导入使用组件。

下载组件

从插件市场 badge详情页,点击“下载”按钮,下载完成后,解压到 uni-app 根目录。

导入组件

假设 page-a.vue 页面需要用到 badge,则在 page-a.vue 的 script 节点下导入 badge 组件,如下:

import uniBadge from "@/components/uni-badge/uni-badge.vue"

定义组件

在 components 选项中定义 badge 组件,如下:

export default {  
    data() {  
        return { /* ... */ }  
    },  
    components: {  
        uniBadge  
    }  
}

若从插件市场下载使用多个组件,则每个组件均需在 components 选项中定义,并以逗号分隔。

使用组件

在 template 节点按照组件使用说明,调用组件并传值,如下:

<uni-badge text="1"></uni-badge>  
<uni-badge text="2" type="success" @click="bindClick"></uni-badge>

完整代码示例如下:

<template>  
    <view>  
        <!-- 页面其它组件 -->  
        <uni-badge text="1"></uni-badge>  
        <uni-badge text="2" type="success" @click="bindClick"></uni-badge>  
        <!-- 页面其它组件 -->  
    </view>  
</template>  
<script>  
    import uniBadge from "@/components/uni-badge/uni-badge.vue"  
    /* import 导入的其它组件 */  

    export default {  
        data() {  
            return { /* ... */ }  
        },  
        components: {  
            uniBadge,  
            /* 其它组件定义 */  
        }  
    }  
</script>
收起阅读 »

DCloud插件开发指南汇总

插件 插件开发

最新文档已经迁移至:https://uniapp.dcloud.io/plugin/publish.html


以下为过期文档:

DCloud有活跃的插件市场,https://ext.dcloud.net.cn/,并提供了变现、评价等机制。
欢迎开发者为插件市场提供插件。
很多优秀的插件作者,可以做到每月销售数万元的插件。(只有uniCloud插件和原生插件支持付费,其他类型插件不能设价格)

插件作者制作插件时,需注意以下几点:

  • 前端建议使用scss预处理并引用uni.scss中的变量定义,保持各插件风格统一,方便插件使用者通过搭积木的方式开发整体风格一致的App
  • 遵循插件目录规范,其中比较重要的是确定插件ID,详细解释下方。
  • 插件包中不需要包含 unpackage 目录
  • 插件包中不应该包含版本控制相关文件和目录,如 .git,.svn 等。

插件ID(原“插件使用名称”)命名规范:

  1. 格式为:'作者ID-插件名称',示例:'xiaoming-tag',其中作者ID和插件名称只能包含英文、数字
  2. 作者ID由插件作者自定义,不能使用'DCloud'、'uni'等关键字,长度要求至少2位字符
  3. 插件名称需直观表达插件的作用,例如:tag、button等

从HBuilderX 3.1起,新增 uni_modules,它是uni生态的重要模块化方案。详情另见:https://uniapp.dcloud.net.cn/uni_modules

插件市场分多种插件:

前端组件

我们以小明开发的tag组件(插件ID为:xiaoming-tag)为例,上传插件市场时,目录结构要求如下:

为保证代码简洁,上传插件时仅需包含必需的文件及目录。

若组件依赖三方组件,则需将三方组件一起打包上传;假设"xiaoming-tag"依赖小红开发的icon组件(xiaohong-icon),则发布"xiaoming-tag"插件时,目录结构要求如下:

Tips:

  • 通用组件、nvue组件、目录结构要求相同
  • 小程序组件的一级目录,名字需从 components 变更为 wxcomponents ,其它结构要求相同
  • 不能包含根目录的 manifest.json、pages.json、App.vue、main.js 等文件

uni-app前端模板

vue/nvue 页面模板

我们以小明开发的设置模板(xiaoming-setting)为例,上传插件市场时,目录结构要求如下:

若页面模板依赖其它组件,则需将依赖组件一起打包;假设"xiaoming-setting"依赖小红开发的list组件(xiaohong-list),则发布"xiaoming-setting"页面模板时,目录结构要求如下:

Tips:

  • vue 页面模板和 nvue 页面模板目录结构要求相同。
  • 页面模板打包时需要包含 manifest.json、pages.json 等文件。

uni-app前端项目模板

项目模板无特殊要求,注意满足 uni-app 项目目录结构要求即可,详情
Tips:

  • 项目模板打包时不需要包含 unpackage 目录;
  • 项目模板打包时需要包含 manifest.json 文件。manifest.json 里不允许有 appid,包括 DCloud appid 或微信等三方 appid;
  • 如果模板中包含 uniCloud 相关的云函数目录,如 cloudfunctions-aliyun、cloudfunctions-tcb,请选择“uniCloud”->“前后一体项目模板”。如果不使用云函数功能,则应该从插件包中删除 cloudfunctions 相关目录。

JS SDK

开发JS SDK时,对目录结构无特殊要求,仅需将js文件命名为插件ID即可,例如:xiaoming-md5.js

Tips:

  • 不能包含根目录的 manifest.json、pages.json、App.vue、main.js 等文件

原生SDK

原生SDK,即uni原生插件,需使用Andorid/iOS原生环境开发实现,请参考以下教程:

压缩包格式要求:打开zip后根目录需为插件id目录,二级目录是ios、android子目录及package.json,详情参考uni原生插件包格式

HBuilderX插件

HBuilderX插件是安装在HBuilderX工具里的。是编辑器的插件,不是手机App的插件。详细开发教程见:http://hx.dcloud.net.cn/

uniCloud

云函数模板

云函数模板对文件命名没有特殊要求,但制作插件压缩包时,需要注意以下几点:

  • 当模板中包含一个或多个云函数时,不能只在插件中放入云函数目录,而需要完整的从项目根目录开始。如uniCloud/cloudfunctions/cf123。uniCloud可以接受-aliyun或-tcb 后缀(阿里云和腾讯云这两个目录也可以同时存在);
  • 云函数有效的入口文件为 index.js,插件包中必须包含至少一个以此命名的文件。
  • 涉及账户管理的话,请使用uni-id

如果上传付费云函数插件,则必须选择要加密的云函数,否则插件试用者可以通过试用流程无限期使用你的插件而不需要付费。

定义加密云函数,为了与uni_modules统一规范,废弃原encryptlist.json,需在插件根目录下添加package.json,在uni_modules-> encrypt中配置需要加密的文件,如:

{  
    "uni_modules": {  
        "encrypt": [ // 配置要加密的文件,为插件包中真实存在且相对根目录的文件路径,需注意uniCloud目录的后缀需与项目一致  
            "uniCloud-aliyun/cloudfunctions/function/index.js"   
        ],  
    }  
}

encrypt数组中可灵活配置uniCloud/cloudfunctions下云函数及公共模块的js文件,与原encryptlist.json文件配置整个云函数或公共模块相比更加灵活。

定义好要加密的云函数内容后,上传插件,DCloud插件市场会自动加密这些云函数。
当插件用户试用插件时,无法查阅这些云函数的源码,并且只有在试用期内(一般是7天内),这些加密云函数才能在他部署的服务空间上运行,过了试用期这些云函数将自动失效。

即便插件用户购买了插件的普通授权版,也看不到这些加密云函数的源码,但这些云函数可以正常运行在他购买时绑定的服务空间上。且无法上传到其他服务空间。

如果插件作者上传插件时,同时提供了源码授权版,且插件使用者购买了源码授权版,才能拿到插件的所有源码。

若插件作者提供了源码授权版,需及时注意合同待签通知。当意向买方在电子合同签名后,DCloud会短信通知插件作者,提醒插件作者也对该电子合同进行签名。

关于普通授权版和源码授权版的区别,详见:https://ask.dcloud.net.cn/article/38040

从HBuilderX 3.2.0版本开始,当发布云端一体项目模板或云端一体页面模板的付费插件时,前端js文件也支持加密了,设置方式与云函数类似,在uni_modules->encrypt中定义文件路径,如:

{  
    "uni_modules": {  
        "encrypt": [  
            "js_sdk/index.js",  
            "components/demo/demo.js"  
        ],  
    }  
}

目前只支持付费插件的js文件加密,vue及nvue文件无法加密,业务核心逻辑建议写到js中。
如果发布云端一体项目且包含uni_modules时,则不会加密uni_modules目录下的文件,uni_modules下应该做为独立插件发布,分别进行加密配置。

如果你的插件配置包含涉密信息,希望保护这些配置不被上传参考:uni_modules插件上传辅助脚本示例

云端一体页面模板

云端一体页面模板为单页面模板,为了防止导入时与项目现有代码冲突,需注意以下几点命名规范:

  • 必须包含云函数相关目录(uniCloud/cloudfunctions),可以包含js_sdk、pages、components、static等目录
  • 云函数、公共模块命名需要包含“-”
  • js_sdk、components、static等目录下的子目录及文件命名需要包含“-”
  • 不能包含根目录的 manifest.json、App.vue、main.js 等文件

前后一体项目模板

与uni-app前端项目模板目录结构基本一致,但是必须包含uniCloud相关目录(uniCloud-aliyun、uniCloud-tcb)

uniCloud admin 插件

在使用uniCloud admin基础框架后,可以进一步集成插件作者写好的admin插件,以丰富自己的admin系统的功能。
插件作者也可以按此文档提交插件,在插件市场的上传发布页面选择uniCloud 分类的 Admin 插件

因文档较长,请单独参阅:uniCloud admin插件开发指南

DB Schema及验证函数

主要用于提交数据表schema及校验函数,所以必须包含uniCloud-aliyun/database 或 uniCloud-tcb/database目录

注意

  • uni-app原生SDK及web项目两个分类下插件发布后需要审核才会生效。
  • 插件不能自行下架,如需下架请发邮件到service@dcloud.io。
  • 关于插件发布及使用过程中碰到的问题,可加入官方QQ群沟通,群号:442089584

注意压缩包为标准zip格式,不要把rar等其他格式改名为zip

继续阅读 »

最新文档已经迁移至:https://uniapp.dcloud.io/plugin/publish.html


以下为过期文档:

DCloud有活跃的插件市场,https://ext.dcloud.net.cn/,并提供了变现、评价等机制。
欢迎开发者为插件市场提供插件。
很多优秀的插件作者,可以做到每月销售数万元的插件。(只有uniCloud插件和原生插件支持付费,其他类型插件不能设价格)

插件作者制作插件时,需注意以下几点:

  • 前端建议使用scss预处理并引用uni.scss中的变量定义,保持各插件风格统一,方便插件使用者通过搭积木的方式开发整体风格一致的App
  • 遵循插件目录规范,其中比较重要的是确定插件ID,详细解释下方。
  • 插件包中不需要包含 unpackage 目录
  • 插件包中不应该包含版本控制相关文件和目录,如 .git,.svn 等。

插件ID(原“插件使用名称”)命名规范:

  1. 格式为:'作者ID-插件名称',示例:'xiaoming-tag',其中作者ID和插件名称只能包含英文、数字
  2. 作者ID由插件作者自定义,不能使用'DCloud'、'uni'等关键字,长度要求至少2位字符
  3. 插件名称需直观表达插件的作用,例如:tag、button等

从HBuilderX 3.1起,新增 uni_modules,它是uni生态的重要模块化方案。详情另见:https://uniapp.dcloud.net.cn/uni_modules

插件市场分多种插件:

前端组件

我们以小明开发的tag组件(插件ID为:xiaoming-tag)为例,上传插件市场时,目录结构要求如下:

为保证代码简洁,上传插件时仅需包含必需的文件及目录。

若组件依赖三方组件,则需将三方组件一起打包上传;假设"xiaoming-tag"依赖小红开发的icon组件(xiaohong-icon),则发布"xiaoming-tag"插件时,目录结构要求如下:

Tips:

  • 通用组件、nvue组件、目录结构要求相同
  • 小程序组件的一级目录,名字需从 components 变更为 wxcomponents ,其它结构要求相同
  • 不能包含根目录的 manifest.json、pages.json、App.vue、main.js 等文件

uni-app前端模板

vue/nvue 页面模板

我们以小明开发的设置模板(xiaoming-setting)为例,上传插件市场时,目录结构要求如下:

若页面模板依赖其它组件,则需将依赖组件一起打包;假设"xiaoming-setting"依赖小红开发的list组件(xiaohong-list),则发布"xiaoming-setting"页面模板时,目录结构要求如下:

Tips:

  • vue 页面模板和 nvue 页面模板目录结构要求相同。
  • 页面模板打包时需要包含 manifest.json、pages.json 等文件。

uni-app前端项目模板

项目模板无特殊要求,注意满足 uni-app 项目目录结构要求即可,详情
Tips:

  • 项目模板打包时不需要包含 unpackage 目录;
  • 项目模板打包时需要包含 manifest.json 文件。manifest.json 里不允许有 appid,包括 DCloud appid 或微信等三方 appid;
  • 如果模板中包含 uniCloud 相关的云函数目录,如 cloudfunctions-aliyun、cloudfunctions-tcb,请选择“uniCloud”->“前后一体项目模板”。如果不使用云函数功能,则应该从插件包中删除 cloudfunctions 相关目录。

JS SDK

开发JS SDK时,对目录结构无特殊要求,仅需将js文件命名为插件ID即可,例如:xiaoming-md5.js

Tips:

  • 不能包含根目录的 manifest.json、pages.json、App.vue、main.js 等文件

原生SDK

原生SDK,即uni原生插件,需使用Andorid/iOS原生环境开发实现,请参考以下教程:

压缩包格式要求:打开zip后根目录需为插件id目录,二级目录是ios、android子目录及package.json,详情参考uni原生插件包格式

HBuilderX插件

HBuilderX插件是安装在HBuilderX工具里的。是编辑器的插件,不是手机App的插件。详细开发教程见:http://hx.dcloud.net.cn/

uniCloud

云函数模板

云函数模板对文件命名没有特殊要求,但制作插件压缩包时,需要注意以下几点:

  • 当模板中包含一个或多个云函数时,不能只在插件中放入云函数目录,而需要完整的从项目根目录开始。如uniCloud/cloudfunctions/cf123。uniCloud可以接受-aliyun或-tcb 后缀(阿里云和腾讯云这两个目录也可以同时存在);
  • 云函数有效的入口文件为 index.js,插件包中必须包含至少一个以此命名的文件。
  • 涉及账户管理的话,请使用uni-id

如果上传付费云函数插件,则必须选择要加密的云函数,否则插件试用者可以通过试用流程无限期使用你的插件而不需要付费。

定义加密云函数,为了与uni_modules统一规范,废弃原encryptlist.json,需在插件根目录下添加package.json,在uni_modules-> encrypt中配置需要加密的文件,如:

{  
    "uni_modules": {  
        "encrypt": [ // 配置要加密的文件,为插件包中真实存在且相对根目录的文件路径,需注意uniCloud目录的后缀需与项目一致  
            "uniCloud-aliyun/cloudfunctions/function/index.js"   
        ],  
    }  
}

encrypt数组中可灵活配置uniCloud/cloudfunctions下云函数及公共模块的js文件,与原encryptlist.json文件配置整个云函数或公共模块相比更加灵活。

定义好要加密的云函数内容后,上传插件,DCloud插件市场会自动加密这些云函数。
当插件用户试用插件时,无法查阅这些云函数的源码,并且只有在试用期内(一般是7天内),这些加密云函数才能在他部署的服务空间上运行,过了试用期这些云函数将自动失效。

即便插件用户购买了插件的普通授权版,也看不到这些加密云函数的源码,但这些云函数可以正常运行在他购买时绑定的服务空间上。且无法上传到其他服务空间。

如果插件作者上传插件时,同时提供了源码授权版,且插件使用者购买了源码授权版,才能拿到插件的所有源码。

若插件作者提供了源码授权版,需及时注意合同待签通知。当意向买方在电子合同签名后,DCloud会短信通知插件作者,提醒插件作者也对该电子合同进行签名。

关于普通授权版和源码授权版的区别,详见:https://ask.dcloud.net.cn/article/38040

从HBuilderX 3.2.0版本开始,当发布云端一体项目模板或云端一体页面模板的付费插件时,前端js文件也支持加密了,设置方式与云函数类似,在uni_modules->encrypt中定义文件路径,如:

{  
    "uni_modules": {  
        "encrypt": [  
            "js_sdk/index.js",  
            "components/demo/demo.js"  
        ],  
    }  
}

目前只支持付费插件的js文件加密,vue及nvue文件无法加密,业务核心逻辑建议写到js中。
如果发布云端一体项目且包含uni_modules时,则不会加密uni_modules目录下的文件,uni_modules下应该做为独立插件发布,分别进行加密配置。

如果你的插件配置包含涉密信息,希望保护这些配置不被上传参考:uni_modules插件上传辅助脚本示例

云端一体页面模板

云端一体页面模板为单页面模板,为了防止导入时与项目现有代码冲突,需注意以下几点命名规范:

  • 必须包含云函数相关目录(uniCloud/cloudfunctions),可以包含js_sdk、pages、components、static等目录
  • 云函数、公共模块命名需要包含“-”
  • js_sdk、components、static等目录下的子目录及文件命名需要包含“-”
  • 不能包含根目录的 manifest.json、App.vue、main.js 等文件

前后一体项目模板

与uni-app前端项目模板目录结构基本一致,但是必须包含uniCloud相关目录(uniCloud-aliyun、uniCloud-tcb)

uniCloud admin 插件

在使用uniCloud admin基础框架后,可以进一步集成插件作者写好的admin插件,以丰富自己的admin系统的功能。
插件作者也可以按此文档提交插件,在插件市场的上传发布页面选择uniCloud 分类的 Admin 插件

因文档较长,请单独参阅:uniCloud admin插件开发指南

DB Schema及验证函数

主要用于提交数据表schema及校验函数,所以必须包含uniCloud-aliyun/database 或 uniCloud-tcb/database目录

注意

  • uni-app原生SDK及web项目两个分类下插件发布后需要审核才会生效。
  • 插件不能自行下架,如需下架请发邮件到service@dcloud.io。
  • 关于插件发布及使用过程中碰到的问题,可加入官方QQ群沟通,群号:442089584

注意压缩包为标准zip格式,不要把rar等其他格式改名为zip

收起阅读 »

FFmpeg转音频格式为wav

需求:
用有道的语音识别接口,识别手机端的录音,由于有道只支持wav文件的识别,而Android录音格式不包括wav,默认为amr,因此需要把amr文件传到服务器端再用FFmpeg转格式
1.服务器安装FFmpeg
http://www.cnblogs.com/freeweb/p/6897907.html

2.PHP使用FFmpeg
https://blog.csdn.net/a9925/article/details/80334700

我后端是用的thinkPHP,具体步骤是,在项目根目录
1.在 php.ini 中开启这两个函数proc_open proc_get_status

  1. 设置中国全量镜像
    composer config -g repo.packagist composer https://packagist.phpcomposer.com
    3.安装php-ffmpeg
    composer require php-ffmpeg/php-ffmpeg
    4.项目中调用
    在控制器中:
    require 'vendor/autoload.php';
    $path = array(
    'ffmpeg.binaries' => '/monchickey/ffmpeg/bin/ffmpeg',
    'ffprobe.binaries' => '/monchickey/ffmpeg/bin/ffprobe');
    $amr = ‘test.amr’;
    $ff = FFMpeg::create($path);
    $audio = $ff->open($amr);
    $audio->save(new \FFMpeg\Format\Audio\Wav(), 'test.wav');

monchickey/ffmpeg/bin/为FFmpeg的安装路径

继续阅读 »

需求:
用有道的语音识别接口,识别手机端的录音,由于有道只支持wav文件的识别,而Android录音格式不包括wav,默认为amr,因此需要把amr文件传到服务器端再用FFmpeg转格式
1.服务器安装FFmpeg
http://www.cnblogs.com/freeweb/p/6897907.html

2.PHP使用FFmpeg
https://blog.csdn.net/a9925/article/details/80334700

我后端是用的thinkPHP,具体步骤是,在项目根目录
1.在 php.ini 中开启这两个函数proc_open proc_get_status

  1. 设置中国全量镜像
    composer config -g repo.packagist composer https://packagist.phpcomposer.com
    3.安装php-ffmpeg
    composer require php-ffmpeg/php-ffmpeg
    4.项目中调用
    在控制器中:
    require 'vendor/autoload.php';
    $path = array(
    'ffmpeg.binaries' => '/monchickey/ffmpeg/bin/ffmpeg',
    'ffprobe.binaries' => '/monchickey/ffmpeg/bin/ffprobe');
    $amr = ‘test.amr’;
    $ff = FFMpeg::create($path);
    $audio = $ff->open($amr);
    $audio->save(new \FFMpeg\Format\Audio\Wav(), 'test.wav');

monchickey/ffmpeg/bin/为FFmpeg的安装路径

收起阅读 »

uni-app之推送

推送

写这个之前被推送给弄蒙了,因为之前没接触过。。。。下面说一下我摸索来的大致过程:
我用的是个推
1:首先需要去个推官网申请账号;
2:然后点击manifest在AppSDK配置去填写在个推平台创建的应用的appid、appkey、appsecret属性;
3:在App模块权限配置中勾选push
4:如果ios也需要加推送的话需要用个推官网的那个透传的模板
在app.vue中的代码为(第一次写,不太会用)
//监听click事件,用户从消息中心点击触发的
plus.push.addEventListener("click", function (msg) {
//根据payload传递过来的数据,打开一个详情
var payload = msg.payload;
if (payload) {
// payload 按照规范是 Object,但实际推送过来有可能是 String,需要多一步处理;
if (typeof payload === 'string') {
payload = JSON.parse(payload);
}
if (typeof payload === 'object') {
if(payload.url){
setTimeout(function(res){
uni.navigateTo({
url:payload.url
})
},1000)
}
}
}
}, false);

            //监听receive事件  
            plus.push.addEventListener("receive", function (msg) {  
                if (plus.os.name != 'iOS') {  
                    plus.push.createMessage(msg.title,msg.payload);  
                }  
                //根据payload传递过来的数据,打开一个详情  
                var payload;  
                if (msg.payload) {  
                    //如透传消息不符合格式,则“payload”属性为string类型  
                    //这里的示例以json字符串去解析,实际上也可以做字符串匹配  
                    if (typeof (msg.payload) == "string") {  
                        try {  
                            payload = JSON.parse(msg.payload);  
                        } catch (error) {  
                            console.log(error);  
                        }  
                    } else if (typeof (msg.payload) == "object") {  
                        //iOS应用正处于前台运行时收到推送,也触发receive事件,此时payload为json对象  
                        plus.push.createMessage(msg.title,msg.content);  
                    }  
                }  

            }, false);
继续阅读 »

写这个之前被推送给弄蒙了,因为之前没接触过。。。。下面说一下我摸索来的大致过程:
我用的是个推
1:首先需要去个推官网申请账号;
2:然后点击manifest在AppSDK配置去填写在个推平台创建的应用的appid、appkey、appsecret属性;
3:在App模块权限配置中勾选push
4:如果ios也需要加推送的话需要用个推官网的那个透传的模板
在app.vue中的代码为(第一次写,不太会用)
//监听click事件,用户从消息中心点击触发的
plus.push.addEventListener("click", function (msg) {
//根据payload传递过来的数据,打开一个详情
var payload = msg.payload;
if (payload) {
// payload 按照规范是 Object,但实际推送过来有可能是 String,需要多一步处理;
if (typeof payload === 'string') {
payload = JSON.parse(payload);
}
if (typeof payload === 'object') {
if(payload.url){
setTimeout(function(res){
uni.navigateTo({
url:payload.url
})
},1000)
}
}
}
}, false);

            //监听receive事件  
            plus.push.addEventListener("receive", function (msg) {  
                if (plus.os.name != 'iOS') {  
                    plus.push.createMessage(msg.title,msg.payload);  
                }  
                //根据payload传递过来的数据,打开一个详情  
                var payload;  
                if (msg.payload) {  
                    //如透传消息不符合格式,则“payload”属性为string类型  
                    //这里的示例以json字符串去解析,实际上也可以做字符串匹配  
                    if (typeof (msg.payload) == "string") {  
                        try {  
                            payload = JSON.parse(msg.payload);  
                        } catch (error) {  
                            console.log(error);  
                        }  
                    } else if (typeof (msg.payload) == "object") {  
                        //iOS应用正处于前台运行时收到推送,也触发receive事件,此时payload为json对象  
                        plus.push.createMessage(msg.title,msg.content);  
                    }  
                }  

            }, false);
收起阅读 »