uni-app uniappx 加入unipush后无法上架安卓市场

uni-app uniappx 加入unipush后无法上架安卓市场

开发环境 版本号 项目创建方式
Windows 10 HBuilderX
产品分类:uniapp/App

PC开发环境操作系统:Windows

PC开发环境操作系统版本号:Windows 10

HBuilderX类型:正式

HBuilderX版本号:4.45

手机系统:Android

手机系统版本号:Android 10

手机厂商:vivo

手机机型:Z6

页面类型:vue

vue版本:vue3

打包方式:云端

项目创建方式:HBuilderX

## 示例代码:

```javascript
export function initPushMsgFun() {  
    const authorizeSetting = uni.getAppAuthorizeSetting()  
    console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~', authorizeSetting?.notificationAuthorized)  
    if (authorizeSetting?.notificationAuthorized == 'authorized') {  
        uni.getPushClientId({  
            success: (res : GetPushClientIdSuccess) => {  
                uni.setStorageSync('clientId', res.cid);  
            }  
        })  
        // 推送  
        uni.onPushMessage((res : OnPushMessageCallbackResult) => {  
                   // ..........逻辑代码  
        })  
    }  
}

操作步骤:

第一次安装即可复现

预期结果:

在没调用getPushClientId和onPushMessage的时候不要获取权限

实际结果:

第一次进入app直接弹了推送权限弹窗

bug描述:

已经加了有权限在调用getPushClientId和onPushMessage的判断,但是第一次安装app还是在隐私政策弹窗前面出现了获取推送权限的系统弹窗, 导致无法上架应用市场 image


更多关于uni-app uniappx 加入unipush后无法上架安卓市场的实战教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

// 完成的初始化代码 initApp.js
import { homeApi, initType, tabsType } from ‘@/api/home.uts’
import { appVersion, speed, versionNum } from ‘@/config/index.uts’
import { setInit, setAddress, setUniverify } from ‘@/store/system.uts’
import { userState, setUserInfo } from ‘@/store/user.uts’
import baseURL from ‘@/config/baseURL.uts’
import { userApi, IImgRes, IImg, IInfoRes } from ‘@/api/user.uts’
import { screenState, setLargeScreen } from ‘@/store/largeScreen.uts’
// #ifdef APP
import { UxRegisterOptions } from “@/uni_modules/ux-weixin”
import * as wxsdk from “@/uni_modules/ux-weixin”
import { showModal, X_MODAL_TYPE } from “@/uni_modules/x-modal-s”
// #endif
// #ifdef APP-ANDROID
import { showTips, hideTips, XTIPS_TYPE } from “@/uni_modules/x-tips-s”
// #endif
// #ifdef APP-IOS
import { openSchema } from ‘@/uni_modules/uts-openSchema’
// #endif
export function initPushMsgFun() {
const authorizeSetting = uni.getAppAuthorizeSetting()
console.log(’~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~’, authorizeSetting?.notificationAuthorized)
if (authorizeSetting?.notificationAuthorized == ‘authorized’) {
uni.getPushClientId({
success: (res : GetPushClientIdSuccess) => {
uni.setStorageSync(‘clientId’, res.cid);
}
})
// 推送
uni.onPushMessage((res : OnPushMessageCallbackResult) => {
let data = res.data as UTSJSONObject;
let pushInfo = data.payload as UTSJSONObject;
if(res.type == ‘click’){
if(pushInfo.isJump == true){
if(pushInfo.jumpType == 0){
let pages = getCurrentPages();
let lastPage = “”;
if(pages.length > 0) {
lastPage = “/”+pages[pages.length - 1].route;
}
if(pages.length > 0 && lastPage == pushInfo.jumpUrl) {
return;
}else if(pages.length > 0 && lastPage == (pushInfo.jumpUrl as string).split("?")[0]) {
uni.redirectTo({
url: pushInfo.jumpUrl as string
})
}else if(pushInfo.jumpUrl == ‘home’ || pushInfo.jumpUrl == ‘cuckoo’ || pushInfo.jumpUrl == ‘my’) {
uni.$emit(‘indexClick’, pushInfo.jumpUrl)
if(lastPage != ‘/pages/index/index’){
uni.switchTab({
url: “/pages/index/index”
})
}
}else {
uni.navigateTo({
url: pushInfo.jumpUrl as string
})
}
}else if(pushInfo.jumpType == 1){
uni.navigateTo({ url: /pages/webview/webview?pushUrl=${encodeURIComponent(pushInfo.jumpUrl as string)}&name=推送详情 })
}
}
}else if(res.type == ‘receive’){
// 创建通知栏消息
uni.createPushMessage({
title: data.title as string,
content: data.content as string,
payload: data.payload
})
// const innerAudioContext = uni.createInnerAudioContext();
// innerAudioContext.autoplay = true;
// let url = ‘’;
// if((data.content as string).indexOf("[红包消息]") > -1){
// url = ‘/static/mp3/red.MP3’
// }else if((data.content as string).indexOf("[转账消息]") > -1){
// url = ‘/static/mp3/transfer.MP3’
// }else if((data.title as string).indexOf(“直接推广收益”) > -1 || (data.title as string).indexOf(“分享推广收益”) > -1){
// url = ‘/static/mp3/profit.MP3’
// }else{
// return;
// }
// innerAudioContext.src = url;
// innerAudioContext.onPlay(() => {
// });
// innerAudioContext.onError((res) => {
// });
}
})
}
}
function startApp() {
const initAppData:UTSJSONObject = {
version: versionNum,
appVersionNum: appVersion,
speedNum: speed,
ratio: 16 as number,
clientId: uni.getStorageSync(‘clientId’),
}
homeApi.initApp(initAppData).then((res: initType) => {
setInit(res)
if(res.loginState == true){
addressDefault()
}
}).catch((err) => {
const errStr = JSON.stringify(err)
const errData = JSON.parse<UTSJSONObject>(errStr)
if (errData?.[‘code’] == 600003) {

    }  
})  
// #ifdef APP  
// 是否支持一键登录  
const univerifyManager = uni.getUniverifyManager()  
univerifyManager?.preLogin({  
    success: () => {  
        setUniverify(true)  
    },  
    fail: (err : UniVerifyManagerPreLoginFail) => { //PreLoginFail UniVerifyManagerPreLoginFail  
        setUniverify(false)  
    }  
} as UniVerifyManagerPreLoginOptions); // as PreLoginOptions UniVerifyManagerPreLoginOptions  
// 注册微信sdk  
wxsdk.register({  
    appid: '',  
    universalLink: '',  
    success: (res) => {  
        // console.log('微信sdk注册成功', res)  
    }  
} as UxRegisterOptions)  
// #endif  
// #ifdef APP-ANDROID  
const permissionListener = uni.createRequestPermissionListener()  
permissionListener!.onRequest((_) => {  
    // 监听到权限申请  
})  
permissionListener!.onConfirm((_) => {  
    hideTips()  
})  
// #endif  
initPushMsgFun() // 初始化推送  
uni.loadFontFace({  
    global: true,  
    family: 'remixicon',  
    source: "url('/static/iconfont/remixicon.ttf')",  
    success() {  
        uni.setStorageSync("loadedFontBytmx", "true")  
    },  
    fail(error) {  
        uni.setStorageSync("loadedFontBytmx", "")  
    },  
})  

}
export function initAppFun() {
uni.getNetworkType({
success: (res: GetNetworkTypeSuccess) => {
if (res.networkType != ‘none’) {
if (uni.getSystemInfoSync().platform == “android” && uni.getStorageSync(‘firstInstall’) != true) { // && uni.getStorageSync(‘firstInstall’) != true
if (screenState.largeScreen == true) {
uni.setStorageSync(‘firstInstall’, true)
} else {
return
}
}
startApp()
let pages = getCurrentPages();
if(pages.length == 0 || pages.length > 0 && pages[pages.length - 1].route != ‘pages/index/index’){
uni.switchTab({
url: ‘/pages/index/index’,
})
}
}
}
} as GetNetworkTypeOptions)
}
// 权限申请
type Callback = () => void;
let timeOut = 0;
export function permissionFun(permission:string, title:string, callback:Callback) {
const appAuthorizeSetting = uni.getAppAuthorizeSetting()
let state:string = ‘’
let tips:string = ‘’
if (permission == ‘android.permission.CAMERA’) { // 相机
state = appAuthorizeSetting.cameraAuthorized
tips = ‘未获取相机权限’
} else if (permission == ‘android.permission.READ_EXTERNAL_STORAGE’) { // 相册
state = appAuthorizeSetting.albumAuthorized
tips = ‘未获取相册/存储权限’
} else if (permission == ‘android.permission.CALL_PHONE’) { // 电话
state = ‘not determined’
tips = ‘未获取电话权限’
} else if (permission == ‘android.permission.BLUETOOTH’) { // 蓝牙
state = appAuthorizeSetting.bluetoothAuthorized
tips = ‘未获取蓝牙权限’
} else if (permission == ‘android.permission.ACCESS_FINE_LOCATION’) { // 定位
state = appAuthorizeSetting.locationAuthorized
tips = ‘未获取定位权限’
} else if (permission == ‘android.permission.RECORD_AUDIO’) { // 麦克风
state = appAuthorizeSetting.microphoneAuthorized
tips = ‘未获取麦克风权限’
} else if (permission == ‘android.permission.MODIFY_AUDIO_SETTINGS’) { // 麦克风
state = appAuthorizeSetting.microphoneAuthorized
tips = ‘未获取麦克风权限’
}
// #ifdef APP-ANDROID
if (UTSAndroid.checkSystemPermissionGranted(UTSAndroid.getUniActivity()!, [permission])) {
callback()
return
}
timeOut = setTimeout(() => {
showTips({
position: ‘top’,
title: title,
titleColor: ‘#fff’,
contentBgColor: ‘rgba(0,0,0,0.8)’,
maskBgColor: ‘rgba(0,0,0,0)’,
iconCode: ‘’,
titleSize: 16,
size: 320,
duration: 0
} as XTIPS_TYPE)
}, 100)
UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, [permission], (_ : boolean, p : string[]) => {
hideTips()
callback()
}, (_ : boolean, p : string[]) => {
clearTimeout(timeOut)
hideTips()
showModal({
title: tips,
content: title,
confirmText: ‘去设置’,
confirm: () => {
UTSAndroid.gotoSystemPermissionActivity(UTSAndroid.getUniActivity()!, [permission])
}
} as X_MODAL_TYPE)
})
// #endif
// #ifdef APP-IOS
if (state == ‘authorized’) { // 已经获得授权,无需再次请求授权
callback()
} else if (state == ‘denied’) { // 请求授权被拒绝,无法再次请求授权。Android平台:需要申请相册相关权限;iOS平台:此情况需要引导用户打开系统设置,在设置页中打开权限
showModal({
title: tips,
content: title,
confirmText: ‘去设置’,
confirm: () => {
openSchema(“app-settings://”)
}
} as X_MODAL_TYPE)
} else if (state == ‘not determined’) { // 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
callback()
} else if (state == ‘config error’) { // Android平台:表示没有配置相册相关权限;iOS平台:当前应用没有配置相册权限描述
}
// #endif
}

// 默认地址
import { productApi } from ‘@/api/product’;
import { AddressDetail } from ‘@/pages/goodsDetails/interface’
export function addressDefault() {
productApi.addressDefault().then((data: AddressDetail) => {
setAddress(data);
})
}

// 图片上传
export function uploadImg(count: number): Promise<string[]> {
return new Promise((res, rej) => {
uni.chooseImage({
count: count,
sizeType: [‘original’, ‘compressed’],
sourceType: [‘album’, ‘camera’],
success: (callback: ChooseImageSuccess) => {
uni.showLoading({
title: ‘上传中…’,
})
let fileList = [] as string[];
callback.tempFilePaths.forEach((item: string) => {
uni.uploadFile({
url: ${baseURL}/front/oss/upload,
filePath: item, //callback.tempFilePaths[0]
name: ‘file’,
header: {
“bingo-token”: uni.getStorageSync(‘token’)
},
formData: {
scene: ‘userHead’,
folder: ‘user/userHead/’
},
success: (result: UploadFileSuccess) => {
const obj = JSON.parse<IImgRes>(result.data as string)
// res(${obj?.data.cdnFilePath});
fileList.push(${obj?.data.cdnFilePath})
if(fileList.length == callback.tempFilePaths.length) {
console.log(fileList)
uni.hideLoading()
res(fileList);
}
},
fail: (result: UploadFileFail) => {
uni.hideLoading()
}
})
})

        },  
        fail: (result: ChooseImageFail) => {  
            uni.hideLoading()  
        }  
    })  
})  

}

更多关于uni-app uniappx 加入unipush后无法上架安卓市场的实战教程也可以访问 https://www.itying.com/category-93-b0.html


我也碰到这样的问题, 怎么解决啊

如何处理呀? 真是各种方法尝试了

隐私弹窗后再进行后面推送设置的逻辑

现在就是这么处理的 但是不生效 刚群友提到了uni.getPrivacySetting这个api 我之前没用 我尝试下再来反馈

回复 前端小周: 我没看到你弹出隐私的代码,看你的代码initAppFun后你直接就运行push相关的逻辑了,你可以使用uni.onPrivacyAuthorizationChange获取隐私协议的同意与否。

回复 DCloud_Android_THB: 我是自己写了个协议弹窗 在用户未点击同意之前是不会执行initAppFun里面的startApp的,也就不会触发推送的代码, 现在加了uni.getPrivacySetting这个api处理还是不行,详细代码粘贴到下面了. 打的测试包: https://testoss.bgbgsc.com/bingo-file/2025/02/22/20250222105036A001.apk

回复 DCloud_Android_THB: 新建个项目一样有问题 所有代码都粘上了 https://issues.dcloud.net.cn/pages/issues/detail?id=15855

回复 前端小周: 我在issue里面回复了你,这是vivo厂商的行为,上架后不会提前弹出。

// main.uts
import App from ‘./App’
import {xui} from “@/uni_modules/tmx-ui/index.uts”
import { createSSRApp } from ‘vue’

// 引入uni统计插件
import { uniStat } from ‘@/uni_modules/uni-stat/plugin.uts’

// uni统计采集项配置
const uniStatcollectItems = {
uniStatPageLog: true,
uniPushClientID: true,
}

// uni统计基础配置
const uniStatOptions = {
debug: true,
collectItems: uniStatcollectItems
}

export function createApp() {
const app = createSSRApp(App)
app.use(xui)
// 载入uni统计插件 ,use 第二个参数不能为空,如需使用默认配置,请传入 {}
app.use(uniStat, uniStatOptions)
return {
app
}
}
// 解决uni.$emit重复触发
let onFun = uni.$on;
uni.$on = (eventName,obj) =>{
try {
uni.$off(eventName);
} catch (error) {}
return onFun(eventName,obj);
} // App.uvue

<script lang="uts"> import { initAppFun } from '@/common/initApp.uts' import { xStore } from "@/uni_modules/tmx-ui/index.uts" import { setUpdate } from '@/store/system.uts' xStore.setDarkModel('light') let firstBackTime = 0 as number export default { onLaunch: function (options) { // 清空更新数据 setUpdate(null) initAppFun(); uni.report({ name: 'uni-app-launch', options: options, success(res) { console.log(res); }, fail(err) { console.log(err); } }) }, onShow: function () { console.log('App Show') // #ifdef APP // 清除角标 // uni.setAppBadgeNumber(0); // #endif uni.report({ name: 'uni-app-show', success(res) { console.log(res); }, fail(err) { console.log(err); } }) }, onHide: function () { console.log('App Hide') uni.report({ name: 'uni-app-hide', success(res) { console.log(res); }, fail(err) { console.log(err); } }) }, onError(err : any) { console.log('错误', err); uni.report({ name: 'uni-app-error', options: err, success(res) { console.log(res); }, fail(err) { console.log(err); } }) }, // #ifdef APP-ANDROID onLastPageBackPress: function () { if (firstBackTime == 0) { uni.showToast({ title: '再按一次退出应用', position: 'bottom'}) firstBackTime = Date.now() setTimeout(() => { firstBackTime = 0 }, 2000) } else if (Date.now() - firstBackTime < 2000) { firstBackTime = Date.now() uni.exit() } }, // #endif onExit: function () { console.log('App Exit') } } </script> <style lang="scss"> [@font-face](/user/font-face) { font-family: UxFont; src: url('@/static/iconfont/iconfont.ttf'); } [@font-face](/user/font-face) { font-family: MyFontNumber; src: url('https://oss.bgbgsc.com/bingo-file/static/otf/number.otf'); } [@import](/user/import) url(./uni_modules/tmx-ui/scss/uvue.min.css); [@import](/user/import) url(./static/css/flex.css); .page{ background: $bg-page-bg; height: 100%; } .element-bg {background: $bg-element-bg} .page-bg {background: $bg-page-bg} .text0{color:$bg-text} .text2{color:$bg-text-2} .text3{color:$bg-text-3} .text4{color:$bg-text-4} .text5{color:$bg-text-5} .text-primary{color:$bg-primary} </style>

// initApp.uts
import { homeApi, initType, tabsType } from ‘@/api/home.uts’
import { appVersion, speed, versionNum } from ‘@/config/index.uts’
import { setInit, setAddress, setUniverify } from ‘@/store/system.uts’
import { userState, setUserInfo } from ‘@/store/user.uts’
import baseURL from ‘@/config/baseURL.uts’
import { userApi, IImgRes, IImg, IInfoRes } from ‘@/api/user.uts’
import { screenState, setLargeScreen } from ‘@/store/largeScreen.uts’
// #ifdef APP
import { UxRegisterOptions } from “@/uni_modules/ux-weixin”
import * as wxsdk from “@/uni_modules/ux-weixin”
import { showModal, X_MODAL_TYPE } from “@/uni_modules/x-modal-s”
// #endif
// #ifdef APP-ANDROID
import { showTips, hideTips, XTIPS_TYPE } from “@/uni_modules/x-tips-s”
// #endif
// #ifdef APP-IOS
import { openSchema } from ‘@/uni_modules/uts-openSchema’
// #endif
export function initPushMsgFun() {
uni.getPrivacySetting({
success: (result: GetPrivacySettingSuccessResult) => {
console.log(result, ‘~~~~~~~~~~~~~~~~~~~~~~~~~~~~~’)
if (result.needAuthorization == false) {
uni.getPushClientId({
success: (res : GetPushClientIdSuccess) => {
uni.setStorageSync(‘clientId’, res.cid);
}
})
uni.showToast({ title: ‘已授权’, icon: ‘none’, duration: 10000 })
// 推送
uni.onPushMessage((res : OnPushMessageCallbackResult) => {
let data = res.data as UTSJSONObject;
let pushInfo = data.payload as UTSJSONObject;
if(res.type == ‘click’){
if(pushInfo.isJump == true){
if(pushInfo.jumpType == 0){
let pages = getCurrentPages();
let lastPage = “”;
if(pages.length > 0) {
lastPage = “/”+pages[pages.length - 1].route;
}
if(pages.length > 0 && lastPage == pushInfo.jumpUrl) {
return;
}else if(pages.length > 0 && lastPage == (pushInfo.jumpUrl as string).split("?")[0]) {
uni.redirectTo({
url: pushInfo.jumpUrl as string
})
}else if(pushInfo.jumpUrl == ‘home’ || pushInfo.jumpUrl == ‘cuckoo’ || pushInfo.jumpUrl == ‘my’) {
uni.$emit(‘indexClick’, pushInfo.jumpUrl)
if(lastPage != ‘/pages/index/index’){
uni.switchTab({
url: “/pages/index/index”
})
}
}else {
uni.navigateTo({
url: pushInfo.jumpUrl as string
})
}
}else if(pushInfo.jumpType == 1){
uni.navigateTo({ url: /pages/webview/webview?pushUrl=${encodeURIComponent(pushInfo.jumpUrl as string)}&name=推送详情 })
}
}
}else if(res.type == ‘receive’){
// 创建通知栏消息
uni.createPushMessage({
title: data.title as string,
content: data.content as string,
payload: data.payload
})
// const innerAudioContext = uni.createInnerAudioContext();
// innerAudioContext.autoplay = true;
// let url = ‘’;
// if((data.content as string).indexOf("[红包消息]") > -1){
// url = ‘/static/mp3/red.MP3’
// }else if((data.content as string).indexOf("[转账消息]") > -1){
// url = ‘/static/mp3/transfer.MP3’
// }else if((data.title as string).indexOf(“直接推广收益”) > -1 || (data.title as string).indexOf(“分享推广收益”) > -1){
// url = ‘/static/mp3/profit.MP3’
// }else{
// return;
// }
// innerAudioContext.src = url;
// innerAudioContext.onPlay(() => {
// });
// innerAudioContext.onError((res) => {
// });
}
})
}
}
})
}
function startApp() {
const initAppData:UTSJSONObject = {
version: versionNum,
appVersionNum: appVersion,
speedNum: speed,
ratio: 16 as number,
clientId: uni.getStorageSync(‘clientId’),
}
homeApi.initApp(initAppData).then((res: initType) => {
setInit(res)
if(res.loginState == true){
addressDefault()
}
}).catch((err) => {
const errStr = JSON.stringify(err)
const errData = JSON.parse<UTSJSONObject>(errStr)
if (errData?.[‘code’] == 600003) {

    }  
})  
// #ifdef APP  
initPushMsgFun() // 初始化推送  
// 是否支持一键登录  
const univerifyManager = uni.getUniverifyManager()  
univerifyManager?.preLogin({  
    success: () => {  
        setUniverify(true)  
    },  
    fail: (err : UniVerifyManagerPreLoginFail) => {  
        setUniverify(false)  
    }  
} as UniVerifyManagerPreLoginOptions);  
// 注册微信sdk  
wxsdk.register({  
    appid: 'wx0c687e00a5ad83d2',  
    universalLink: 'https://api-online.bgbgsc.com/ulink/',  
    success: (res) => {  
        // console.log('微信sdk注册成功', res)  
    }  
} as UxRegisterOptions)  
// #endif  
// #ifdef APP-ANDROID  
const permissionListener = uni.createRequestPermissionListener()  
permissionListener!.onRequest((_) => {  
})  
permissionListener!.onConfirm((_) => {  
    hideTips()  
})  
// #endif  
uni.loadFontFace({  
    global: true,  
    family: 'remixicon',  
    source: "url('/static/iconfont/remixicon.ttf')",  
    success() {  
        uni.setStorageSync("loadedFontBytmx", "true")  
    },  
    fail(error) {  
        uni.setStorageSync("loadedFontBytmx", "")  
    },  
})  

}
export function initAppFun() {
uni.getNetworkType({
success: (res: GetNetworkTypeSuccess) => {
if (res.networkType != ‘none’) {
if (uni.getSystemInfoSync().platform == “android” && uni.getStorageSync(‘firstInstall’) != true) { // && uni.getStorageSync(‘firstInstall’) != true
if (screenState.largeScreen == true) {
uni.setStorageSync(‘firstInstall’, true)
} else {
// 安卓手机端未点击同意协议按钮的时候直接return 不执行后面的代码
return
}
}
startApp()
let pages = getCurrentPages();
if(pages.length == 0 || pages.length > 0 && pages[pages.length - 1].route != ‘pages/index/index’){
uni.switchTab({
url: ‘/pages/index/index’,
})
}
}
}
} as GetNetworkTypeOptions)
}

根据描述,问题出在UniPush权限弹窗过早触发,违反了安卓市场的隐私政策要求。以下是关键点分析:

  1. 问题本质:UniPush SDK在初始化时自动请求通知权限,这发生在用户同意隐私政策之前,不符合应用商店审核规范。

  2. 当前代码问题:

  • 虽然加了权限判断,但uni.getAppAuthorizeSetting()调用时SDK可能已经触发权限请求
  • 权限请求与隐私政策的时序控制不够严格
  1. 解决方案方向:
  • 延迟UniPush初始化时机,确保在用户同意隐私政策后再执行
  • 修改manifest.json中的推送配置,关闭自动初始化:
"push": {
    "unipush": {
        "delay": true  // 延迟初始化
    }
}
  1. 代码调整建议:
// 在用户同意隐私政策后手动初始化
function initAfterPrivacyAgreed() {
    uni.requirePrivacyAuthorize({
        success: () => {
            // 用户已同意隐私政策
            initPushMsgFun();
        }
    });
}
回到顶部