问题比较杂,记录2022年开发uniapp项目时遇到的问题及相关建议。包含图片问题、跨域配置、cookie、路由、安全扫描、消息推送相关。
1. 组件引用推荐easycom组件模式
使用easycom组件模式,只要组件安装在项目的components目录下或uni_modules目录下,并符合components/组件名称/组件名称.vue目录结构,就可以不用引用、注册,直接在页面中使用。
不管components目录下安装了多少组件,easycom打包后会自动剔除没有使用的组件,对组件库的使用尤为友好。
2. H5方式图片资源被用户图库看到问题
打包为web或H5后,用户在手机图库中可以看到项目中图片资源:
图一为uniapp图片转base64说明。但在实践过程中对以下说明还是存有疑问。图二中为我打包后的H5包,可以看到static文件夹下的静态图片文件会原样打包进入。由此判断static下的图片文件并未转为base64。经测试非static文件夹下图片资源可以转化为base64并且打包并不会原样拷贝静态资源到打包后的文件中。
大概是图三中官网说明让我对此疑惑,认为图片资源放入static文件夹是规范。
结论,若不想将图片资源打包进项目,可将图片放入非static文件夹下。(对此未作深入研究,如有好的方案请留言)。
(图一:)
(图二:)
(图三:)
3. tabBar中配置了图片H5或APP端不展示
在pages.json tabBar中配置底部导航图标iconPath和selectedIconPath,但h5或app端不展示的情况。
解决:查看图片是否放在了static文件夹,且无文件夹嵌套,比如在static/icon/*.png 就会出现上述情况。(该问题是2022年记录的,不知现在这个问题是否被官网修复)。
4. H5跨域配置:
解决h5访问方式跨域问题,通常会使用webpack-dev-server代理解决,一是通过配置vue.config.js,二是manifest.json中设置devServer。
"h5" : {
"devServer" : {
// "port" : 8080, //端口号
"disableHostCheck" : true
},
5. cookie问题
h5端cookie会自动携带,app需要手动添加:www.html5plus.org/doc/zh_cn/n…
6. 路由传参问题
app端没有router,调用this.$route.query报错。app端可以使用getCurrentPages()。
/**
* @description 获取当前页面路径
*/
function page() {
const pages = getCurrentPages()
// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
return `/${pages[pages.length - 1]?.route ?? ''}`
}
6. IOS无法输入小数点
在开发app端时,输入框是type为number, Android 可以输入小数点,ios却不可以。
解决方法:把type类型更换为digit就可以了。
uniapp.dcloud.net.cn/component/i…
7. 配置unipush:报错CID不存在或不属于此应用
根据官网配置流程还是出现了"CID不存在或不属于此应用"报错,通过排查是cid不对导致。
解决方案,运行到手机设备打印
plus.push.getClientInfo(),获取到的clientid是正确的。
8. 个别手机测试收不到消息推送
测试时遇到cid能测试通过,dcloud开发者中心中数据统计-- 推送记录里面显示推送成功,但手机始终没有接收到推送消息,用同事手机测试了下可以收到。找到如下说明,部分厂商需上架应用市场才能正常使用推送服务。
9. Android平台安全检查相关
安全报告中显示有以下问题:
1. 加固
如腾讯云加固:console.cloud.tencent.com/ms/reinforc…
基础版(免费)解决的问题有:APK防反编译、壳加密算法保护、DEX文件整体加固保护、DEX文件防篡改保护。
加固过程中删除了签名信息,加固后的安装包需要重新签名,否则会安装失败。重新签名可以把打包时用的签名文件,加固后的安装包放在同一文件夹下,然后命令行执行如下,会生成一个新的安装包,新的apk就可以正常安装使用了。
jarsigner -verbose -keystore 签名文件.后缀 -signedjar 签名后的apk名称.apk 签名前的.apk名称 证书别名
2. 避免运行在root环境及证书签名验证
App.vue:
<script>
export default {
onLaunch: function() {
// #ifdef APP-PLUS
/**判断是否为ROOT环境,ROOT环境下可以访问到一些敏感关键目录*/
let isRoot = false;
const platform = uni.getSystemInfoSync.platform;
const sign = plus.navigator.getSignature();
if ('android'==platform) {
const paths = [
'/sbin/su',
'/system/bin/su',
'/system/xbin/su',
'/data/local/xbin/su',
'/data/local/bin/su',
'/system/sd/xbin/su',
'/system/bin/failsafe/su',
'/data/local/su'
];
const File = plus.android.importClass('java.io.File');
for (let i = 0; i < paths.length; i++) {
let path = paths[i];
let fd = new File(path);
// 如果 Dictionary 对象中存在所指定的主键则返回 true
if (fd.exists()) {
isRoot = true;
break;
}
}
}
if('android'==platform){ //Android平台
var sha1 = 'xxxxxxxxxxxx'; //修改为自己应用签名证书SHA-1值,是全小写并且中间不包含“:”符号
if(sha1!=sign){
//证书不对时退出应用
plus.runtime.quit();
}
}
// #endif
}
};
</script>