1***@qq.com
1***@qq.com
  • 发布:2025-06-20 09:30
  • 更新:2025-06-20 09:30
  • 阅读:18

APP上架OPPO被驳回,APP未见提供相关业务功能或服务,申请通讯录、定位、短信、录音、相机、日历等权限

分类:uni-app
               "excludePermissions" : [  
                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",  
                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",  
                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",  
                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",  
                    "<uses-permission android:name=\"android.permission.READ_SMS\"/>",  
                    "<uses-permission android:name=\"android.permission.SEND_SMS\"/>",  
                    "<uses-permission android:name=\"android.permission.RECEIVE_SMS\"/>",  
                    "<uses-permission android:name=\"android.permission.READ_PHONE_NUMBERS\"/>",  
                    "<uses-permission android:name=\"android.permission.READ_CALENDAR\"/>",  
                    "<uses-permission android:name=\"android.permission.WRITE_CALENDAR\"/>",  
                    "<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>",  
                    "<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>",  
                    "<uses-permission android:name=\"android.permission.GET_TASKS\"/>"  
                ]

已强行移除,但是上传审核就驳回:
5.7 APP 未见提供相关业务功能或服务,申请通讯录、定位、短信、录音、相机、日历等权限。
检测详情:
APP过度申请权限
改进建议:
(1)建议遵循最小必要原则,仅申请APP业务功能所必需的权限,不申请与业务功能无关的权限(即使用户可选择拒绝)。如APP申请的敏感权限与现有业务功能无关,建议删除无关权限。<br/>(2)可参考《网络安全标准实践指南 移动互联网应用程序(APP)系统权限申请使用指南》,其给出了权限相关的业务功能示例以及与常见服务类型相关程度较低不建议申请的安卓系统权限。

比如上面明明 移除了 READ_CONTACTS,但是权限检测报告显示如下:  
读取联系人(android.permission.READ_CONTACTS)冗余权限  
权限描述:  
允许应用程序读取用户的联系人信息  
自身APP使用:  
位置:  
<com.bumptech.glide.load.data.StreamLocalUriFetcher: java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver,android.net.Uri)>  
描述:  
$r2 = staticinvoke <android.provider.ContactsContract$Contacts: java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver,android.net.Uri,boolean)>($r3, $r1, 1)  
位置:  
<com.bumptech.glide.load.data.StreamLocalUriFetcher: java.io.InputStream loadResourceFromUri(android.net.Uri,android.content.ContentResolver)>  
描述:  
$r1 = staticinvoke <android.provider.ContactsContract$Contacts: android.net.Uri lookupContact(android.content.ContentResolver,android.net.Uri)>($r2, $r1)  
位置:  
<com.facebook.imagepipeline.producers.LocalContentUriFetchProducer: com.facebook.imagepipeline.image.EncodedImage getEncodedImage(com.facebook.imagepipeline.request.ImageRequest)>  
描述:  
$r6 = staticinvoke <android.provider.ContactsContract$Contacts: java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver,android.net.Uri)>($r5, $r3)
录音(android.permission.RECORD_AUDIO)冗余权限  
权限描述:  
允许程序录制声音通过手机或耳机的麦克  
自身APP使用:  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setOutputFormat(int)>(1)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
$i3 = virtualinvoke $r1.<android.media.AudioRecord: int getSampleRate()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i2 = virtualinvoke $r1.<android.media.AudioRecord: int read(byte[],int,int)>($r5, 0, $i2)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void stop()>  
描述:  
virtualinvoke $r1.<android.media.MediaRecorder: void stop()>()  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void start()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: void setRecordPositionUpdateListener(android.media.AudioRecord$OnRecordPositionUpdateListener,android.os.Handler)>($r6, $r7)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void setAudioEncoder(int)>(3)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i2 = virtualinvoke $r1.<android.media.AudioRecord: int read(short[],int,int)>($r7, 0, $i2)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setOutputFormat(int)>(4)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void setOutputFile(java.lang.String)>($r19)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i5 = virtualinvoke $r1.<android.media.AudioRecord: int getChannelCount()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioSamplingRate(int)>($i0)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void createRecord(int,int,int)>  
描述:  
specialinvoke $r1.<android.media.AudioRecord: void <init>(int,int,int,int,int)>(1, $i0, $i1, $i2, $i3)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
$i2 = virtualinvoke $r1.<android.media.AudioRecord: int getChannelCount()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
$i0 = virtualinvoke $r1.<android.media.AudioRecord: int getSampleRate()>()  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void reset()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: boolean isFound()>  
描述:  
$i5 = virtualinvoke $r5.<android.media.AudioRecord: int getState()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioEncoder(int)>(3)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i1 = virtualinvoke $r1.<android.media.AudioRecord: int getSampleRate()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioEncoder(int)>(2)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: int setPositionNotificationPeriod(int)>(220)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i2 = virtualinvoke $r1.<android.media.AudioRecord: int getChannelCount()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
$i2 = virtualinvoke $r1.<android.media.AudioRecord: int getAudioFormat()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void init()>  
描述:  
$i0 = virtualinvoke $r1.<android.media.AudioRecord: int getAudioFormat()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioEncoder(int)>(1)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void release()>()  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void setAudioSamplingRate(int)>(96000)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void prepare()>()  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void setOutputFormat(int)>(1)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setOutputFormat(int)>(0)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioSource(int)>(0)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setAudioEncoder(int)>(0)  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setOutputFile(java.lang.String)>($r3)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
specialinvoke $r26.<android.media.MediaRecorder: void <init>()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: void stop()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void run()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: void startRecording()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: boolean isFound()>  
描述:  
$i6 = staticinvoke <android.media.AudioRecord: int getMinBufferSize(int,int,int)>($i3, $i5, $i1)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void setAudioSource(int)>(0)  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void stopRecord()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: void release()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void reset()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
specialinvoke $r2.<android.media.MediaRecorder: void <init>()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void start()>  
描述:  
virtualinvoke $r1.<android.media.MediaRecorder: void start()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void <init>(io.dcloud.feature.audio.recorder.RecordOption)>  
描述:  
virtualinvoke $r2.<android.media.MediaRecorder: void setOutputFormat(int)>(3)  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void prepare()>()  
位置:  
<io.dcloud.feature.audio.recorder.AudioRecorder: void release()>  
描述:  
virtualinvoke $r1.<android.media.MediaRecorder: void release()>()  
位置:  
<io.dcloud.common.adapter.util.PermissionUtil: int trycatchGetPermission(android.app.Activity,java.lang.String,java.lang.String)>  
描述:  
virtualinvoke $r26.<android.media.MediaRecorder: void stop()>()  
位置:  
<io.dcloud.feature.audio.recorder.RecorderTask: void stopRecord()>  
描述:  
virtualinvoke $r1.<android.media.AudioRecord: void stop()>()

HBuilderX版本:4.66

2025-06-20 09:30 负责人:无 分享
已邀请:

要回复问题请先登录注册