HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

Android Studio离线打包(版本更新后配置)

HBuilderX版本更新后,Android Studio 离线打包的配置:

1. 下载官方5+SDK最新版

2. 解压缩到本地

3. 打开文件夹,找到目录下这5个文件

4. 替换原有目录下对应文件

5. 修改dcloud_control.xml中的内容

6. 找到解压缩后 /HBuilder-hello/app/lib 目录下的jar/arr包

7. 替换原有目录/app/libs 下的jar/arr包 注意: 如果项目引入第三方插件,注意替换时,应保留这些插件对应的jar/arr包

8. 找到解压缩后 /HBuilder-hello/app/src/main 目录下的AndroidManifest.xml文件

9. 用编辑器打开后 搜索provider 找到provider标签

10. 与原有项目下的AndroidManifest.xml文件中的 provider标签 进行对比替换即可。

至此,项目更新完成,可以愉快的进行Android离线打包了……

继续阅读 »

HBuilderX版本更新后,Android Studio 离线打包的配置:

1. 下载官方5+SDK最新版

2. 解压缩到本地

3. 打开文件夹,找到目录下这5个文件

4. 替换原有目录下对应文件

5. 修改dcloud_control.xml中的内容

6. 找到解压缩后 /HBuilder-hello/app/lib 目录下的jar/arr包

7. 替换原有目录/app/libs 下的jar/arr包 注意: 如果项目引入第三方插件,注意替换时,应保留这些插件对应的jar/arr包

8. 找到解压缩后 /HBuilder-hello/app/src/main 目录下的AndroidManifest.xml文件

9. 用编辑器打开后 搜索provider 找到provider标签

10. 与原有项目下的AndroidManifest.xml文件中的 provider标签 进行对比替换即可。

至此,项目更新完成,可以愉快的进行Android离线打包了……

收起阅读 »

Linux开发uni-app (deepin 上,ubuntu 同理)

此方案可以在Linux上开发uniapp 但是限制是不能打包APP打包APP还是得在HbuilderX上进行

安装 微信开发者工具

两种安装方式

1、deepin 应用商店 一键安装。(deepin 系统 推荐)
2、安装 wine 并且 安装 wechat_web_devtools

点我查看 微信开发者工具 安装 文档地址

安装uni-app框架

// 1. 全局安装vue-cli  
npm install -g @vue/cli  
// 2. 创建uni-app  
ue create -p dcloudio/uni-preset-vue my-project  
// 3. 选择需要创建的模板类型 跟 HbuilderX 上差不多  
// 4. 进入目录,运行项目  
// 4.1 运行至 H5   
npm run dev:h5  
// 4.1 运行至 微信小程序   
npm run dev:mp-weixin  
// 5. 打包时 将dev换成build即可。

如果用的deepin 一键安装,在应用列表即可找到快捷方式 打开 微信开发者工具。

如果是安装 wechat_web_devtools 则在安装目录下的 bin文件夹 下的 wxdt 直接运行。(记得按照文档上install)

这里有个bug 导入文件时不能选择文件夹 查了很多资料发现在 1811290 版本的时候是可以用的 新的版本不行。

解决方案:先新建项目 选好文件夹 填好项目名称,然后直接切换到 导入项目一栏 即可。

附件:运行截图

继续阅读 »

此方案可以在Linux上开发uniapp 但是限制是不能打包APP打包APP还是得在HbuilderX上进行

安装 微信开发者工具

两种安装方式

1、deepin 应用商店 一键安装。(deepin 系统 推荐)
2、安装 wine 并且 安装 wechat_web_devtools

点我查看 微信开发者工具 安装 文档地址

安装uni-app框架

// 1. 全局安装vue-cli  
npm install -g @vue/cli  
// 2. 创建uni-app  
ue create -p dcloudio/uni-preset-vue my-project  
// 3. 选择需要创建的模板类型 跟 HbuilderX 上差不多  
// 4. 进入目录,运行项目  
// 4.1 运行至 H5   
npm run dev:h5  
// 4.1 运行至 微信小程序   
npm run dev:mp-weixin  
// 5. 打包时 将dev换成build即可。

如果用的deepin 一键安装,在应用列表即可找到快捷方式 打开 微信开发者工具。

如果是安装 wechat_web_devtools 则在安装目录下的 bin文件夹 下的 wxdt 直接运行。(记得按照文档上install)

这里有个bug 导入文件时不能选择文件夹 查了很多资料发现在 1811290 版本的时候是可以用的 新的版本不行。

解决方案:先新建项目 选好文件夹 填好项目名称,然后直接切换到 导入项目一栏 即可。

附件:运行截图

收起阅读 »

适配Android10+设备注意事项

Android Q Android10 Android

名词介绍: Android 10+ 表示android系统版本大于等于10 既包括android 10以及android 11的系统统称

Android 10+ 概述

Android 10系统开始 进一步增强了平台功能,为外部存储设备上的应用和用户数据提供了更好的保护。作为这项工作的一部分,平台引入了进一步的改进,以简化向分区存储的转换。
为了让用户更好地控制自己的文件,保护用户隐私数据,并限制文件混乱情况,Android 11在分区存储基础上限制了应用访问其他应用的文件。

<a id="io"/>

分区存储

先说一下为什么会有分区存储这个机制出现。

在分区存储之前,某些应用中,即使功能很简单,大部分都不需要这么宽泛的权限。
这就使得某些应用程序

1、乱占空间 :各种各样的文件散布在磁盘的各个地方,当用户卸载应用之后,这些被遗弃的文件被滞留在原地,无人管理,占用了磁盘空间,最终结果就会导致磁盘不足
2、随意读取用户的数据
3、随意读取应用的数据

因此分区存储诞生了,限制了过于宽泛的 存储权限。

什么是分区存储?

Google针对外部存储引入了一个新特性,它的名字叫:Scoped Storage,Google官方对它的翻译为分区存储,我们也可以把它叫做沙盒存储。
更明确了空间的归属,也就是对目录有一个更明确的所有权结构。

分区存储是一种安全机制,用于防止应用读取其他应用的数据。

  • 每个应用程序都有自己的存储空间。
  • 应用程序不能翻过自己的目录,去访问公共目录。
  • 应用程序请求的数据都要通过权限检测,不符合要求不会被放行。

分区存储机制下uni-app/5+ 开发者的影响

android 9及以下系统未做分区存储,除其他应用的内部存储空间不可以读写,其他任意存储目录下的资源文件都可以正常读写操作。
android 10仅对targetSdkVersion>=29则会开启分区存储。targetSdkVersion小于29则不会有任何限制与android9及以下同理。
andorid 11强制执行分区存储。不允许应用读写操作非应用沙盒目录和系统公共目录下的资源文件。

dcloud已对分区存储机制做了适配工作。但也增加了开发者对文件目录操作的规则。在分区存储的环境下分出两个可操文件数据目录系统公共目录应用沙盒目录.

系统公共目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等

  • 公共目录的文件在App卸载后,不会删除
  • 通过plus.gallery.pick获取
  • 拥有权限,也能通过路径直接访问

公共目录对照表:

  • Downloads 对应的绝对路径 file:///storage/emulated/0/Download
  • Documents 对应的绝对路径 file:///storage/emulated/0/Documents
  • Pictures 对应的绝对路径 file:///storage/emulated/0/Pictures
  • DCIM 对应的绝对路径 file:///storage/emulated/0/DCIM
  • Movies 对应的绝对路径 file:///storage/emulated/0/Movies
  • Music 对应的绝对路径 file:///storage/emulated/0/Music
  • Ringtones 对应的绝对路径 file:///storage/emulated/0/Ringtones

系统公共目录缺陷:

  • 系统公共目录仅支持读取媒体文件 如:音频文件、视频文件、图片文件。其他类型文件不支持!!!!
  • 系统公共目录下创建的文件是公用的,你需要确保你的文件命名是惟一的。否则会出现名称对应不上的问题。多数重命名会文件名尾部(i++)处理
  • 系统公共目录不可随意删减。该文件谁创建的谁才有权限删除修改。如果不是当前应用创建的文件是无权权限删改的。
  • 系统公共目录删减文件会被系统认为恶意操作。将会弹通知栏。告诫手机用户当前XXX应用删除了什么文件。

系统公共目录地址的获取来源是哪里:

这里多数是通过plus.gallery.pick获取到的媒体文件。如图片视频等。多数是DCIM、Pictures、Movies等。其他Ringtones、Documents仅提供绝对路径让开发者对比,实际业务中可能并不会获取到相关路径目录的。

目前业务逻辑会用到系统公共目录多数为分享。需要将图片等资源拷贝到系统公共目录下。别的三方应用才有权读取该文件。进行操作业务逻辑。

应用沙盒目录(应用专属目录)

  • 应用沙盒目录只能自己直接访问
  • App卸载,数据会清除。

应用沙盒目录分为:

  • 内部存储空间目录

    • plus.io.PRIVATE_WWW 对应绝对路径 file:///data/user/0/%PACKAGENAME%/files/apps/%APPID%/www

    • plus.io.PRIVATE_DOC 对应绝对路径 file:///data/user/0/%PACKAGENAME%/files/apps/%APPID%/doc

  • 外部存储空间目录

    • plus.io.PUBLIC_DOCUMENTS 对应绝对路径 file:///storage/emulated/0/Android/data/%PACKAGENAME%/.%APPID%/documents

    • plus.io.PUBLIC_DOWNLOADS 对应绝对路径 file:///storage/emulated/0/Android/data/%PACKAGENAME%/.%APPID%/downloads

具体请参考文档

以下是针对分区存储机制作出文件操作目录限制的5+API:

以上API设置了不支持的目录部分会返回code =15的错误信息!,部分会返回执行失败的错误回调具体以API为准!

建议

可预见的未来android系统的更新将会对存储数据操作更加严格。推荐广大开发者文件数据操作都在应用本身的沙盒目录下完成。减少未来不必要的适配工作。相对的你的应用也会更加安全可靠。

扩展问题:

Q:分区存储 我的应用那些需要改动?

A: 目前应用多数与文件操作数据都已适配。用户只需关注部分API操作的文件路径是否符合目录限制规则。非应用沙盒目录或非系统公共目录请及时修改或增加判断调整业务逻辑。

Q:我是不是只要targetSdkVersion不设置>=29就可以了?

A: 不是在android11的设备已经强制开启分区存储机制。您必须做出适配。否则在android11的设备上无法正常运行。

Q:我是不是可以将所以之前应用的特殊文件都放入到系统公共目录下不就行了。之后也可以随意操作不需要非要在应用沙盒目录操作文件呀。

A: 首先不推荐这样操作的。这样会导致功系统公共目录下的文件激增导致多应用做操出现的文件名称冲突等问题。`系统公共目录还有个明显缺陷就是不可以随意删除、修改。都会被系统判断为恶意删减或无权限修改。造成业务逻辑错误。

设备位置

推出新的用户选项;只有在前台使用您的应用时,该选项才允许访问设备位置信息。

Android 10开始中如果应用需要在后台时也获得用户位置,则需要申请后台定位权限,uni-app/5+应用会默认申请该权限,其表现为:
targetSdkVersion>=29,用户同意定位权限后,再次弹窗申请后台定位权限。
targetSdkVersion<29,申请定位权限弹窗中会增加“始终允许”选项。

后台应用启动

针对在没有用户互动的情况下从后台启动活动的新限制。

硬件标识符

对设备硬件标识符(如 IMEI、序列号、MAC 和类似数据)访问权限的新限制。
为保护用户隐私,Android 10开始将不会开放众多可以确定设备的唯一标识。因此Android 10+设备中plus.device.getInfo返回的imei、uuid将会为空。

摄像头和连接性

针对完整摄像头元数据的访问权限实施了新限制,并且现在许多连接工作流都需要精确位置权限。

Android 10+新特性官方说明:https://developer.android.google.cn/preview/privacy

继续阅读 »

名词介绍: Android 10+ 表示android系统版本大于等于10 既包括android 10以及android 11的系统统称

Android 10+ 概述

Android 10系统开始 进一步增强了平台功能,为外部存储设备上的应用和用户数据提供了更好的保护。作为这项工作的一部分,平台引入了进一步的改进,以简化向分区存储的转换。
为了让用户更好地控制自己的文件,保护用户隐私数据,并限制文件混乱情况,Android 11在分区存储基础上限制了应用访问其他应用的文件。

<a id="io"/>

分区存储

先说一下为什么会有分区存储这个机制出现。

在分区存储之前,某些应用中,即使功能很简单,大部分都不需要这么宽泛的权限。
这就使得某些应用程序

1、乱占空间 :各种各样的文件散布在磁盘的各个地方,当用户卸载应用之后,这些被遗弃的文件被滞留在原地,无人管理,占用了磁盘空间,最终结果就会导致磁盘不足
2、随意读取用户的数据
3、随意读取应用的数据

因此分区存储诞生了,限制了过于宽泛的 存储权限。

什么是分区存储?

Google针对外部存储引入了一个新特性,它的名字叫:Scoped Storage,Google官方对它的翻译为分区存储,我们也可以把它叫做沙盒存储。
更明确了空间的归属,也就是对目录有一个更明确的所有权结构。

分区存储是一种安全机制,用于防止应用读取其他应用的数据。

  • 每个应用程序都有自己的存储空间。
  • 应用程序不能翻过自己的目录,去访问公共目录。
  • 应用程序请求的数据都要通过权限检测,不符合要求不会被放行。

分区存储机制下uni-app/5+ 开发者的影响

android 9及以下系统未做分区存储,除其他应用的内部存储空间不可以读写,其他任意存储目录下的资源文件都可以正常读写操作。
android 10仅对targetSdkVersion>=29则会开启分区存储。targetSdkVersion小于29则不会有任何限制与android9及以下同理。
andorid 11强制执行分区存储。不允许应用读写操作非应用沙盒目录和系统公共目录下的资源文件。

dcloud已对分区存储机制做了适配工作。但也增加了开发者对文件目录操作的规则。在分区存储的环境下分出两个可操文件数据目录系统公共目录应用沙盒目录.

系统公共目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等

  • 公共目录的文件在App卸载后,不会删除
  • 通过plus.gallery.pick获取
  • 拥有权限,也能通过路径直接访问

公共目录对照表:

  • Downloads 对应的绝对路径 file:///storage/emulated/0/Download
  • Documents 对应的绝对路径 file:///storage/emulated/0/Documents
  • Pictures 对应的绝对路径 file:///storage/emulated/0/Pictures
  • DCIM 对应的绝对路径 file:///storage/emulated/0/DCIM
  • Movies 对应的绝对路径 file:///storage/emulated/0/Movies
  • Music 对应的绝对路径 file:///storage/emulated/0/Music
  • Ringtones 对应的绝对路径 file:///storage/emulated/0/Ringtones

系统公共目录缺陷:

  • 系统公共目录仅支持读取媒体文件 如:音频文件、视频文件、图片文件。其他类型文件不支持!!!!
  • 系统公共目录下创建的文件是公用的,你需要确保你的文件命名是惟一的。否则会出现名称对应不上的问题。多数重命名会文件名尾部(i++)处理
  • 系统公共目录不可随意删减。该文件谁创建的谁才有权限删除修改。如果不是当前应用创建的文件是无权权限删改的。
  • 系统公共目录删减文件会被系统认为恶意操作。将会弹通知栏。告诫手机用户当前XXX应用删除了什么文件。

系统公共目录地址的获取来源是哪里:

这里多数是通过plus.gallery.pick获取到的媒体文件。如图片视频等。多数是DCIM、Pictures、Movies等。其他Ringtones、Documents仅提供绝对路径让开发者对比,实际业务中可能并不会获取到相关路径目录的。

目前业务逻辑会用到系统公共目录多数为分享。需要将图片等资源拷贝到系统公共目录下。别的三方应用才有权读取该文件。进行操作业务逻辑。

应用沙盒目录(应用专属目录)

  • 应用沙盒目录只能自己直接访问
  • App卸载,数据会清除。

应用沙盒目录分为:

  • 内部存储空间目录

    • plus.io.PRIVATE_WWW 对应绝对路径 file:///data/user/0/%PACKAGENAME%/files/apps/%APPID%/www

    • plus.io.PRIVATE_DOC 对应绝对路径 file:///data/user/0/%PACKAGENAME%/files/apps/%APPID%/doc

  • 外部存储空间目录

    • plus.io.PUBLIC_DOCUMENTS 对应绝对路径 file:///storage/emulated/0/Android/data/%PACKAGENAME%/.%APPID%/documents

    • plus.io.PUBLIC_DOWNLOADS 对应绝对路径 file:///storage/emulated/0/Android/data/%PACKAGENAME%/.%APPID%/downloads

具体请参考文档

以下是针对分区存储机制作出文件操作目录限制的5+API:

以上API设置了不支持的目录部分会返回code =15的错误信息!,部分会返回执行失败的错误回调具体以API为准!

建议

可预见的未来android系统的更新将会对存储数据操作更加严格。推荐广大开发者文件数据操作都在应用本身的沙盒目录下完成。减少未来不必要的适配工作。相对的你的应用也会更加安全可靠。

扩展问题:

Q:分区存储 我的应用那些需要改动?

A: 目前应用多数与文件操作数据都已适配。用户只需关注部分API操作的文件路径是否符合目录限制规则。非应用沙盒目录或非系统公共目录请及时修改或增加判断调整业务逻辑。

Q:我是不是只要targetSdkVersion不设置>=29就可以了?

A: 不是在android11的设备已经强制开启分区存储机制。您必须做出适配。否则在android11的设备上无法正常运行。

Q:我是不是可以将所以之前应用的特殊文件都放入到系统公共目录下不就行了。之后也可以随意操作不需要非要在应用沙盒目录操作文件呀。

A: 首先不推荐这样操作的。这样会导致功系统公共目录下的文件激增导致多应用做操出现的文件名称冲突等问题。`系统公共目录还有个明显缺陷就是不可以随意删除、修改。都会被系统判断为恶意删减或无权限修改。造成业务逻辑错误。

设备位置

推出新的用户选项;只有在前台使用您的应用时,该选项才允许访问设备位置信息。

Android 10开始中如果应用需要在后台时也获得用户位置,则需要申请后台定位权限,uni-app/5+应用会默认申请该权限,其表现为:
targetSdkVersion>=29,用户同意定位权限后,再次弹窗申请后台定位权限。
targetSdkVersion<29,申请定位权限弹窗中会增加“始终允许”选项。

后台应用启动

针对在没有用户互动的情况下从后台启动活动的新限制。

硬件标识符

对设备硬件标识符(如 IMEI、序列号、MAC 和类似数据)访问权限的新限制。
为保护用户隐私,Android 10开始将不会开放众多可以确定设备的唯一标识。因此Android 10+设备中plus.device.getInfo返回的imei、uuid将会为空。

摄像头和连接性

针对完整摄像头元数据的访问权限实施了新限制,并且现在许多连接工作流都需要精确位置权限。

Android 10+新特性官方说明:https://developer.android.google.cn/preview/privacy

收起阅读 »

基于mui+vue框架的跨平台客户端app---购物商城

Vue

涉及到知识点:

  • vue.js
  • 首页底部Tab
  • banner广告
  • 沉浸式状态栏
  • 分类顶部切换的slider
  • 图片预览并保存到相册
  • 拍照、扫码、选择本地文件
  • 侧滑栏
  • 搜索列表页两层侧滑栏筛选
  • 上拉刷新下拉加载
  • 登录、退出逻辑处理

主要功能点:
首页商品展示,商品分类,搜索列表,商品详情,购物车,下订单,个人中心,我的订单/退单,收货地址管理

示例图片

常见问题

  • 首页底部的Tab
    html页面
<nav class="mui-bar mui-bar-tab footerBar">  
    <a id="defaultTab" class="mui-tab-item ft-tab-item mui-active" href="home.html">  
        <span class=" mui-icon iconfont icon-m-ao"></span>  
        <span class="mui-tab-label">首页</span>  
    </a>  
    <a id="tab1" class="mui-tab-item ft-tab-item" href="classify.html">  
        <span class="mui-icon iconfont icon-m-am"></span>  
        <span class="mui-tab-label">分类</span>  
    </a>  
    <a id="tab2" class="mui-tab-item ft-tab-item" href="cart.html">  
        <span class="mui-icon iconfont icon-m-y"></span>  
        <span class="mui-tab-label">购物车</span>  
    </a>  
    <a id="tab3" class="mui-tab-item ft-tab-item" href="my.html">  
        <span class="mui-icon iconfont icon-m-aq"></span>  
        <span class="mui-tab-label">我的</span>  
    </a>  
</nav>

js代码

//底部选项卡切换跳转  
(function jumpPage() {  
    //跳转页面  
    var subpages = ['view/home/home.html', 'view/home/classify.html', 'view/home/cart.html', 'view/home/my.html'];  
    var ids = ['home.html', 'classify.html', 'cart.html', 'my.html'];  
    var aniShow = {};  
    //创建子页面,首个选项卡页面显示,其它均隐藏;  
    mui.plusReady(function() {  
        plus.screen.lockOrientation("portrait-primary");   
        var subpage_style = {  
            top: '0px',  
            bottom: '51px'  
        };  
        //设置bottom绝对位置  
        //iphoneX中出现遮挡底部tab现象,采用js判断屏幕大小方式改变bottom值  
        //isIPhoneX() 要在plusReady后调用  
        if (isIPhoneX()) {  
            subpage_style = {  
                top: '0px',  
                bottom: '88px', //34px  
                styles: {  
                    "render": "always",  
                }  
            };  
        }  
        var self = plus.webview.currentWebview();  
        for (var i = 0; i < 4; i++) {  
            var temp = {};  
            var sub = plus.webview.create(subpages[i], ids[i], subpage_style);  
            if (i > 0) {  
                sub.hide();  
            } else {  
                temp[ids[i]] = "true";  
                mui.extend(aniShow, temp);  
            }  
            self.append(sub);  
        }  
    });  
    //当前激活选项  
    var activeTab = ids[0];  

    //选项卡点击事件  
    mui('.mui-bar-tab').on('tap', 'a', function(e) {  
        e.preventDefault();  
        var targetTab = this.getAttribute('href');  
        if (targetTab == activeTab) {  
            return;  
        }  
        //显示目标选项卡  
        //若为iOS平台或非首次显示,则直接显示  
        if (mui.os.ios || aniShow[targetTab]) {  
            plus.webview.show(targetTab);  
        } else {  
            //否则,使用fade-in动画,且保存变量  
            var temp = {};  
            temp[targetTab] = "true";  
            mui.extend(aniShow, temp);  
            plus.webview.show(targetTab, "fade-in", 300);  
        }  
        //隐藏当前;  
        plus.webview.hide(activeTab);  
        //更改当前活跃的选项卡  
        activeTab = targetTab;  
    });  
})()  

注意iphoneX中出现遮挡底部tab现象,采用js判断屏幕大小方式改变bottom值,isIPhoneX(),isIPhoneX() 要在plusReady后调用。

  • 沉浸式状态栏

1.在manifest.json文件,切换到代码视图,在plus -> statusbar 下添加immersed节点并设置值为true

"statusbar" : {  
    "immersed" : true  
},

2.设置了沉浸式状态栏后,状态栏的高度变为0,如图所示
https://github.com/gs-wenbing/mui-mall/blob/master/img/show/status1.jpg
输入框把状态挡住了,这时候需要重写mui.css或者mui.min.css样式表,在样式表底部添加如下一段样式

*解决沉寖式状态栏导致导航栏高度少20px的问题*/  
.mui-bar-nav {  
    height: 64px;  
    padding-top: 22px;  
}  

.mui-bar-nav ~ .mui-content  
{  
    padding-top: 64px;  
}  

.mui-bar-nav ~ .mui-content .mui-pull-top-pocket  
{  
    top: 64px;  
}  

.mui-bar-nav ~ .mui-content.mui-scroll-wrapper .mui-scrollbar-vertical  
{  
    top: 64px;  
}  

.mui-bar-nav ~ .mui-content .mui-slider.mui-fullscreen  
{  
    top: 64px;  
}

显示效果如图
https://github.com/gs-wenbing/mui-mall/blob/master/img/show/status2.jpg
注意:以上操作后Android沉浸式状态就完成了,但是IOS还需在distribute节点下的apple节点下添加

"UIReserveStatusbarOffset" : false

本以为沉浸式状态栏就完成了,结果老板iPhoneX手机显示有问题,于是又单独适配iPhoneX,具体操作:
在mui.js或者mui.min.js中底部添加如下一段代码

/**  
 * 适配iPhone X 系列手机的导航栏(包括状态栏)  
 */  
mui.plusReady(function(){  
    if(plus.navigator.isImmersedStatusbar() && isIPhoneX()){  
        //.mui-bar-nav  
        var nav = document.querySelector(".mui-bar-nav");  
        if(nav){  
            nav.style.cssText="height:88px; padding-top: 44px;";  
        } else {  
            return;  
        }  
        //.mui-bar-nav ~ .mui-content  
        var content = document.querySelector(".mui-content");  
        if (content) {  
            content.style.paddingTop = "88px";  
        } else {  
            return;  
        }  
        //.mui-bar-nav ~ .mui-content .mui-pull-top-pocket  
        var pullTopPocket_Arr = content.querySelectorAll(".mui-pull-top-pocket");  
        if (pullTopPocket_Arr) {  
            pullTopPocket_Arr.forEach(function(value){  
                value.style.top = "88px";  
            });  
        }  
        //.mui-bar-nav ~ .mui-content.mui-scroll-wrapper .mui-scrollbar-vertical  
        var scrollbarVertical = document.querySelector(".mui-content.mui-scroll-wrapper .mui-scrollbar-vertical");  
        if (scrollbarVertical) {  
            scrollbarVertical.style.top = "88px";  
        }  
        //.mui-bar-nav ~ .mui-content .mui-slider.mui-fullscreen  
        var slider_fullscreen_Arr = content.querySelectorAll(".mui-content .mui-slider.mui-fullscreen");  
        if (slider_fullscreen_Arr) {  
            slider_fullscreen_Arr.forEach(function(value){  
                value.style.top = "88px";  
            });  
        }  
    }  
});  

/**  
 * 判断是否为iPhone X 系列机型  
 */  
function isIPhoneX(){  
    if(plus.device.model.indexOf('iPhone') > -1 && screen.height >= 812){  
        return true;  
    }else{  
        return false;  
    }  
}
  • 标题栏在IOS上存在的问题
    原生标题栏
var styles = { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置  
    titleNView: { // 窗口的标题栏控件  
        titleText: title, // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题  
        titleColor: "#FFFFFF", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"  
        backgroundColor: "#E60012", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"  
        autoBackButton: true  
    }  
}  
plus.webview.create(url, id, styles, extras);

1.mui原生标题栏,假如titleColor的值为小写(#ffffff)的话,在IOS上不显示标题,必须要大写(#FFFFFF)才显示,亲测<br>
2.非原生标题栏,假如页面中有输入框的话,软键盘弹出,IOS上会把标题栏顶上去,因为ios弹出软键盘的时候,webview的高度没有变化导致超出屏幕范围,
而plus这时候又会自动把header的 position:fixed 属性设置为 position:relative,header就跟着滚动了。在mui社区找到一个的解决方案:

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

plus.webview.currentWebview().setStyle({    
    softinputMode: "adjustResize"  // 弹出软键盘时自动改变webview的高度    
});   

html, body {    
    height: 100%;    
    margin: 0px;    
    padding: 0px;    
    overflow: hidden;    
    -webkit-touch-callout: none;    
    -webkit-user-select: none;    
}    

.mui-content {    
    height: 100%;    
    overflow: auto;     
}   

这样会解决IOS标题栏顶上去的问题,但是这样处理后,页面打开标题栏会有抖动,虽然很短暂,但是看着不爽,有更好的方案可以联系我(QQ742330561)

具体的demo地址: https://github.com/gs-wenbing/mui-mall
如果对您有帮助,您可以"Star" 支持一下 谢谢! ^^

继续阅读 »

涉及到知识点:

  • vue.js
  • 首页底部Tab
  • banner广告
  • 沉浸式状态栏
  • 分类顶部切换的slider
  • 图片预览并保存到相册
  • 拍照、扫码、选择本地文件
  • 侧滑栏
  • 搜索列表页两层侧滑栏筛选
  • 上拉刷新下拉加载
  • 登录、退出逻辑处理

主要功能点:
首页商品展示,商品分类,搜索列表,商品详情,购物车,下订单,个人中心,我的订单/退单,收货地址管理

示例图片

常见问题

  • 首页底部的Tab
    html页面
<nav class="mui-bar mui-bar-tab footerBar">  
    <a id="defaultTab" class="mui-tab-item ft-tab-item mui-active" href="home.html">  
        <span class=" mui-icon iconfont icon-m-ao"></span>  
        <span class="mui-tab-label">首页</span>  
    </a>  
    <a id="tab1" class="mui-tab-item ft-tab-item" href="classify.html">  
        <span class="mui-icon iconfont icon-m-am"></span>  
        <span class="mui-tab-label">分类</span>  
    </a>  
    <a id="tab2" class="mui-tab-item ft-tab-item" href="cart.html">  
        <span class="mui-icon iconfont icon-m-y"></span>  
        <span class="mui-tab-label">购物车</span>  
    </a>  
    <a id="tab3" class="mui-tab-item ft-tab-item" href="my.html">  
        <span class="mui-icon iconfont icon-m-aq"></span>  
        <span class="mui-tab-label">我的</span>  
    </a>  
</nav>

js代码

//底部选项卡切换跳转  
(function jumpPage() {  
    //跳转页面  
    var subpages = ['view/home/home.html', 'view/home/classify.html', 'view/home/cart.html', 'view/home/my.html'];  
    var ids = ['home.html', 'classify.html', 'cart.html', 'my.html'];  
    var aniShow = {};  
    //创建子页面,首个选项卡页面显示,其它均隐藏;  
    mui.plusReady(function() {  
        plus.screen.lockOrientation("portrait-primary");   
        var subpage_style = {  
            top: '0px',  
            bottom: '51px'  
        };  
        //设置bottom绝对位置  
        //iphoneX中出现遮挡底部tab现象,采用js判断屏幕大小方式改变bottom值  
        //isIPhoneX() 要在plusReady后调用  
        if (isIPhoneX()) {  
            subpage_style = {  
                top: '0px',  
                bottom: '88px', //34px  
                styles: {  
                    "render": "always",  
                }  
            };  
        }  
        var self = plus.webview.currentWebview();  
        for (var i = 0; i < 4; i++) {  
            var temp = {};  
            var sub = plus.webview.create(subpages[i], ids[i], subpage_style);  
            if (i > 0) {  
                sub.hide();  
            } else {  
                temp[ids[i]] = "true";  
                mui.extend(aniShow, temp);  
            }  
            self.append(sub);  
        }  
    });  
    //当前激活选项  
    var activeTab = ids[0];  

    //选项卡点击事件  
    mui('.mui-bar-tab').on('tap', 'a', function(e) {  
        e.preventDefault();  
        var targetTab = this.getAttribute('href');  
        if (targetTab == activeTab) {  
            return;  
        }  
        //显示目标选项卡  
        //若为iOS平台或非首次显示,则直接显示  
        if (mui.os.ios || aniShow[targetTab]) {  
            plus.webview.show(targetTab);  
        } else {  
            //否则,使用fade-in动画,且保存变量  
            var temp = {};  
            temp[targetTab] = "true";  
            mui.extend(aniShow, temp);  
            plus.webview.show(targetTab, "fade-in", 300);  
        }  
        //隐藏当前;  
        plus.webview.hide(activeTab);  
        //更改当前活跃的选项卡  
        activeTab = targetTab;  
    });  
})()  

注意iphoneX中出现遮挡底部tab现象,采用js判断屏幕大小方式改变bottom值,isIPhoneX(),isIPhoneX() 要在plusReady后调用。

  • 沉浸式状态栏

1.在manifest.json文件,切换到代码视图,在plus -> statusbar 下添加immersed节点并设置值为true

"statusbar" : {  
    "immersed" : true  
},

2.设置了沉浸式状态栏后,状态栏的高度变为0,如图所示
https://github.com/gs-wenbing/mui-mall/blob/master/img/show/status1.jpg
输入框把状态挡住了,这时候需要重写mui.css或者mui.min.css样式表,在样式表底部添加如下一段样式

*解决沉寖式状态栏导致导航栏高度少20px的问题*/  
.mui-bar-nav {  
    height: 64px;  
    padding-top: 22px;  
}  

.mui-bar-nav ~ .mui-content  
{  
    padding-top: 64px;  
}  

.mui-bar-nav ~ .mui-content .mui-pull-top-pocket  
{  
    top: 64px;  
}  

.mui-bar-nav ~ .mui-content.mui-scroll-wrapper .mui-scrollbar-vertical  
{  
    top: 64px;  
}  

.mui-bar-nav ~ .mui-content .mui-slider.mui-fullscreen  
{  
    top: 64px;  
}

显示效果如图
https://github.com/gs-wenbing/mui-mall/blob/master/img/show/status2.jpg
注意:以上操作后Android沉浸式状态就完成了,但是IOS还需在distribute节点下的apple节点下添加

"UIReserveStatusbarOffset" : false

本以为沉浸式状态栏就完成了,结果老板iPhoneX手机显示有问题,于是又单独适配iPhoneX,具体操作:
在mui.js或者mui.min.js中底部添加如下一段代码

/**  
 * 适配iPhone X 系列手机的导航栏(包括状态栏)  
 */  
mui.plusReady(function(){  
    if(plus.navigator.isImmersedStatusbar() && isIPhoneX()){  
        //.mui-bar-nav  
        var nav = document.querySelector(".mui-bar-nav");  
        if(nav){  
            nav.style.cssText="height:88px; padding-top: 44px;";  
        } else {  
            return;  
        }  
        //.mui-bar-nav ~ .mui-content  
        var content = document.querySelector(".mui-content");  
        if (content) {  
            content.style.paddingTop = "88px";  
        } else {  
            return;  
        }  
        //.mui-bar-nav ~ .mui-content .mui-pull-top-pocket  
        var pullTopPocket_Arr = content.querySelectorAll(".mui-pull-top-pocket");  
        if (pullTopPocket_Arr) {  
            pullTopPocket_Arr.forEach(function(value){  
                value.style.top = "88px";  
            });  
        }  
        //.mui-bar-nav ~ .mui-content.mui-scroll-wrapper .mui-scrollbar-vertical  
        var scrollbarVertical = document.querySelector(".mui-content.mui-scroll-wrapper .mui-scrollbar-vertical");  
        if (scrollbarVertical) {  
            scrollbarVertical.style.top = "88px";  
        }  
        //.mui-bar-nav ~ .mui-content .mui-slider.mui-fullscreen  
        var slider_fullscreen_Arr = content.querySelectorAll(".mui-content .mui-slider.mui-fullscreen");  
        if (slider_fullscreen_Arr) {  
            slider_fullscreen_Arr.forEach(function(value){  
                value.style.top = "88px";  
            });  
        }  
    }  
});  

/**  
 * 判断是否为iPhone X 系列机型  
 */  
function isIPhoneX(){  
    if(plus.device.model.indexOf('iPhone') > -1 && screen.height >= 812){  
        return true;  
    }else{  
        return false;  
    }  
}
  • 标题栏在IOS上存在的问题
    原生标题栏
var styles = { // 窗口参数 参考5+规范中的WebviewStyle,也就是说WebviewStyle下的参数都可以在此设置  
    titleNView: { // 窗口的标题栏控件  
        titleText: title, // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题  
        titleColor: "#FFFFFF", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"  
        backgroundColor: "#E60012", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"  
        autoBackButton: true  
    }  
}  
plus.webview.create(url, id, styles, extras);

1.mui原生标题栏,假如titleColor的值为小写(#ffffff)的话,在IOS上不显示标题,必须要大写(#FFFFFF)才显示,亲测<br>
2.非原生标题栏,假如页面中有输入框的话,软键盘弹出,IOS上会把标题栏顶上去,因为ios弹出软键盘的时候,webview的高度没有变化导致超出屏幕范围,
而plus这时候又会自动把header的 position:fixed 属性设置为 position:relative,header就跟着滚动了。在mui社区找到一个的解决方案:

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

plus.webview.currentWebview().setStyle({    
    softinputMode: "adjustResize"  // 弹出软键盘时自动改变webview的高度    
});   

html, body {    
    height: 100%;    
    margin: 0px;    
    padding: 0px;    
    overflow: hidden;    
    -webkit-touch-callout: none;    
    -webkit-user-select: none;    
}    

.mui-content {    
    height: 100%;    
    overflow: auto;     
}   

这样会解决IOS标题栏顶上去的问题,但是这样处理后,页面打开标题栏会有抖动,虽然很短暂,但是看着不爽,有更好的方案可以联系我(QQ742330561)

具体的demo地址: https://github.com/gs-wenbing/mui-mall
如果对您有帮助,您可以"Star" 支持一下 谢谢! ^^

收起阅读 »

支付宝小程序分享后,用户通过分享的应用点进来之后,tabbar消失。

支付宝小程序分享后,用户通过分享的应用点进来之后,tabbar消失。
第二个图是分享后用户点进来的页面!
第三个是正常的!

支付宝小程序分享后,用户通过分享的应用点进来之后,tabbar消失。
第二个图是分享后用户点进来的页面!
第三个是正常的!

Windows电脑直接申请iOS证书p12及.mobileprovision文件过程

5+App开发 iOS打包

Appuploader软件可以辅助在Windows电脑直接申请iOS证书,并且可以上传ipa到App Store审核!

对于没有Mac电脑的开发者,是一个很好的iOS上架辅助工具

下面介绍申请一套iOS开发证书申请及在HBuilder平台打包的过程!

一、下载安装iOS证书申请及上架辅助软件Appuploader

Appuploader下载链接

下载软件包后解压直接使用,无需安装。

二、登录Appuploader申请iOS证书文件p12

2.1打开Appuploader,用苹果开发者账号登录进去。

2.2、选择证书项目进入

2.3、点击右下角+ADD选择

类型:选择开发证书(开发证书打包的才能安装到手机)

输入证书名称:不要中文、随意设置

邮箱:(随意)

密码:证书的密码,不是开发者账号密码,如123这样不用很复杂,记好、打包时要用、很重要。

应用id:这里不用选!

点击ok创建。

注意:iOS开发证书最多能申请2个,如果账号已经有2个开发证书了,将申请报错(如下图)。

一个开发证书可以用于多个APP测试,不用每个app都对应申请个开发证书p12,开发证书p12是可以公用的,区分开下面步骤申请的的描述文件就行了,一个p12可以对应无数描述文件。

当然也可以删除之前的重新申请

2.4、创建成功后,找到刚创建的iOS开发证书(iOS Development这个类型的就是开发证书,如果之前创建过看过期时间就知道哪个是新创建的了),点击p12 文件,下载保存.p12证书文件到电脑。

三、登录Appuploader申请iOS开发证书描述文件mobileprovision

iOS证书文件有两个,刚申请了p12文件,接下来申请mobileprovision描述文件

在申请ios描述文件之前,先添加好两样基础信息,应用id及苹果手机设备号udid

如果你之前添加过应用id和设备,应用id点击三角符号下拉可以看到,设备选择开发版profile选项可以看到之前添加的。

如果之前加过要用以前加过的应用id,跳过此步。

初次使用或者需要上架另一个项目app需要先创建一个应用id及添加相关的开发测试人员设备。

3.1、先介绍添加应用ID,点击添加应用id!(不同的APP需要编写不同的应用id相当于app的身份证)

应用id:三段式格式、如app名称是淘宝,可以编写为com.app.taobao,自由编写!不能重复!具有唯一性@

名称:数字或者字母,自由编写,不要中文,不能重复。

如果添加报错(应用id具有唯一性,可能重复添加或者别人用过这个应用id),解决办法就是修改下应用id,重新编下。

在AU软件添加的应用id只有默认权限,如果你需要开通推送通知、苹果支付等权限需要到苹果开发者中心配置!

苹果开发者中心添加应用id配置相关权限教程

点击ok只要没弹出报错就是添加成功了,注意先关掉窗口,重新点右下角+ADD进入下拉应用id可查看刚添加的应用id是否存在。

填加好应用id下步添加设置udid

3.2 添加测试设备udid

要安装到哪个苹果手机测试就添加哪个手机的udid,添加了udid的手机才能安装,最多能加100个!

如果你以前加过udid,不需要加新的测试苹果手机上去,跳过此步,直接申请证书!

先来获取udid

udid如果你的手机链接了电脑并且安装好了相关驱动,AU软件会自动获取,直接点ok添加就行了

其他两种获取udid的方式

3.3、苹果手机助手获取UDID

如爱思助手,电脑下载爱思助手,连上苹果手机,设备信息里面那个设备标识就是udid。

3.4、扫码获取苹果手机udid

使用 iPhone 或 iPad 微信扫码选择自带的浏览器safari浏览器打开二维码里的链接,即可快速获取 UDID

这个一长串的就是设备的Udid

udid实例:2D4B87350609342980CB144F72FD2E66B66AEF6C

获取到udid输入

名称name:数字或者名字,自由编写,不能重复,不能中文。

点击ok无提示即为添加成功

在苹果开发中心也可以添加设备,在AU软件添加的设备在开发者中心也会有显示。

苹果开发者中心添加udid设备教程

如果苹果设备udid添加报错(如下图),检查这个udid是否正确或者之前添加过!

Type选择开发版即可看到刚添加的设备。

3.5、勾选相关信息生成ios开发证书描述文件

Type:选择开发版profile(安装到手机测试需要开发证书)

应用id:选择添加的对应的应用id

Devices:勾选需要测试苹果手机

名称:数字或者字母,随意输入,注意不要重复。

点击ok创建

3.6、选择刚创建的iOS开发版描述文件(iOS Developer这个类型的就是开发描述文件,找到刚创建的输入的名字),点击Download下载,保存到电脑

申请得到了两个iOS证书文件p12和.mobileprovision就可以去打包ipa了。

打开HBuilder工具,选择开发好的项目,点击发行,选择发行为原生安装包。

AppID:跟申请证书描述.mobileprovision时选择的要一致(又称套装id,appid,BundleID,应用id,包名)

profile文件:选择上传配置文件.mobileprovision

私钥证书:上传.p12文件

私钥密码:输入创建p12设置的密码。

然后点击打包。

(​

打包成功后,下载保存ipa,这个ipa包就能安装到手机测试了。

​(​

继续阅读 »

Appuploader软件可以辅助在Windows电脑直接申请iOS证书,并且可以上传ipa到App Store审核!

对于没有Mac电脑的开发者,是一个很好的iOS上架辅助工具

下面介绍申请一套iOS开发证书申请及在HBuilder平台打包的过程!

一、下载安装iOS证书申请及上架辅助软件Appuploader

Appuploader下载链接

下载软件包后解压直接使用,无需安装。

二、登录Appuploader申请iOS证书文件p12

2.1打开Appuploader,用苹果开发者账号登录进去。

2.2、选择证书项目进入

2.3、点击右下角+ADD选择

类型:选择开发证书(开发证书打包的才能安装到手机)

输入证书名称:不要中文、随意设置

邮箱:(随意)

密码:证书的密码,不是开发者账号密码,如123这样不用很复杂,记好、打包时要用、很重要。

应用id:这里不用选!

点击ok创建。

注意:iOS开发证书最多能申请2个,如果账号已经有2个开发证书了,将申请报错(如下图)。

一个开发证书可以用于多个APP测试,不用每个app都对应申请个开发证书p12,开发证书p12是可以公用的,区分开下面步骤申请的的描述文件就行了,一个p12可以对应无数描述文件。

当然也可以删除之前的重新申请

2.4、创建成功后,找到刚创建的iOS开发证书(iOS Development这个类型的就是开发证书,如果之前创建过看过期时间就知道哪个是新创建的了),点击p12 文件,下载保存.p12证书文件到电脑。

三、登录Appuploader申请iOS开发证书描述文件mobileprovision

iOS证书文件有两个,刚申请了p12文件,接下来申请mobileprovision描述文件

在申请ios描述文件之前,先添加好两样基础信息,应用id及苹果手机设备号udid

如果你之前添加过应用id和设备,应用id点击三角符号下拉可以看到,设备选择开发版profile选项可以看到之前添加的。

如果之前加过要用以前加过的应用id,跳过此步。

初次使用或者需要上架另一个项目app需要先创建一个应用id及添加相关的开发测试人员设备。

3.1、先介绍添加应用ID,点击添加应用id!(不同的APP需要编写不同的应用id相当于app的身份证)

应用id:三段式格式、如app名称是淘宝,可以编写为com.app.taobao,自由编写!不能重复!具有唯一性@

名称:数字或者字母,自由编写,不要中文,不能重复。

如果添加报错(应用id具有唯一性,可能重复添加或者别人用过这个应用id),解决办法就是修改下应用id,重新编下。

在AU软件添加的应用id只有默认权限,如果你需要开通推送通知、苹果支付等权限需要到苹果开发者中心配置!

苹果开发者中心添加应用id配置相关权限教程

点击ok只要没弹出报错就是添加成功了,注意先关掉窗口,重新点右下角+ADD进入下拉应用id可查看刚添加的应用id是否存在。

填加好应用id下步添加设置udid

3.2 添加测试设备udid

要安装到哪个苹果手机测试就添加哪个手机的udid,添加了udid的手机才能安装,最多能加100个!

如果你以前加过udid,不需要加新的测试苹果手机上去,跳过此步,直接申请证书!

先来获取udid

udid如果你的手机链接了电脑并且安装好了相关驱动,AU软件会自动获取,直接点ok添加就行了

其他两种获取udid的方式

3.3、苹果手机助手获取UDID

如爱思助手,电脑下载爱思助手,连上苹果手机,设备信息里面那个设备标识就是udid。

3.4、扫码获取苹果手机udid

使用 iPhone 或 iPad 微信扫码选择自带的浏览器safari浏览器打开二维码里的链接,即可快速获取 UDID

这个一长串的就是设备的Udid

udid实例:2D4B87350609342980CB144F72FD2E66B66AEF6C

获取到udid输入

名称name:数字或者名字,自由编写,不能重复,不能中文。

点击ok无提示即为添加成功

在苹果开发中心也可以添加设备,在AU软件添加的设备在开发者中心也会有显示。

苹果开发者中心添加udid设备教程

如果苹果设备udid添加报错(如下图),检查这个udid是否正确或者之前添加过!

Type选择开发版即可看到刚添加的设备。

3.5、勾选相关信息生成ios开发证书描述文件

Type:选择开发版profile(安装到手机测试需要开发证书)

应用id:选择添加的对应的应用id

Devices:勾选需要测试苹果手机

名称:数字或者字母,随意输入,注意不要重复。

点击ok创建

3.6、选择刚创建的iOS开发版描述文件(iOS Developer这个类型的就是开发描述文件,找到刚创建的输入的名字),点击Download下载,保存到电脑

申请得到了两个iOS证书文件p12和.mobileprovision就可以去打包ipa了。

打开HBuilder工具,选择开发好的项目,点击发行,选择发行为原生安装包。

AppID:跟申请证书描述.mobileprovision时选择的要一致(又称套装id,appid,BundleID,应用id,包名)

profile文件:选择上传配置文件.mobileprovision

私钥证书:上传.p12文件

私钥密码:输入创建p12设置的密码。

然后点击打包。

(​

打包成功后,下载保存ipa,这个ipa包就能安装到手机测试了。

​(​

收起阅读 »

Android平台App支持CPU类型配置说明

Android

此文档不再维护,请参考新文档地址:https://uniapp.dcloud.io/tutorial/app-android-abifilters

HBuilderX2.7.0+ 调整 云端打包默认不再包含 x86 CPU类型库,减少apk包体积 <a href="https://ask.dcloud.net.cn/article/36195#nox86" target="_self">详情</a>

HBuilderX2.1.5+ 开始支持Android平台的新增适配64位CPU类型,云端打包支持配置App支持的CPU类型
满足Google Play从2019年8月1日起上传的App必需支持64位CPU的要求。
不管5+App、wap2app、uni-app的各种编译模式,均已支持。
上一代HBuilder不支持,请升级更新为HBuilderX。

概要

Android平台配置CPU类型针对的是为了提高运行效率使用C/C++语言开发生成的so库,需要为各cpu类型平台单独编译生成对应指令的so库。Java语言开发的代码运行在虚拟机中,由虚拟机适配CPU类型,不涉及到此问题。

HBuilder/HBuilderX中使用so库的功能(模块)

  • Audio(录音):支持mp3格式
  • Geolocation(定位):百度
  • LivePush(直播推流)
  • Maps(地图):高德、百度
  • OAuth(登录鉴权):新浪微博
  • Push(消息推送):个推、UniPush
  • Share(分享):新浪微博
  • Speech(语音输入):百度,注意:讯飞不支持64位
  • Weex(原生渲染):uni-app(自定义组件模式、nvue页面), 注意:HBuilderX2.1.5及以上版本支持

CPU类型

目前HBuilder/HBulderX适配支持以下主流CPU类型:

  • armeabi-v7a
    第7代及以上的ARM处理器(ARM32位),市面上大多数手机使用此CPU类型。
  • arm64-v8a
    第8代、64位ARM处理器(ARM64位),最近两年新发的设备使用此CPU类型,可以兼容使用armeabi-v7a的so库。
  • x86
    少部分平板使用x86,AS模拟器中选了intel x86时使用x86处理器,以及其它常用三方模拟器通常使用x86

注意:不勾选x86在模拟器上可能无法正常运行,以下是常见模拟器是否需要包含x86的情况

  • 雷电模拟器:
    3.x必须包含x86,否则无法正常运行;4.x无需包含x86。
  • 夜神模拟器:
    必须包含x86,否则无法正常运行
  • MuMu模拟器:
    无需包含x86
  • 逍遥模拟器:
    无需包含x86
  • BlueStacks(蓝叠模拟器):
    无需包含x86
  • 腾讯模拟器(手游助手):
    必须包含x86,否则无法正常运行
  • 其它模拟器:
    未测试验证,建议包含x86,确保在模拟器正常运行

云端打包配置

可视化界面配置

打开项目的manifest.json文件,切换到“App常用其它设置”页面,勾选需要支持的cpu类型:

源码视图配置

打开项目的manifest.json文件,切换到“源码视图”
5+APP项目在 "plus" -> "distribute" -> "google" -> "abiFilters",uni-app项目在 "app-plus" -> "distribute" -> "android" -> "abiFilters" 添加要支持的CPU类型:

"abiFilters":[  
    "armeabi-v7a",  
    "arm64-v8a"  
],

在上面节点配置需要支持的cpu类型,不需要的删除即可,不设置此字段则默认使用armeabi-v7a(ARM32位)

提交Google Play时要求支持64位,请选择"armeabi-v7a"、"arm64-v8a"两个即可。不要勾选“x86”
保存后提交云端打包生效。

查看打包后插件apk支持的CPU类型

使用解压工具打开apk,在lib目录下可以查看到支持的CPU类型,如下图所示:

离线打包配置

配置CPU类型

使用Android studio打开Android原生项目,打开对应项目的build.gradle文件。
在Android -> defaultConfig下添加支持的CPU类型,如下示例:

defaultConfig{  
    ndk {  
            abiFilters 'arm64-v8a','armeabi-v7a'  
        }  
}

注意:离线打包仅支持arm64-v8a、armeabi-v7a、x86三种类型,建议根据自己需求选择打包的CPU类型

CPU类型选择建议

ARM64位(arm64-v8a)CPU可以兼容ARM32的指令,也就是说只选择armeabi-v7a类型的so库也可以在64位手机上运行,只是没有完全发挥CPU的性能。
选择支持的CPU类型时请参考以下建议:

  • 如果不在意apk大小,三种CPU类型都勾选
  • 如果在意apk大小,选择ARM32位即可(几乎在所有ARM指令的所有设备上都可正常运行)
  • 如果要兼容一些平板和模拟器,选择ARM32位和X86
    不是所有模拟都仅支持x86指令,如雷电(4.x)、MuMu等模拟器也是支持ARM指令。

CPU类型错误安装提示

如果打包选择的CPU类型与设备不兼容,会导致无法正常安装。
通过adb命令安装通常会提示如下错误:

Performing Streamed Install  
adb: failed to install android_debug.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

使用Android Studio自带的x86模拟器,将不包含x86 cpu类型的apk拖到模拟器安装时会弹出如下提示框:

<a id="nox86"/>

HBuilderx2.7.0+ 云端打包默认CPU类型不再包含x86

目前市面上常见的手机都是使用ARM处理器,很少有设备使用x86处理器,因此从HBuilderX2.7.0开始云端打包调整为默认不再包含x86的CPU类型,减少apk包大小:

  • uni-app项目
    基础功能apk减少5M+,使用的三方SDK及uni原生插件越多,减少的包尺寸越大,具体值取决于其包含的x86类型的so库大小
  • 5+App、Wap2App项目
    基础功能apk减少100K+,如果使用的三方SDK中存在so库则减少的尺寸较大,具体值取决于其包含的x86类型的so库大小

注意:大多数模拟器(如夜神)必须包含x86,否则应用启动时可能会白屏,请参考上面“配置CPU类型”章节勾选“x86”

继续阅读 »

此文档不再维护,请参考新文档地址:https://uniapp.dcloud.io/tutorial/app-android-abifilters

HBuilderX2.7.0+ 调整 云端打包默认不再包含 x86 CPU类型库,减少apk包体积 <a href="https://ask.dcloud.net.cn/article/36195#nox86" target="_self">详情</a>

HBuilderX2.1.5+ 开始支持Android平台的新增适配64位CPU类型,云端打包支持配置App支持的CPU类型
满足Google Play从2019年8月1日起上传的App必需支持64位CPU的要求。
不管5+App、wap2app、uni-app的各种编译模式,均已支持。
上一代HBuilder不支持,请升级更新为HBuilderX。

概要

Android平台配置CPU类型针对的是为了提高运行效率使用C/C++语言开发生成的so库,需要为各cpu类型平台单独编译生成对应指令的so库。Java语言开发的代码运行在虚拟机中,由虚拟机适配CPU类型,不涉及到此问题。

HBuilder/HBuilderX中使用so库的功能(模块)

  • Audio(录音):支持mp3格式
  • Geolocation(定位):百度
  • LivePush(直播推流)
  • Maps(地图):高德、百度
  • OAuth(登录鉴权):新浪微博
  • Push(消息推送):个推、UniPush
  • Share(分享):新浪微博
  • Speech(语音输入):百度,注意:讯飞不支持64位
  • Weex(原生渲染):uni-app(自定义组件模式、nvue页面), 注意:HBuilderX2.1.5及以上版本支持

CPU类型

目前HBuilder/HBulderX适配支持以下主流CPU类型:

  • armeabi-v7a
    第7代及以上的ARM处理器(ARM32位),市面上大多数手机使用此CPU类型。
  • arm64-v8a
    第8代、64位ARM处理器(ARM64位),最近两年新发的设备使用此CPU类型,可以兼容使用armeabi-v7a的so库。
  • x86
    少部分平板使用x86,AS模拟器中选了intel x86时使用x86处理器,以及其它常用三方模拟器通常使用x86

注意:不勾选x86在模拟器上可能无法正常运行,以下是常见模拟器是否需要包含x86的情况

  • 雷电模拟器:
    3.x必须包含x86,否则无法正常运行;4.x无需包含x86。
  • 夜神模拟器:
    必须包含x86,否则无法正常运行
  • MuMu模拟器:
    无需包含x86
  • 逍遥模拟器:
    无需包含x86
  • BlueStacks(蓝叠模拟器):
    无需包含x86
  • 腾讯模拟器(手游助手):
    必须包含x86,否则无法正常运行
  • 其它模拟器:
    未测试验证,建议包含x86,确保在模拟器正常运行

云端打包配置

可视化界面配置

打开项目的manifest.json文件,切换到“App常用其它设置”页面,勾选需要支持的cpu类型:

源码视图配置

打开项目的manifest.json文件,切换到“源码视图”
5+APP项目在 "plus" -> "distribute" -> "google" -> "abiFilters",uni-app项目在 "app-plus" -> "distribute" -> "android" -> "abiFilters" 添加要支持的CPU类型:

"abiFilters":[  
    "armeabi-v7a",  
    "arm64-v8a"  
],

在上面节点配置需要支持的cpu类型,不需要的删除即可,不设置此字段则默认使用armeabi-v7a(ARM32位)

提交Google Play时要求支持64位,请选择"armeabi-v7a"、"arm64-v8a"两个即可。不要勾选“x86”
保存后提交云端打包生效。

查看打包后插件apk支持的CPU类型

使用解压工具打开apk,在lib目录下可以查看到支持的CPU类型,如下图所示:

离线打包配置

配置CPU类型

使用Android studio打开Android原生项目,打开对应项目的build.gradle文件。
在Android -> defaultConfig下添加支持的CPU类型,如下示例:

defaultConfig{  
    ndk {  
            abiFilters 'arm64-v8a','armeabi-v7a'  
        }  
}

注意:离线打包仅支持arm64-v8a、armeabi-v7a、x86三种类型,建议根据自己需求选择打包的CPU类型

CPU类型选择建议

ARM64位(arm64-v8a)CPU可以兼容ARM32的指令,也就是说只选择armeabi-v7a类型的so库也可以在64位手机上运行,只是没有完全发挥CPU的性能。
选择支持的CPU类型时请参考以下建议:

  • 如果不在意apk大小,三种CPU类型都勾选
  • 如果在意apk大小,选择ARM32位即可(几乎在所有ARM指令的所有设备上都可正常运行)
  • 如果要兼容一些平板和模拟器,选择ARM32位和X86
    不是所有模拟都仅支持x86指令,如雷电(4.x)、MuMu等模拟器也是支持ARM指令。

CPU类型错误安装提示

如果打包选择的CPU类型与设备不兼容,会导致无法正常安装。
通过adb命令安装通常会提示如下错误:

Performing Streamed Install  
adb: failed to install android_debug.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

使用Android Studio自带的x86模拟器,将不包含x86 cpu类型的apk拖到模拟器安装时会弹出如下提示框:

<a id="nox86"/>

HBuilderx2.7.0+ 云端打包默认CPU类型不再包含x86

目前市面上常见的手机都是使用ARM处理器,很少有设备使用x86处理器,因此从HBuilderX2.7.0开始云端打包调整为默认不再包含x86的CPU类型,减少apk包大小:

  • uni-app项目
    基础功能apk减少5M+,使用的三方SDK及uni原生插件越多,减少的包尺寸越大,具体值取决于其包含的x86类型的so库大小
  • 5+App、Wap2App项目
    基础功能apk减少100K+,如果使用的三方SDK中存在so库则减少的尺寸较大,具体值取决于其包含的x86类型的so库大小

注意:大多数模拟器(如夜神)必须包含x86,否则应用启动时可能会白屏,请参考上面“配置CPU类型”章节勾选“x86”

收起阅读 »

用wap2app在线视频网站打包播放视频没有全屏的已经解决

视频全屏

1、网站打包方法请参加这个网址
http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/13425。
2、在线视频网站打包后,有一些视频格式可以全屏观看的例;MP4,其它格式就不可以全屏了
我这个方法只能全屏,其它操作不行。


红色圈那个是全屏。

播放器增加全屏操作方法
1、在你的网站空间找到,播放器文件,js/player/有很多播放文件。你随便打一个播放文件找到下面这段代码。

跟你代码对比后发现了这个代码: allowfullscreen="allowfullscreen" 复制到你播放文件后,再刷新一下就可以了。

如果不明白操作的,加我的QQ370413232 备注播放器全屏,不备注不通过。

继续阅读 »

1、网站打包方法请参加这个网址
http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/13425。
2、在线视频网站打包后,有一些视频格式可以全屏观看的例;MP4,其它格式就不可以全屏了
我这个方法只能全屏,其它操作不行。


红色圈那个是全屏。

播放器增加全屏操作方法
1、在你的网站空间找到,播放器文件,js/player/有很多播放文件。你随便打一个播放文件找到下面这段代码。

跟你代码对比后发现了这个代码: allowfullscreen="allowfullscreen" 复制到你播放文件后,再刷新一下就可以了。

如果不明白操作的,加我的QQ370413232 备注播放器全屏,不备注不通过。

收起阅读 »

IMEI获得不到

IMEI

请下载hbuilder alpha 版本。

请下载hbuilder alpha 版本。

uni-app使用vue-i18n实现小程序端国际化

多语言 国际化 微信小程序 i18n
  1. vue-i18n的基础写法就不详细说明了,相关文档请到官网查看
  2. 官网的文档真的写的还不错,闲话少说直接上代码,我将主要代码分成三个文件,index.js,zh-CHS.js,en-US.js:

index.js主代码

import Vue from 'vue'  
import VueI18n from 'vue-i18n'  

Vue.use(VueI18n)  

// 国际化  
const i18n = new VueI18n({  
  locale: 'zh-CHS', // set locale  
  messages: {  
    'zh-CHS': require('./zh-CHS.js'), // 中文语言包  
    'en-US': require('./en-US.js') // 英文语言包  
  },  
  silentTranslationWarn: true  
})  

// window.i18n = i18n  

export default i18n

中文zh-CHS.js

module.exports = {  
  "home": "首页"  
}

英文en-US.js
module.exports = {
"home": "Home"
}

  1. 在mian.js中引用
    
    import Vue from 'vue'  
    import App from 'App'  
    import i18n from './language'  

Vue.config.productionTip = false
Vue.prototype.i18n = i18n

App.mpType = 'app'

const app = new Vue({
i18n,
...App
})
app.$mount()

4. 使用过vue-i18n的同学都知道,使用i18n-loader用于单文件或组件中,自定义块的语言环境信息,而uni-app并不支持  
无奈要实现国际化,读了vue-i18n-loader的源码,但其中并没有时间部分,只有对不同文件的解析,官网也没有详细写,然后只能自己实现了,悲催呀!  
各种摩擦,整了一天终于出来了,还是官网一个例子给我了启发:  
官网例子:
```javascript  
new Vue({  
  i18n: new VueI18n({  
    locale: 'en',  
    messages: {  
      en: { hello: 'hi there!' },  
      ja: { hello: 'こんにちは!' }  
    }  
  }),  
  data: { path: 'hello' }  
}).$mount('#string-syntax')

根据这个实现了功能。

5.最终实现代码我放github上,地址https://github.com/sjpeter/web/blob/master/vue/i18n/main.vue

  1. 这种写法应该也适用于其他端,但为测试。
继续阅读 »
  1. vue-i18n的基础写法就不详细说明了,相关文档请到官网查看
  2. 官网的文档真的写的还不错,闲话少说直接上代码,我将主要代码分成三个文件,index.js,zh-CHS.js,en-US.js:

index.js主代码

import Vue from 'vue'  
import VueI18n from 'vue-i18n'  

Vue.use(VueI18n)  

// 国际化  
const i18n = new VueI18n({  
  locale: 'zh-CHS', // set locale  
  messages: {  
    'zh-CHS': require('./zh-CHS.js'), // 中文语言包  
    'en-US': require('./en-US.js') // 英文语言包  
  },  
  silentTranslationWarn: true  
})  

// window.i18n = i18n  

export default i18n

中文zh-CHS.js

module.exports = {  
  "home": "首页"  
}

英文en-US.js
module.exports = {
"home": "Home"
}

  1. 在mian.js中引用
    
    import Vue from 'vue'  
    import App from 'App'  
    import i18n from './language'  

Vue.config.productionTip = false
Vue.prototype.i18n = i18n

App.mpType = 'app'

const app = new Vue({
i18n,
...App
})
app.$mount()

4. 使用过vue-i18n的同学都知道,使用i18n-loader用于单文件或组件中,自定义块的语言环境信息,而uni-app并不支持  
无奈要实现国际化,读了vue-i18n-loader的源码,但其中并没有时间部分,只有对不同文件的解析,官网也没有详细写,然后只能自己实现了,悲催呀!  
各种摩擦,整了一天终于出来了,还是官网一个例子给我了启发:  
官网例子:
```javascript  
new Vue({  
  i18n: new VueI18n({  
    locale: 'en',  
    messages: {  
      en: { hello: 'hi there!' },  
      ja: { hello: 'こんにちは!' }  
    }  
  }),  
  data: { path: 'hello' }  
}).$mount('#string-syntax')

根据这个实现了功能。

5.最终实现代码我放github上,地址https://github.com/sjpeter/web/blob/master/vue/i18n/main.vue

  1. 这种写法应该也适用于其他端,但为测试。
收起阅读 »

Android离线打包 高德地图配置经验分享

请先按照附件中的图片修改好

注意application节点里面配置时 附件图片里面不是太清楚 这里我给贴出一个完整的节点配置

application节点下配置实例

<meta-data android:name="com.amap.api.v2.apikey" android:value="52488663213be8ssssf3247b47924916" />  
<service android:name="com.amap.api.location.APSService"></service>

最重要一步配置,官方没有贴出来

修改build.gradle文件(app目录下),加入如下两句话:
implementation(name: 'amap-libs-release', ext: 'aar')
implementation(name: 'geolocation-amap-release', ext: 'aar')

最后请离线打包测试看是否能够正常获取定位点。如果有问题请提问,大家一起交流,仅限高德地图离线配置的问题。
本人本着无私分享的精神,如果不能解决你的问题 请不要生气。


附件图片在这里

继续阅读 »

请先按照附件中的图片修改好

注意application节点里面配置时 附件图片里面不是太清楚 这里我给贴出一个完整的节点配置

application节点下配置实例

<meta-data android:name="com.amap.api.v2.apikey" android:value="52488663213be8ssssf3247b47924916" />  
<service android:name="com.amap.api.location.APSService"></service>

最重要一步配置,官方没有贴出来

修改build.gradle文件(app目录下),加入如下两句话:
implementation(name: 'amap-libs-release', ext: 'aar')
implementation(name: 'geolocation-amap-release', ext: 'aar')

最后请离线打包测试看是否能够正常获取定位点。如果有问题请提问,大家一起交流,仅限高德地图离线配置的问题。
本人本着无私分享的精神,如果不能解决你的问题 请不要生气。


附件图片在这里

收起阅读 »