HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

hx 启动失败 查看日志提示错误:Cannt find HX Window to activate(解决办法)

无法启动 HBuilder

在文件管理器中打开hx目录

在地址栏输入%appdata%回车; 在此目录下,找到HBuilder X目录

文件删除

进入目录中删除“.lock”文件

重新启动

然后重新启动即可解决hx启动失败 提示“Cannt find HX Window to activate”的解决办法

继续阅读 »

在文件管理器中打开hx目录

在地址栏输入%appdata%回车; 在此目录下,找到HBuilder X目录

文件删除

进入目录中删除“.lock”文件

重新启动

然后重新启动即可解决hx启动失败 提示“Cannt find HX Window to activate”的解决办法

收起阅读 »

采用uniapp+云开发的方式,仿一个小程序,vx:157 023 57828

采用uniapp+云开发的方式,仿一个小程序

采用uniapp+云开发的方式,仿一个小程序

onLoad参数获取

在手机上测试可以获取,打包后无法获取参数什么原因?

在手机上测试可以获取,打包后无法获取参数什么原因?

uniCloud clientDB,使用groupby分组统计,求每个商品的合计金额

{
data: [{
name: "商品1",
amount: 5,
price: 100
},{
name: "商品2",
amount: 5,
price: 200
},{
name: "商品3",
amount: 5,
price: 300
}]
}

#uniCloud clientDB,使用groupby分组统计,求每个商品的合计金额  
const res = await db.collection('orders')  
.groupBy('name')  
.groupField('sum(multiply(amount,price)) as total')  
.get()

返回结果如下

{
data: [{
name: "商品1",
total:500
},{
name: "商品2",
total:1000
},{
name: "商品3",
total:1500
}]
}

继续阅读 »

{
data: [{
name: "商品1",
amount: 5,
price: 100
},{
name: "商品2",
amount: 5,
price: 200
},{
name: "商品3",
amount: 5,
price: 300
}]
}

#uniCloud clientDB,使用groupby分组统计,求每个商品的合计金额  
const res = await db.collection('orders')  
.groupBy('name')  
.groupField('sum(multiply(amount,price)) as total')  
.get()

返回结果如下

{
data: [{
name: "商品1",
total:500
},{
name: "商品2",
total:1000
},{
name: "商品3",
total:1500
}]
}

收起阅读 »

video 组件 高阶晋级

VideoPlayer

video 组件 高阶晋级

前言

本文是为使用了uni-app 框架开发App时 使用video标签 但是播放部分视频有一定特殊需求时的解决方案。
如果现有功能已经满足日常开发,可以忽略本文。

IJKMediaFramework

  • 目前uni-app中 video的实现 是基于ijkplayer基础之上的二次封装, 框架已经设置了一些属性解决常见的问题,例如 seek不准确, http重定向跳转到rstp,https无法播放等问题。

通过 video 标签中的 advanced 可以实现对于一些高级属性的设置,下边是示例

    'format','codec','sws','player' 可以设置四种, 具体设置类型 通过文章所列或者 ijkplayer,ffmpeg 相关资料查询  

    <video :advanced= advanced> </video>  

    advanced = [  
        {  
            "key": "dns_cache_clear",  
            "value": 1,  
            "type": "format",  
        },  
        {  
            "key": "framedrop",  
            "value": 1,  
            "type": "player",  
        },  
        {  
            "key": "videotoolbox",  
            "value": 0,  
            "type": "player",  
        }  
    ]  

uni-app iOS端 video组件的设置

框架默认参数

Key 默认值 注释 所属类型
max-fps 30 最大fps player
framedrop 0 跳帧开关,如果cpu解码能力不足,可以设置成5,否则会引起音视频不同步,也可以通过设置它来跳帧达到倍速播放 player
video-pictq-size 3 暂无 player
videotoolbox 0 1开启 0关闭 硬解码(硬件解码CPU消耗低。软解,更稳定) player
videotoolbox-max-frame-width 960 指定最大宽度 player
enable-accurate-seek 1 某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少 player
auto_convert 0 自动转屏开关 fortmat
reconnect 1 重连次数 fortmat
timeout 30 1000 1000 (超时时间,timeout参数只对http设置有效。若果你用rtmp设置timeout,ijkplayer内部会忽略timeout参数。rtmp的timeout参数含义和http的不一样。) fortmat
user-agent Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app (具体值看真实设备的值) User-Agent fortmat
dns_cache_clear 1 清空DNS,有时因为在APP里面要播放多种类型的视频(如:MP4,直播,直播平台保存的视频,和其他http视频), 有时会造成因为DNS的问题而报10000问题的 fortmat

uni-app Android端 video组件的设置

框架默认参数

Key 默认值 注释 所属类型
max-fps 30 最大fps player
framedrop 5 跳帧开关,如果cpu解码能力不足,可以设置成5,否则会引起音视频不同步,也可以通过设置它来跳帧达到倍速播放 player
mediacodec 0 1开启 0关闭 硬解码(硬件解码更清晰。软解,更稳定) player
enable-accurate-seek 1 某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少 player
skip_loop_filter 0 环路滤波 0/8/16/24/32/48, 增强播放效率,其中48是指'AVDISCARD_ALL', 所有帧都不做环路滤波. codec
user-agent Mozilla/5.0 (Linux; Android 10; MXW-AN00 Build/HONORMXW-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Html5Plus/1.0 (具体值看真实设备的值) User-Agent fortmat
dns_cache_clear 1 清空DNS,有时因为在APP里面要播放多种类型的视频(如:MP4,直播,直播平台保存的视频,和其他http视频), 有时会造成因为DNS的问题而报10000问题的 fortmat

高阶拓展参数

一些可能用到的参数

Key 可能设置的值 注释 所属类型
soundtouch 设置是否开启变调 1开启 0 不开启 player
skip_loop_filter 设置是否开启环路过滤,0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小 codec
analyzemaxduration 100L 设置播放前的最大探测时间 format
analyzeduration 设置播放前的探测时间 1,达到首屏秒开效果 format
probesize 1024*10 播放前的探测Size,默认是1M, 改小一点会出画面更快 format
flush_packets 1 每处理一个packet之后刷新io上下文 format
max-buffer-size 0 最大缓冲大小,单位kb player
packet-buffering 是否开启预缓冲,一般直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验 1开启 0 不开启 player
fflags fastseek 解决m3u8文件拖动问题 比如:一个3个多少小时的音频文件,开始播放几秒中,然后拖动到2小时左右的时间,要loading 10分钟 fortmat

还有一些更多的参数设置 大家可以参考 ffmpeg 和 一些网络文章

注意注意注意

ijkplayer 为开源项目,可以看得到源码,  
由于`iOS`和 `Android` 的差异性,部分属性可能只在一端生效,具体支持的参数,请查看 [ff_ffplay_options.h] (https://github.com/Bilibili/ijkplayer/blob/master/ijkmedia/ijkplayer/ff_ffplay_options.h)  
继续阅读 »

video 组件 高阶晋级

前言

本文是为使用了uni-app 框架开发App时 使用video标签 但是播放部分视频有一定特殊需求时的解决方案。
如果现有功能已经满足日常开发,可以忽略本文。

IJKMediaFramework

  • 目前uni-app中 video的实现 是基于ijkplayer基础之上的二次封装, 框架已经设置了一些属性解决常见的问题,例如 seek不准确, http重定向跳转到rstp,https无法播放等问题。

通过 video 标签中的 advanced 可以实现对于一些高级属性的设置,下边是示例

    'format','codec','sws','player' 可以设置四种, 具体设置类型 通过文章所列或者 ijkplayer,ffmpeg 相关资料查询  

    <video :advanced= advanced> </video>  

    advanced = [  
        {  
            "key": "dns_cache_clear",  
            "value": 1,  
            "type": "format",  
        },  
        {  
            "key": "framedrop",  
            "value": 1,  
            "type": "player",  
        },  
        {  
            "key": "videotoolbox",  
            "value": 0,  
            "type": "player",  
        }  
    ]  

uni-app iOS端 video组件的设置

框架默认参数

Key 默认值 注释 所属类型
max-fps 30 最大fps player
framedrop 0 跳帧开关,如果cpu解码能力不足,可以设置成5,否则会引起音视频不同步,也可以通过设置它来跳帧达到倍速播放 player
video-pictq-size 3 暂无 player
videotoolbox 0 1开启 0关闭 硬解码(硬件解码CPU消耗低。软解,更稳定) player
videotoolbox-max-frame-width 960 指定最大宽度 player
enable-accurate-seek 1 某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少 player
auto_convert 0 自动转屏开关 fortmat
reconnect 1 重连次数 fortmat
timeout 30 1000 1000 (超时时间,timeout参数只对http设置有效。若果你用rtmp设置timeout,ijkplayer内部会忽略timeout参数。rtmp的timeout参数含义和http的不一样。) fortmat
user-agent Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app (具体值看真实设备的值) User-Agent fortmat
dns_cache_clear 1 清空DNS,有时因为在APP里面要播放多种类型的视频(如:MP4,直播,直播平台保存的视频,和其他http视频), 有时会造成因为DNS的问题而报10000问题的 fortmat

uni-app Android端 video组件的设置

框架默认参数

Key 默认值 注释 所属类型
max-fps 30 最大fps player
framedrop 5 跳帧开关,如果cpu解码能力不足,可以设置成5,否则会引起音视频不同步,也可以通过设置它来跳帧达到倍速播放 player
mediacodec 0 1开启 0关闭 硬解码(硬件解码更清晰。软解,更稳定) player
enable-accurate-seek 1 某些视频在SeekTo的时候,会跳回到拖动前的位置,这是因为视频的关键帧的问题,通俗一点就是FFMPEG不兼容,视频压缩过于厉害,seek只支持关键帧,出现这个情况就是原始的视频文件中i 帧比较少 player
skip_loop_filter 0 环路滤波 0/8/16/24/32/48, 增强播放效率,其中48是指'AVDISCARD_ALL', 所有帧都不做环路滤波. codec
user-agent Mozilla/5.0 (Linux; Android 10; MXW-AN00 Build/HONORMXW-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 Html5Plus/1.0 (具体值看真实设备的值) User-Agent fortmat
dns_cache_clear 1 清空DNS,有时因为在APP里面要播放多种类型的视频(如:MP4,直播,直播平台保存的视频,和其他http视频), 有时会造成因为DNS的问题而报10000问题的 fortmat

高阶拓展参数

一些可能用到的参数

Key 可能设置的值 注释 所属类型
soundtouch 设置是否开启变调 1开启 0 不开启 player
skip_loop_filter 设置是否开启环路过滤,0开启,画面质量高,解码开销大,48关闭,画面质量差点,解码开销小 codec
analyzemaxduration 100L 设置播放前的最大探测时间 format
analyzeduration 设置播放前的探测时间 1,达到首屏秒开效果 format
probesize 1024*10 播放前的探测Size,默认是1M, 改小一点会出画面更快 format
flush_packets 1 每处理一个packet之后刷新io上下文 format
max-buffer-size 0 最大缓冲大小,单位kb player
packet-buffering 是否开启预缓冲,一般直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验 1开启 0 不开启 player
fflags fastseek 解决m3u8文件拖动问题 比如:一个3个多少小时的音频文件,开始播放几秒中,然后拖动到2小时左右的时间,要loading 10分钟 fortmat

还有一些更多的参数设置 大家可以参考 ffmpeg 和 一些网络文章

注意注意注意

ijkplayer 为开源项目,可以看得到源码,  
由于`iOS`和 `Android` 的差异性,部分属性可能只在一端生效,具体支持的参数,请查看 [ff_ffplay_options.h] (https://github.com/Bilibili/ijkplayer/blob/master/ijkmedia/ijkplayer/ff_ffplay_options.h)  
收起阅读 »

uniapp h5打开微信小程序

uniapp

官方文档: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62,必须是认证公众号。

  1. 到微信公众号后台配置JS接口安全域名:设置与开发 - 公众号设置 - 功能设置 - JS接口安全域名,写 www.xxx.com
  2. 通过https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=微信公众号APPID&secret=微信公众号APPSECRET 获取Access token
  3. 通过https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi 获取ticket
  4. 签名生成:
    ①拼接string :jsapi_ticket={上面接口获取的ticket}&noncestr={随机字符串}&timestamp={当前时间戳}&url={js接口安全域名(如果后面不加参数要这么写: http://www.xxx.com/ 注意最后面的/ )}
    ②sh1加密string得到signature
    ③以上步骤为后端生成,生成后返回 appId、timestamp、nonceStr、signature给前端。
  5. 前端安装模块 npm install jweixin-module --save
  6. main.js 添加一行代码 Vue.config.ignoredElements.push('wx-open-launch-weapp')
  7. 标签
    <wx-open-launch-weapp id="launch-btn" username="公众号id" path="/pages/index/index.html">  
                <script type="text/wxtag-template">  
                    <style>  
                        .btn {  
                            border-radius: 30px;  
                            width: 300px;  
                            height: 40px;  
                            font-size: 28px;  
                            border: none !important;  
                            color: #FFFFFF;  
                            background:#44ea76;  
                        }  
                    </style>  
                    <button class="btn" type="default">打开小程序</button>  
                </script>  
            </wx-open-launch-weapp>

    js

    import wx from 'jweixin-module';  
    onShow(){  
    wx.config({  
                    debug:true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  
                    appId:'', // 必填,公众号的唯一标识,填自己的!  
                    timestamp: , // 必填,生成签名的时间戳,刚才接口拿到的数据  
                    nonceStr: '', // 必填,生成签名的随机串  
                    signature: '', // 必填,签名  
                    jsApiList: ['wx-open-launch-weapp'],  
                    openTagList: ['wx-open-launch-weapp'] // 跳转小程序时必填  
                });  
    }

    要在js安全域名上并且在真机上访问才有效果,如果没效果或者是有错误的弹窗出现说明wx.config配置不正确,这种方式只能在微信网页里才能用!!

外部浏览器h5打开微信小程序方法:
官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
1.通过https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=微信小程序APPID&secret=微信小程序APPSECRET 获取Access token
2.通过POST https://api.weixin.qq.com/wxa/generatescheme?access_token=ACCESS_TOKEN 获取到URL Scheme

  1. 通过location.href = 'weixin://dl/business/?t=接口取到' 调用就可以。h5好像是要https才能打开~
继续阅读 »

官方文档: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62,必须是认证公众号。

  1. 到微信公众号后台配置JS接口安全域名:设置与开发 - 公众号设置 - 功能设置 - JS接口安全域名,写 www.xxx.com
  2. 通过https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=微信公众号APPID&secret=微信公众号APPSECRET 获取Access token
  3. 通过https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi 获取ticket
  4. 签名生成:
    ①拼接string :jsapi_ticket={上面接口获取的ticket}&noncestr={随机字符串}&timestamp={当前时间戳}&url={js接口安全域名(如果后面不加参数要这么写: http://www.xxx.com/ 注意最后面的/ )}
    ②sh1加密string得到signature
    ③以上步骤为后端生成,生成后返回 appId、timestamp、nonceStr、signature给前端。
  5. 前端安装模块 npm install jweixin-module --save
  6. main.js 添加一行代码 Vue.config.ignoredElements.push('wx-open-launch-weapp')
  7. 标签
    <wx-open-launch-weapp id="launch-btn" username="公众号id" path="/pages/index/index.html">  
                <script type="text/wxtag-template">  
                    <style>  
                        .btn {  
                            border-radius: 30px;  
                            width: 300px;  
                            height: 40px;  
                            font-size: 28px;  
                            border: none !important;  
                            color: #FFFFFF;  
                            background:#44ea76;  
                        }  
                    </style>  
                    <button class="btn" type="default">打开小程序</button>  
                </script>  
            </wx-open-launch-weapp>

    js

    import wx from 'jweixin-module';  
    onShow(){  
    wx.config({  
                    debug:true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  
                    appId:'', // 必填,公众号的唯一标识,填自己的!  
                    timestamp: , // 必填,生成签名的时间戳,刚才接口拿到的数据  
                    nonceStr: '', // 必填,生成签名的随机串  
                    signature: '', // 必填,签名  
                    jsApiList: ['wx-open-launch-weapp'],  
                    openTagList: ['wx-open-launch-weapp'] // 跳转小程序时必填  
                });  
    }

    要在js安全域名上并且在真机上访问才有效果,如果没效果或者是有错误的弹窗出现说明wx.config配置不正确,这种方式只能在微信网页里才能用!!

外部浏览器h5打开微信小程序方法:
官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html
1.通过https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=微信小程序APPID&secret=微信小程序APPSECRET 获取Access token
2.通过POST https://api.weixin.qq.com/wxa/generatescheme?access_token=ACCESS_TOKEN 获取到URL Scheme

  1. 通过location.href = 'weixin://dl/business/?t=接口取到' 调用就可以。h5好像是要https才能打开~
收起阅读 »

nPro 高质量的全端组件与模版库~支持nvue~vue3纯组合式API来袭

vue3 UI nvue

基于nvue的全端组件与模版库

从nvue最开始到现在,从mypUI开源到现在。

我们从最初的磕磕碰碰开始,到第一个开源的nvue组件库mypUI,经历过数次的优化与迭代,经历过众多项目的实践与打磨。21年6月,我们终于放出了超级优秀的nvue组件与模版库:nPro

nPro坚定的理念就是:只需熟悉一次,然后越用越快,越用越好。

我们的目标是囊括各行各业各种场景下的设计和模版。让你能够快速的去实现或者学习自己想要的效果。

nPro只会越来越优秀,现在的价格绝对物超所值:一顿饭钱,不仅获得优秀的技术与良好的性能,更有一群共同进步的朋友。

最后把我经常说的一句话送给大家:

去用,去实现,去完成!

祝大家越来越优秀,发大财!nPro用起来!

教学视频

nPro的整体理解与快速使用

功能与新功能体验

关注视频号:马三又的又,接收新的功能提醒:

部分示范

nPro

小程序体验

nPro小程序

继续阅读 »

基于nvue的全端组件与模版库

从nvue最开始到现在,从mypUI开源到现在。

我们从最初的磕磕碰碰开始,到第一个开源的nvue组件库mypUI,经历过数次的优化与迭代,经历过众多项目的实践与打磨。21年6月,我们终于放出了超级优秀的nvue组件与模版库:nPro

nPro坚定的理念就是:只需熟悉一次,然后越用越快,越用越好。

我们的目标是囊括各行各业各种场景下的设计和模版。让你能够快速的去实现或者学习自己想要的效果。

nPro只会越来越优秀,现在的价格绝对物超所值:一顿饭钱,不仅获得优秀的技术与良好的性能,更有一群共同进步的朋友。

最后把我经常说的一句话送给大家:

去用,去实现,去完成!

祝大家越来越优秀,发大财!nPro用起来!

教学视频

nPro的整体理解与快速使用

功能与新功能体验

关注视频号:马三又的又,接收新的功能提醒:

部分示范

nPro

小程序体验

nPro小程序

收起阅读 »

2021年插件大赛获奖结果

插件大赛

2021年插件大赛圆满结束。

感谢各位插件作者,为提升中国开发者的开发效率,又贡献了大量优秀的轮子。

经过这次大赛:

  • 涌现大量拿来就用的商用项目,云端一体的源码模板。
  • 涌现大量变现利器,除了官方提供的合成游戏、猜歌游戏外,插件作者们还提供了小说阅读App、CPS等权益卡券等众多变现工具。
  • 出现国际化的云端一体商城,让海外的开发者和用户进入DCloud生态。

本次插件大赛最终获奖名单:

  • 特等奖:
    奖品:5万元插件包销 + 旗舰手机1部(iphone 12 5G 或 华为P40 Pro 5G 2选1)+ 插件市场置顶推荐1个月 + HBuilderX预置 + DCloud奖牌
    名额:1名
    贝壳阅读:小说阅读商业级项目,自带激励视频变现。用户端管理端

此外,合作伙伴个推还赞助了30个双肩包、30个马克杯。特、一、二、三等奖的获奖者,每人都会得到一个双肩包和一个马克杯。贡献奖中随机得到上述礼品。

注:以上奖励提及的“包销”,只对付费插件生效。免费插件没有包销奖励。

获奖插件作者须知

  1. 请及时在社区的个人设置中完善资料补充邮寄地址电话等信息。
  2. 如奖品涉及选项(三等奖以上均涉及奖品选择),请发邮件到 bd@dcloud.io,标题为插件大赛奖品选择。请使用插件作者身份对应的邮箱账户发送,在内容中说明你选择的具体奖品。特、一、二、三等奖的获奖者还有奖牌发放,请邮件同时提供获奖作者署名信息进行确认。

更新邮寄地址信息或发送选择奖品的邮件,时间最晚不超过6月15日,过期将视为放弃领奖。

已获奖作者请耐心等待,收集齐全作者快递信息后官方会统一快递奖品。

结语

没有参赛或中奖的开发者不要气馁,下月初(2021年6月),将揭晓uniCloud行业服务商,170万的奖励比本次插件大赛更刺激!​另见:https://ask.dcloud.net.cn/article/38878

期待各位插件作者再接再厉,为大家提供更好的轮子!

也请各位开发者,多多支持优秀的插件作者,多购买或赞赏他们的插件。

继续阅读 »

2021年插件大赛圆满结束。

感谢各位插件作者,为提升中国开发者的开发效率,又贡献了大量优秀的轮子。

经过这次大赛:

  • 涌现大量拿来就用的商用项目,云端一体的源码模板。
  • 涌现大量变现利器,除了官方提供的合成游戏、猜歌游戏外,插件作者们还提供了小说阅读App、CPS等权益卡券等众多变现工具。
  • 出现国际化的云端一体商城,让海外的开发者和用户进入DCloud生态。

本次插件大赛最终获奖名单:

  • 特等奖:
    奖品:5万元插件包销 + 旗舰手机1部(iphone 12 5G 或 华为P40 Pro 5G 2选1)+ 插件市场置顶推荐1个月 + HBuilderX预置 + DCloud奖牌
    名额:1名
    贝壳阅读:小说阅读商业级项目,自带激励视频变现。用户端管理端

此外,合作伙伴个推还赞助了30个双肩包、30个马克杯。特、一、二、三等奖的获奖者,每人都会得到一个双肩包和一个马克杯。贡献奖中随机得到上述礼品。

注:以上奖励提及的“包销”,只对付费插件生效。免费插件没有包销奖励。

获奖插件作者须知

  1. 请及时在社区的个人设置中完善资料补充邮寄地址电话等信息。
  2. 如奖品涉及选项(三等奖以上均涉及奖品选择),请发邮件到 bd@dcloud.io,标题为插件大赛奖品选择。请使用插件作者身份对应的邮箱账户发送,在内容中说明你选择的具体奖品。特、一、二、三等奖的获奖者还有奖牌发放,请邮件同时提供获奖作者署名信息进行确认。

更新邮寄地址信息或发送选择奖品的邮件,时间最晚不超过6月15日,过期将视为放弃领奖。

已获奖作者请耐心等待,收集齐全作者快递信息后官方会统一快递奖品。

结语

没有参赛或中奖的开发者不要气馁,下月初(2021年6月),将揭晓uniCloud行业服务商,170万的奖励比本次插件大赛更刺激!​另见:https://ask.dcloud.net.cn/article/38878

期待各位插件作者再接再厉,为大家提供更好的轮子!

也请各位开发者,多多支持优秀的插件作者,多购买或赞赏他们的插件。

收起阅读 »

【真BUG】官方文档小技巧

文档

今天开始学习插件开发,应该是官方怕我们学会,搞的莫名奇妙,这个官方的demo

! function(root, factory) {    
    if (typeof exports == 'object' && typeof module != 'undefined') {    
        module.exports = factory()    
    } else if (typeof define == 'function' && define.amd) {    
        define(factory)    
    } else {    
        /**    
         * 插件对象直接扩展到 window 对象上    
         * 这个对象的名字,需要自己填写一下。例如:plugintest    
         */    
        var moduleName = 'plugintest';    
        root[moduleName] = factory()    
    }    
}(this, function() {    
    var _BARCODE = 'plugintest';    
    var plugintest = {    
        PluginTestFunction: function(Argus1, Argus2, Argus3, Argus4, successCallback, errorCallback) {    
            var success = typeof successCallback !== 'function' ? null : function(args) {    
                    successCallback(args);    
                },    
                fail = typeof errorCallback !== 'function' ? null : function(code) {    
                    errorCallback(code);    
                };    
            callbackID = plus.bridge.callbackId(success, fail);    

            return plus.bridge.exec(_BARCODE, "PluginTestFunction", [callbackID, Argus1, Argus2, Argus3, Argus4]);    
        },    
        PluginTestFunctionArrayArgu: function(Argus, successCallback, errorCallback) {    
            var success = typeof successCallback !== 'function' ? null : function(args) {    
                    successCallback(args);    
                },    
                fail = typeof errorCallback !== 'function' ? null : function(code) {    
                    errorCallback(code);    
                };    
            callbackID = plus.bridge.callbackId(success, fail);    
            return plus.bridge.exec(_BARCODE, "PluginTestFunctionArrayArgu", [callbackID, Argus]);    
        },    
        PluginTestFunctionSync: function(Argus1, Argus2, Argus3, Argus4) {    
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSync", [Argus1, Argus2, Argus3, Argus4]);    
        },    
        PluginTestFunctionSyncArrayArgu: function(Argus) {    
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSyncArrayArgu", [Argus]);    
        }    
    };    
    return plugintest;    
});

我粘贴复制都跑不起来,研究半天,后面自己写,其实就用了plus.bridge.exec(_BARCODE, "PluginTestFunctionArrayArgu", [callbackID, Argus]); 这一句就可以了,简直扯淡!

继续阅读 »

今天开始学习插件开发,应该是官方怕我们学会,搞的莫名奇妙,这个官方的demo

! function(root, factory) {    
    if (typeof exports == 'object' && typeof module != 'undefined') {    
        module.exports = factory()    
    } else if (typeof define == 'function' && define.amd) {    
        define(factory)    
    } else {    
        /**    
         * 插件对象直接扩展到 window 对象上    
         * 这个对象的名字,需要自己填写一下。例如:plugintest    
         */    
        var moduleName = 'plugintest';    
        root[moduleName] = factory()    
    }    
}(this, function() {    
    var _BARCODE = 'plugintest';    
    var plugintest = {    
        PluginTestFunction: function(Argus1, Argus2, Argus3, Argus4, successCallback, errorCallback) {    
            var success = typeof successCallback !== 'function' ? null : function(args) {    
                    successCallback(args);    
                },    
                fail = typeof errorCallback !== 'function' ? null : function(code) {    
                    errorCallback(code);    
                };    
            callbackID = plus.bridge.callbackId(success, fail);    

            return plus.bridge.exec(_BARCODE, "PluginTestFunction", [callbackID, Argus1, Argus2, Argus3, Argus4]);    
        },    
        PluginTestFunctionArrayArgu: function(Argus, successCallback, errorCallback) {    
            var success = typeof successCallback !== 'function' ? null : function(args) {    
                    successCallback(args);    
                },    
                fail = typeof errorCallback !== 'function' ? null : function(code) {    
                    errorCallback(code);    
                };    
            callbackID = plus.bridge.callbackId(success, fail);    
            return plus.bridge.exec(_BARCODE, "PluginTestFunctionArrayArgu", [callbackID, Argus]);    
        },    
        PluginTestFunctionSync: function(Argus1, Argus2, Argus3, Argus4) {    
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSync", [Argus1, Argus2, Argus3, Argus4]);    
        },    
        PluginTestFunctionSyncArrayArgu: function(Argus) {    
            return plus.bridge.execSync(_BARCODE, "PluginTestFunctionSyncArrayArgu", [Argus]);    
        }    
    };    
    return plugintest;    
});

我粘贴复制都跑不起来,研究半天,后面自己写,其实就用了plus.bridge.exec(_BARCODE, "PluginTestFunctionArrayArgu", [callbackID, Argus]); 这一句就可以了,简直扯淡!

收起阅读 »

Android开机自启应用-离线打包将应用变为Launcher程序

HBuilder X launcher App离线打包 uniapp
最近做一个项目,开始以为app只是一个开机自启动的程序.后来发现其实是需要app完全覆盖设备,即开机就显示自己的app且设备运行期间只能展示自己的app.  
在网上找了一圈想用uniapp暂时是不能实现了,于是就想到了用原生Android中  
<category android:name="android.intent.category.HOME" />  
<category android:name="android.intent.category.DEFAULT" />  

将应用变成launcher程序,结合uniapp通过离线打包实现  

**uniapp端**  
  1. 创建uniapp项目

2.HbuilderX制作自定义基座

Android签名证书生成指南:https://ask.dcloud.net.cn/article/35777

3.获取app-sha1和包名

安装Android包名sha1获取apk:链接: https://pan.baidu.com/s/1kFcJoQQTbJanp1TzoAfRrw 提取码: whyh 复制这段内容后打开百度网盘手机App,操作更方便哦

  1. dcloud开发者中心-配置离线打包key管理


Android端

  1. 创建Android项目


2.导入sdk里面的包
app离线打包sdk下载地址https://nativesupport.dcloud.net.cn/AppDocs/download/android

  1. 创建对应文件夹到对应位置

  1. 将sdk中的assets下的data下的文件放到对应目录下

  1. 修改AndroidManifest.xml

代码:
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:hardwareAccelerated="true"
android:theme="@style/TranslucentTheme"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard"
android:hardwareAccelerated="true"
android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="h56131bcf" />
</intent-filter>
</activity>

    <provider  
        android:authorities="com.kuaikefu.androidlauncher.dc.fileprovider"  
        android:name="io.dcloud.common.util.DCloud_FileProvider"  
        android:exported="false"  
        android:grantUriPermissions="true">  
        <meta-data  
            android:name="android.support.FILE_PROVIDER_PATHS"  
            android:resource="@xml/dcloud_file_provider"/>  
    </provider>  

    <meta-data  
        android:name="dcloud_appkey"  
        android:value="你的开发者中心生成的app key" />  

6.添加对应代码

代码:
plugins {
id 'com.android.application'
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.3"

signingConfigs {  
    config {  
        keyAlias '别名'  
        keyPassword 'keypass'  
        storeFile file('路径')  
        storePassword 'pass'  
        v1SigningEnabled true //兼容v1  
        v2SigningEnabled true //兼容v2  
    }  
}  

defaultConfig {  
    applicationId "uni.UNI20C4F61"  
    minSdkVersion 21  
    targetSdkVersion 30  
    versionCode 1  
    versionName "1.0"  

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"  

    multiDexEnabled true  
    ndk {  
        abiFilters 'armeabi-v7a', 'x86'// , 'arm64-v8a'//, 'x86_64'  
    }  

}  

buildTypes {  
    debug  {  
        signingConfig signingConfigs.config  
        minifyEnabled false  
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
    }  
    release {  
        minifyEnabled false  
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
    }  
}  

aaptOptions {  
    additionalParameters '--auto-add-overlay'  
    ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"  
}  

compileOptions {  
    sourceCompatibility JavaVersion.VERSION_1_8  
    targetCompatibility JavaVersion.VERSION_1_8  
}  

}

dependencies {

implementation 'androidx.appcompat:appcompat:1.1.0'  
implementation 'com.google.android.material:material:1.1.0'  
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'  
testImplementation 'junit:junit:4.+'  
androidTestImplementation 'androidx.test.ext:junit:1.1.1'  
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'  

implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])  
implementation "com.android.support:support-v4:28.0.0"  
implementation "com.android.support:appcompat-v7:28.0.0"  
implementation 'com.android.support:recyclerview-v7:28.0.0'  
implementation 'com.facebook.fresco:fresco:1.13.0'  
implementation "com.facebook.fresco:animated-gif:1.13.0"  
implementation 'com.github.bumptech.glide:glide:4.9.0'  
implementation 'com.alibaba:fastjson:1.1.46.android'  

}
同步一下


7.添加对应代码并同步

代码:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
maven{
url 'https://dl.google.com/dl/android/maven2/'
name 'Google'
}
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"

    // NOTE: Do not place your application dependencies here; they belong  
    // in the individual module build.gradle files  
}  

}

allprojects {
repositories {
google()
maven{
url 'https://dl.google.com/dl/android/maven2/'
name 'Google'
}
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
8.HbuilderX生成本地打包app资源

复制此文件夹(UNI20C4F61)

9.打开Android-studio 在assets下创建apps文件夹 将复制的资源包放到apps文件夹下

10.修改appid

11.调试

最终效果 实现uniapp 通过原生离线打包将应用变为Launcher程序

继续阅读 »
最近做一个项目,开始以为app只是一个开机自启动的程序.后来发现其实是需要app完全覆盖设备,即开机就显示自己的app且设备运行期间只能展示自己的app.  
在网上找了一圈想用uniapp暂时是不能实现了,于是就想到了用原生Android中  
<category android:name="android.intent.category.HOME" />  
<category android:name="android.intent.category.DEFAULT" />  

将应用变成launcher程序,结合uniapp通过离线打包实现  

**uniapp端**  
  1. 创建uniapp项目

2.HbuilderX制作自定义基座

Android签名证书生成指南:https://ask.dcloud.net.cn/article/35777

3.获取app-sha1和包名

安装Android包名sha1获取apk:链接: https://pan.baidu.com/s/1kFcJoQQTbJanp1TzoAfRrw 提取码: whyh 复制这段内容后打开百度网盘手机App,操作更方便哦

  1. dcloud开发者中心-配置离线打包key管理


Android端

  1. 创建Android项目


2.导入sdk里面的包
app离线打包sdk下载地址https://nativesupport.dcloud.net.cn/AppDocs/download/android

  1. 创建对应文件夹到对应位置

  1. 将sdk中的assets下的data下的文件放到对应目录下

  1. 修改AndroidManifest.xml

代码:
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:hardwareAccelerated="true"
android:theme="@style/TranslucentTheme"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard"
android:hardwareAccelerated="true"
android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="h56131bcf" />
</intent-filter>
</activity>

    <provider  
        android:authorities="com.kuaikefu.androidlauncher.dc.fileprovider"  
        android:name="io.dcloud.common.util.DCloud_FileProvider"  
        android:exported="false"  
        android:grantUriPermissions="true">  
        <meta-data  
            android:name="android.support.FILE_PROVIDER_PATHS"  
            android:resource="@xml/dcloud_file_provider"/>  
    </provider>  

    <meta-data  
        android:name="dcloud_appkey"  
        android:value="你的开发者中心生成的app key" />  

6.添加对应代码

代码:
plugins {
id 'com.android.application'
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.3"

signingConfigs {  
    config {  
        keyAlias '别名'  
        keyPassword 'keypass'  
        storeFile file('路径')  
        storePassword 'pass'  
        v1SigningEnabled true //兼容v1  
        v2SigningEnabled true //兼容v2  
    }  
}  

defaultConfig {  
    applicationId "uni.UNI20C4F61"  
    minSdkVersion 21  
    targetSdkVersion 30  
    versionCode 1  
    versionName "1.0"  

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"  

    multiDexEnabled true  
    ndk {  
        abiFilters 'armeabi-v7a', 'x86'// , 'arm64-v8a'//, 'x86_64'  
    }  

}  

buildTypes {  
    debug  {  
        signingConfig signingConfigs.config  
        minifyEnabled false  
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
    }  
    release {  
        minifyEnabled false  
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'  
    }  
}  

aaptOptions {  
    additionalParameters '--auto-add-overlay'  
    ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"  
}  

compileOptions {  
    sourceCompatibility JavaVersion.VERSION_1_8  
    targetCompatibility JavaVersion.VERSION_1_8  
}  

}

dependencies {

implementation 'androidx.appcompat:appcompat:1.1.0'  
implementation 'com.google.android.material:material:1.1.0'  
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'  
testImplementation 'junit:junit:4.+'  
androidTestImplementation 'androidx.test.ext:junit:1.1.1'  
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'  

implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])  
implementation "com.android.support:support-v4:28.0.0"  
implementation "com.android.support:appcompat-v7:28.0.0"  
implementation 'com.android.support:recyclerview-v7:28.0.0'  
implementation 'com.facebook.fresco:fresco:1.13.0'  
implementation "com.facebook.fresco:animated-gif:1.13.0"  
implementation 'com.github.bumptech.glide:glide:4.9.0'  
implementation 'com.alibaba:fastjson:1.1.46.android'  

}
同步一下


7.添加对应代码并同步

代码:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
maven{
url 'https://dl.google.com/dl/android/maven2/'
name 'Google'
}
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"

    // NOTE: Do not place your application dependencies here; they belong  
    // in the individual module build.gradle files  
}  

}

allprojects {
repositories {
google()
maven{
url 'https://dl.google.com/dl/android/maven2/'
name 'Google'
}
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
8.HbuilderX生成本地打包app资源

复制此文件夹(UNI20C4F61)

9.打开Android-studio 在assets下创建apps文件夹 将复制的资源包放到apps文件夹下

10.修改appid

11.调试

最终效果 实现uniapp 通过原生离线打包将应用变为Launcher程序

收起阅读 »

沐融天津海外研发中心成立,招聘Uniapp高手,快到碗里来!!!欢迎投递简历到zhaopin@murongtech.com。

招聘

北京沐融信息科技股份有限公司是全球领先的数字金融IT解决方案提供商,专注于融合互联网技术,为银行、保险、基金
、证券、支付机构、企业金融等金融行业客户提供丰富的软件产品及解决方案。公司总部位于中国北京,在上海、广州、
深圳、天津、肯尼亚等地设有分支机构。

在肯尼亚我们正在为客户打造全业务场景的支付app,对标支付宝,建立小程序生态;欢迎有志于此的朋友加入,一起打造非洲的支付宝;现需要招聘以下人员:

职位:前端开发工程师(中高级)、前端开发经理

职责描述:
1、在uni-app框架下,进行移动多端(iOS、Android、微信小程序)开发;
2、根据产品经理的需求和UI设计进行页面开发、功能开发;
3、负责公司APP的开发、迭代与优化;
4、参与APP研发技术的积累、学习、实践工作;
5、负责公司APP团队人员培养,队伍建设、技术路线发展等(管理岗)

任职要求:
1、3年以上前端开发工作经验,至少两个uniapp项目开发经验;
2、精通前端基本技术,包括HTML、CSS、Javacript 等;
3、精通JSON、XML等通信格式以及基于AJAX请求实现与后台数据交互;
4、熟悉微信生态及微信小程序生态,有完整的微信小程序项目经验;
5、熟悉使用HBuilder IDE编辑器进行开发,并完成打包发布安卓、ios版本app;
6、精通Vue、uni-app框架应用,并能运用uni-app框架完成移动端及小程序开发;
7、大专及以上学历,责任心强,有团队精神,学习能力强

工作地点:天津 河东区远洋国际中心A座29层
简历请投递:zhaopin@murongtech.com

继续阅读 »

北京沐融信息科技股份有限公司是全球领先的数字金融IT解决方案提供商,专注于融合互联网技术,为银行、保险、基金
、证券、支付机构、企业金融等金融行业客户提供丰富的软件产品及解决方案。公司总部位于中国北京,在上海、广州、
深圳、天津、肯尼亚等地设有分支机构。

在肯尼亚我们正在为客户打造全业务场景的支付app,对标支付宝,建立小程序生态;欢迎有志于此的朋友加入,一起打造非洲的支付宝;现需要招聘以下人员:

职位:前端开发工程师(中高级)、前端开发经理

职责描述:
1、在uni-app框架下,进行移动多端(iOS、Android、微信小程序)开发;
2、根据产品经理的需求和UI设计进行页面开发、功能开发;
3、负责公司APP的开发、迭代与优化;
4、参与APP研发技术的积累、学习、实践工作;
5、负责公司APP团队人员培养,队伍建设、技术路线发展等(管理岗)

任职要求:
1、3年以上前端开发工作经验,至少两个uniapp项目开发经验;
2、精通前端基本技术,包括HTML、CSS、Javacript 等;
3、精通JSON、XML等通信格式以及基于AJAX请求实现与后台数据交互;
4、熟悉微信生态及微信小程序生态,有完整的微信小程序项目经验;
5、熟悉使用HBuilder IDE编辑器进行开发,并完成打包发布安卓、ios版本app;
6、精通Vue、uni-app框架应用,并能运用uni-app框架完成移动端及小程序开发;
7、大专及以上学历,责任心强,有团队精神,学习能力强

工作地点:天津 河东区远洋国际中心A座29层
简历请投递:zhaopin@murongtech.com

收起阅读 »

App“必要性”合规,需要这样依照《规定》!

法律科普

国家互联网信息办公室、工业和信息化部、公安部和国家市场监督管理总局(“四部委”)联合发布的《常见类型移动互联网应用程序必要个人信息范围规定》(以下简称“《规定》”)5月1日正式实施。

自2021年3月初《规定》颁布以来,多数企业立即针对《规定》展开自查,力争将业务所涉及的App类型收集的信息限制在“必要信息范围”之内,自查过程中企业会面对怎样的难点?需要重视哪些条款? 此文基于实务,讨论企业依照《规定》完成个人信息保护合规的具体路径。

小程序也要严格遵守《规定》

根据《规定》第二条规定,若企业运营App或小程序,且该App或小程序存在收集用户个人信息行为,则应当遵守《规定》的要求

在实践中,小程序被纳入监管范围之内已经不存在争议,需要注意的是对小程序现有规定标准的准确把握。以微信小程序为例,不少小程序因其形式上作为小程序,相应的隐私保护设计“自行改装”。例如,大多数小程序没有实现传统App常见的交互,常常仅以一条主动勾选的动态链接代替需要获取用户明确同意的弹窗界。

随着《规定》的出台,小程序应对齐传统App的监管标准。从合规角度而言,小程序应立即调整为与传统App完全一致的交互设计方案。例如,需要获取用户明确同意时,小程序不应再继续简化模式,而应配置具体的符合一般要求的弹窗;又如,如果涉及调用可以收集用户个人信息敏感权限的,小程序也应当设置相应的说明窗口,在启用具体功能时获取用户的授权同意。总之,小程序并不能因为其形式上的特殊性而减免其个人信息保护的责任

此外还应注意,小程序作为“应用软件开放平台”的接入方,本身还应遵从平台方的相应规定,向平台方报备涉及个人信息处理的举措及信息。仍以微信小程序为例,某一小程序通过平台报备而向公众公示的数据包括:开发者信息、服务和数据的来源信息(网址)、服务商信息、用户隐私及数据提示等

由于小程序的实际控制者、开发者、运营者可能并非同一主体,填报工作可能由运营者为快速上线而随意完成,导致小程序的公示信息与其实际运营信息存在差距和混淆,最终小程序的个人信息收集方(控制者)未能履行向个人信息主体告知的义务。鉴此,在实践过程中,小程序的实际控制者应在委托其他方开发运营小程序时,在明确约定个人数据处理的数据安全责任之余,还应特别注意协同对平台的申报责任,避免侵犯个人信息主体知情权

理解并明确必要个人信息的范围

《规定》出台对必要个人信息的范围进行了明确。《规定》第三条规定,“本规定所称必要个人信息,是指保障App基本功能服务正常运行所必需的个人信息,缺少该信息App即无法实现基本功能服务。具体是指消费侧用户个人信息,不包括服务供给侧用户个人信息。”据此,必要个人信息应当同时具备以下条件:

(1)是App基本业务功能所必需的个人信息;

(2)是消费侧用户个人信息。

这两个条件在企业实践中是高度关注的研判重点,也是《规定》对常见应用程序基本业务功能和必要个人信息进行划分的初衷。在以往的案例中,如何判断某信息是否是“App基本业务功能所必需的个人信息”,经常是企业关注重点之一。

首先,判断必要个人信息的前提是正确认定App的“基本业务功能”。按照《个人信息安全规范》(GB/T 35273-2020)附录C.2的指导,基本业务功能“应根据个人信息主体选择、使用所提供产品或服务的根本期待和最主要的需求”划定,但实践中并非每个App都具备清晰的设计逻辑。

对于某些探索期的应用程序而言,其设计思路在于尽可能多的命中用户的潜在需求,用户可能基于功能A选择了该产品,也可能基于功能B而选择该产品,其基本功能显然会以用户的主观感受为转移,从而导致必要个人信息的范畴也存在游离。在这种情况下,基本业务功能的确认是否正确,或是否能够存在多个基本功能,成为企业个人信息保护合规判断的重要一环。

确定基本业务功能后,如何判断其“所必需的个人信息”又成为了合规工作的重点。企业需要注意,合规判断并非某单一职能部门有能力作出,比如,法务部门认为在“定位和导航软件”功能下,无需收集用户的设备信息,但是,如果产品设计方从技术角度认为必须收集设备信息确保运营环境安全,则法务和技术部门需要共同根据《规定》做出统一判断。

切实落实对个人信息主体的告知义务

如上所述,必要个人信息作为用户所选择的基本业务功能所必需的个人信息,可以视为符合《个人信息安全规范》规定的“履约必要”条件,从而豁免个人信息控制者获取个人信息主体授权同意的义务,符合《规定》要求的必要个人信息无需征得个人信息主体的授权同意。但是个人信息控制者仍应落实对个人信息主体的告知义务。因此,《隐私政策》中仍应对基于“履约必要”条件收集的个人信息向个人信息主体进行告知

同时,如果基于“履约必要”条件收集的个人信息将用于数据分析并最终用于实现自动化决策、个性化推荐场景时,其目的显然已经超越了履约目的,因此应获取个人信息主体的额外授权同意。出于产品合规的目的,这个授权同意应当在告知个人信息主体必要个人信息范围时一并告知并获得授权同意。

同时,针对因授权同意而获取的个人信息,即便“履约必要”作为合法处理理由之一,仍应赋予其撤销权,且为保障该撤销权不影响基本功能的实现,基于“履约必要”目的和基于数据分析目的而收集的数据应分开表单存储。诸如此类,隐私设计细节,均应在产品设计之初考虑,并落实在《隐私政策》中告知用户。

对标《规定》,“升级”对个人信息和个人敏感信息的表述

《规定》第五条对于39类常见类型App的基本功能和必要个人信息范围以列举形式进行了明示,供企业在设计、投产、复核其自身App的合规情况作为有效对照。

需要注意的是,《规定》对不同类别App个人信息获取范围做了明确,相对以往的规范有了增减,新增表述字段梳理如下

APP类型 新增必要个人信息字段

  • 网上购物类 支付渠道

  • 餐饮外卖类 支付渠道

  • 交通票务类 车次/船次/航班号、席别/舱位等级、座位号(如有)

  • 房屋租售类 面积/户型、期望售价或租金

  • 问诊挂号类 预约挂号的医院和科室

  • 旅游服务类 旅游目的地、旅游时间

  • 酒店服务类 入住和退房时间、入住酒店名称

  • 演出票务类 观演场次、座位号(如有);支付渠道

这些被明确认定为个人信息的表述,几乎都是个人信息中能够反映个人信息主体行踪轨迹、健康状况和财产状况的个人信息,如果按照“一旦泄露、非法提供或滥用可能危害人身和财产安全,极易导致个人名誉、身心健康受到损害或歧视性待遇等”的标准判断,此类信息均足以视为个人敏感信息。

鉴此,企业在个人信息保护合规工作中,需要业务进一步“升级”:

(1)在合规表述中,扩充个人信息和个人敏感信息的字段示例范围;

(2)扩充数据分级分类标准,将能够反映个人信息主体行踪轨迹、健康状况和财产状况的个人信息提高敏感级别。

【作者: 周杨 史蕾 来源:本文由中国网络空间安全协会个人信息保护专家工作组供稿】,声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 邮箱地址:pufa@dcloud.io 。

原文链接

继续阅读 »

国家互联网信息办公室、工业和信息化部、公安部和国家市场监督管理总局(“四部委”)联合发布的《常见类型移动互联网应用程序必要个人信息范围规定》(以下简称“《规定》”)5月1日正式实施。

自2021年3月初《规定》颁布以来,多数企业立即针对《规定》展开自查,力争将业务所涉及的App类型收集的信息限制在“必要信息范围”之内,自查过程中企业会面对怎样的难点?需要重视哪些条款? 此文基于实务,讨论企业依照《规定》完成个人信息保护合规的具体路径。

小程序也要严格遵守《规定》

根据《规定》第二条规定,若企业运营App或小程序,且该App或小程序存在收集用户个人信息行为,则应当遵守《规定》的要求

在实践中,小程序被纳入监管范围之内已经不存在争议,需要注意的是对小程序现有规定标准的准确把握。以微信小程序为例,不少小程序因其形式上作为小程序,相应的隐私保护设计“自行改装”。例如,大多数小程序没有实现传统App常见的交互,常常仅以一条主动勾选的动态链接代替需要获取用户明确同意的弹窗界。

随着《规定》的出台,小程序应对齐传统App的监管标准。从合规角度而言,小程序应立即调整为与传统App完全一致的交互设计方案。例如,需要获取用户明确同意时,小程序不应再继续简化模式,而应配置具体的符合一般要求的弹窗;又如,如果涉及调用可以收集用户个人信息敏感权限的,小程序也应当设置相应的说明窗口,在启用具体功能时获取用户的授权同意。总之,小程序并不能因为其形式上的特殊性而减免其个人信息保护的责任

此外还应注意,小程序作为“应用软件开放平台”的接入方,本身还应遵从平台方的相应规定,向平台方报备涉及个人信息处理的举措及信息。仍以微信小程序为例,某一小程序通过平台报备而向公众公示的数据包括:开发者信息、服务和数据的来源信息(网址)、服务商信息、用户隐私及数据提示等

由于小程序的实际控制者、开发者、运营者可能并非同一主体,填报工作可能由运营者为快速上线而随意完成,导致小程序的公示信息与其实际运营信息存在差距和混淆,最终小程序的个人信息收集方(控制者)未能履行向个人信息主体告知的义务。鉴此,在实践过程中,小程序的实际控制者应在委托其他方开发运营小程序时,在明确约定个人数据处理的数据安全责任之余,还应特别注意协同对平台的申报责任,避免侵犯个人信息主体知情权

理解并明确必要个人信息的范围

《规定》出台对必要个人信息的范围进行了明确。《规定》第三条规定,“本规定所称必要个人信息,是指保障App基本功能服务正常运行所必需的个人信息,缺少该信息App即无法实现基本功能服务。具体是指消费侧用户个人信息,不包括服务供给侧用户个人信息。”据此,必要个人信息应当同时具备以下条件:

(1)是App基本业务功能所必需的个人信息;

(2)是消费侧用户个人信息。

这两个条件在企业实践中是高度关注的研判重点,也是《规定》对常见应用程序基本业务功能和必要个人信息进行划分的初衷。在以往的案例中,如何判断某信息是否是“App基本业务功能所必需的个人信息”,经常是企业关注重点之一。

首先,判断必要个人信息的前提是正确认定App的“基本业务功能”。按照《个人信息安全规范》(GB/T 35273-2020)附录C.2的指导,基本业务功能“应根据个人信息主体选择、使用所提供产品或服务的根本期待和最主要的需求”划定,但实践中并非每个App都具备清晰的设计逻辑。

对于某些探索期的应用程序而言,其设计思路在于尽可能多的命中用户的潜在需求,用户可能基于功能A选择了该产品,也可能基于功能B而选择该产品,其基本功能显然会以用户的主观感受为转移,从而导致必要个人信息的范畴也存在游离。在这种情况下,基本业务功能的确认是否正确,或是否能够存在多个基本功能,成为企业个人信息保护合规判断的重要一环。

确定基本业务功能后,如何判断其“所必需的个人信息”又成为了合规工作的重点。企业需要注意,合规判断并非某单一职能部门有能力作出,比如,法务部门认为在“定位和导航软件”功能下,无需收集用户的设备信息,但是,如果产品设计方从技术角度认为必须收集设备信息确保运营环境安全,则法务和技术部门需要共同根据《规定》做出统一判断。

切实落实对个人信息主体的告知义务

如上所述,必要个人信息作为用户所选择的基本业务功能所必需的个人信息,可以视为符合《个人信息安全规范》规定的“履约必要”条件,从而豁免个人信息控制者获取个人信息主体授权同意的义务,符合《规定》要求的必要个人信息无需征得个人信息主体的授权同意。但是个人信息控制者仍应落实对个人信息主体的告知义务。因此,《隐私政策》中仍应对基于“履约必要”条件收集的个人信息向个人信息主体进行告知

同时,如果基于“履约必要”条件收集的个人信息将用于数据分析并最终用于实现自动化决策、个性化推荐场景时,其目的显然已经超越了履约目的,因此应获取个人信息主体的额外授权同意。出于产品合规的目的,这个授权同意应当在告知个人信息主体必要个人信息范围时一并告知并获得授权同意。

同时,针对因授权同意而获取的个人信息,即便“履约必要”作为合法处理理由之一,仍应赋予其撤销权,且为保障该撤销权不影响基本功能的实现,基于“履约必要”目的和基于数据分析目的而收集的数据应分开表单存储。诸如此类,隐私设计细节,均应在产品设计之初考虑,并落实在《隐私政策》中告知用户。

对标《规定》,“升级”对个人信息和个人敏感信息的表述

《规定》第五条对于39类常见类型App的基本功能和必要个人信息范围以列举形式进行了明示,供企业在设计、投产、复核其自身App的合规情况作为有效对照。

需要注意的是,《规定》对不同类别App个人信息获取范围做了明确,相对以往的规范有了增减,新增表述字段梳理如下

APP类型 新增必要个人信息字段

  • 网上购物类 支付渠道

  • 餐饮外卖类 支付渠道

  • 交通票务类 车次/船次/航班号、席别/舱位等级、座位号(如有)

  • 房屋租售类 面积/户型、期望售价或租金

  • 问诊挂号类 预约挂号的医院和科室

  • 旅游服务类 旅游目的地、旅游时间

  • 酒店服务类 入住和退房时间、入住酒店名称

  • 演出票务类 观演场次、座位号(如有);支付渠道

这些被明确认定为个人信息的表述,几乎都是个人信息中能够反映个人信息主体行踪轨迹、健康状况和财产状况的个人信息,如果按照“一旦泄露、非法提供或滥用可能危害人身和财产安全,极易导致个人名誉、身心健康受到损害或歧视性待遇等”的标准判断,此类信息均足以视为个人敏感信息。

鉴此,企业在个人信息保护合规工作中,需要业务进一步“升级”:

(1)在合规表述中,扩充个人信息和个人敏感信息的字段示例范围;

(2)扩充数据分级分类标准,将能够反映个人信息主体行踪轨迹、健康状况和财产状况的个人信息提高敏感级别。

【作者: 周杨 史蕾 来源:本文由中国网络空间安全协会个人信息保护专家工作组供稿】,声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 邮箱地址:pufa@dcloud.io 。

原文链接

收起阅读 »