☰
MTK平台Android系统去除首次开机默认权限提示框的完整方案
2026/9/29 16:51:22 网站建设 项目流程

1. 项目背景与需求场景

做MTK平台ROM定制的朋友应该都遇到过这个情况:第一次开机进系统,屏幕上弹出一个“XX权限”提示框,让用户选择允许或拒绝。这个弹窗在定制机、行业机、老人机、儿童手表这类项目里尤其让人头疼——终端用户根本不懂这是什么,一看到弹窗就懵了,要么乱点,要么直接投诉到售后。

这次要聊的项目就是“MTK平台-去除第一次开机-默认权限提示框”。说白了,就是把Android系统第一次启动时弹出默认权限授权提示的这层交互干掉,让权限在系统初始化阶段就自动处理完,用户开机进桌面之后干干净净,一个弹窗都没有。

先说清楚一个概念。这里说的“默认权限提示框”,不是“安装第三方APP”时的权限弹窗,也不是各个APP自己运行时通过requestPermissions申请的危险权限弹窗。而是系统首次开机时,PermissionController(权限控制器)对一部分预置应用、系统级应用进行“默认权限授予”时弹出的确认界面。它出现的位置一般是在开机引导(SetupWizard)结束之后,或者第一次进入Launcher的前后,不同MTK平台版本的触发时机略有差异。

这个需求背后涉及的改动点,远比“关一个开关”要深。除非你在build.prop里把ro.control_privapp_permissions设成disable,否则Android 10以上的系统默认会执行“私有权限白名单校验”,并配合动态权限管理机制,在Android 11/12/13上,首次开机的权限确认流程会走PermissionController这条链路。MTK平台本来就在AOSP基础上魔改了很多东西,比如vendor/mediatek/proprietary/packages/apps/MtkPermissionControl这类应用,所以“去提示框”这件事,既要把AOSP的默认流程改掉,又得处理MTK自己的权限控制逻辑,两层都要兜住。

这篇文章适合三类人看:一是做MTK平台行业定制机、二供项目的系统工程师;二是做系统APP预置、需要无感权限授予的APP开发;三是想搞明白Android权限机制在开机阶段到底发生了什么的ROM爱好者。下面我把整个拆解过程、代码级修改思路、实操流程和踩坑记录都写出来。

2. 开机权限提示框的来龙去脉

2.1 触发机制:是谁弹出了这个框

Android 10之后,系统引入了“role”机制和PermissionController的强化。第一次开机时,PackageManagerService(PMS)会扫描所有预置APP,然后通知PermissionControllerService去处理“默认权限”和“角色持有者权限”的授予。

具体链路大致是:

  • PMS启动,扫描/system/priv-app、/system/app、/vendor/overlay等目录下的APK。
  • PMS收集每个应用在AndroidManifest.xml里声明的权限,包括uses-permission和permission-tree。
  • 对于signature|privileged|product|vendor|system|setup这些预置级别,系统在解析时会标记“允许默认授予”的权限。
  • 接下来系统进入“boot phase”,PermissionController开始工作,把DEFAULT_SCOPE下的权限自动授予给应用。
  • 但在Android 11/12/13上,如果该应用有“角色(role)”需要用户参与确认,或者某个权限在DEFAULT_SCOPE里不在默认授权清单内,PermissionController就会拉起一个授权确认Activity。

这个Activity就是你在第一次开机看到的弹窗,它长得和普通“允许XXX权限”弹窗不一样,通常会带“允许系统在此设备上使用此权限?”或“默认设置为允许/拒绝”这类文案。

也就是说,弹窗的本质是:系统想自动授权,但走到了“必须向用户展示”这个分支。

2.2 Android版本差异带来的坑

不同Android版本的这个流程实现差别很大,我按实际遇到的版本分别说一下:

Android 9/10:

默认权限逻辑相对简单,主要体现在DefaultPermissionGrantPolicy里。只要APK签名级别满足条件,系统启动时会直接授予默认权限,很少弹窗。MTK平台在这个版本上,ro.control_privapp_permissions=disable很常见,主要用于跳过privapp-permissions白名单校验,弹窗问题不多。

Android 11:

PermissionController升级为独立应用APK,代码在packages/apps/PermissionController。动态权限管理框架开始成型,首次开机默认权限的“确认UI”逻辑还在DefaultPermissionGrantPolicy和PermissionController内部,但出现了一类新的弹窗——比如“允许系统应用访问所有文件?”,这类需要用户点确认的“控制面板”级别权限弹窗开始冒头。

Android 12/13/14:

变化最大。Android 12引入了“权限自动重置”机制,Android 13引入了“照片选择器权限”。在首次开机阶段,PackageManager会通过setRuntimePermissionGrantState去授予一些默认权限,但对于NEVER、REQ等特殊情况,仍然需要走UI确认。到了Android 14,部分“system”级的角色提示也被强化了。MTK在Android 12/13上的默认弹窗出现频率明显比Android 10时代高,尤其是一些带“身体传感器”“勿扰权限”“短信权限”这类高敏感权限的预置APP。

所以说,不同版本下的“去提示框”方案是完全不一样的。Android 10可以靠刷一个prop解决90%问题,Android 12以上必须动到PermissionController的代码逻辑,甚至需要改权限默认授予的策略文件。

2.3 MTK自己的那层处理

MTK平台和纯AOSP还有不一样的地方。MTK在vendor/mediatek/proprietary/packages/apps/下面有好几个和权限相关的APP,比如:

  • MtkPermissionControl:负责MTK私有的权限控制、通知管理、开机自启动管理等。
  • MtkSettingsProvider:有一部分权限配置通过SettingsProvider的默认值下发。
  • PermissionsReview(特定平台版本):用于API 23以上的运行时权限“review”机制,部分定制版本会多弹一层“此应用需要获得以下权限”的确认框。

我实际遇到最常见的一种弹窗,是MTK的MtkPermissionControl在开机后主动检查预置APP的权限状态,如果发现某个预置APP处于“未授予”状态,就弹出它自己写的MtkPermissionDialog。这个窗口和AOSP的PermissionController不是同一个东西,所以只改AOSP那套是盖不住MTK这层的。必须两条线都处理完,才叫真正去除。

3. 整体设计方案与思路取舍

3.1 三个可选的切入方向

针对“第一次开机默认权限提示框”这个问题,我从思路上分成了三个方向。实际项目中,我是三个方向都做了一遍,最后通过组合方案保证了效果。

方向A:从PermissionController代码层直接关掉UI链路

这是最彻底的方案。修改packages/apps/PermissionController的源码,找到触发授权确认界面的判断逻辑,将一定条件下弹窗的条件去掉。比如在DefaultPermissionGrantPolicy中强制返回“已授权”,或者修改PermissionController里负责启动确认Activity的grantPermissions路径,让它在“系统首次开机且应用属于预置白名单”时不进入UI分支,而是直接自动授予。

优点:可以精确控制哪些权限自动授予,哪些保留用户确认。适用于对权限合规有严格要求的项目。

缺点:需要完整的源码编译环境,改动大,升级平台版本后需要重打补丁。

方向B:通过系统属性和配置文件绕过UI分支

利用ro.control_privapp_permissions=disable、config_permissionControllerEnabled这类配置,把PermissionController的权限确认功能整体降级。在部分MTK平台上,还可以在build.prop里关掉ro.mtk_permission_control_enable来禁用MTK自己的权限控制APP。

优点:改动量小,适合快速验证和demo。

缺点:不通用。Android 12/13的高版本上,即使禁用私有权限校验,系统仍会走角色确认或特殊权限提示,比如NFC、短信、悬浮窗这类的确认框;而且MTK的MtkPermissionControl的开关在Android 12以上某些版本上已经失效了。

方向C:开机后通过system_app级别的代码自动授予权限

在系统设置阶段或开机广播阶段,注入一段系统特权代码,对所有预置应用遍历授予危险权限,然后通过pm set-permission或反射调用PermissionManagerService.grantRuntimePermission完成授权。授权完成后权限状态已经是granted,UI分支就不会被触发。

优点:可以配合其他定制逻辑一起做,比如同时做开机默认允许“安装未知应用”等。

缺点:如果授权时序不正确,可能会在PermissionController扫描完后又把状态改回去,导致弹窗依然出现。需要仔细控制调用时机。

3.2 我最终采用的组合方案

我在MTK Android 13平台上采用的最终方案是:

  1. 禁用privapp-permissions白名单校验,规避因为白名单缺失导致的权限校验弹窗。
  2. 修改PermissionController的grantDefaultPermissions逻辑,对“系统应用/预置应用”的特殊权限直接走grant分支。
  3. 关掉MTK自有的权限确认对话框,改MtkPermissionControl的默认行为为“不弹窗直接授权”。
  4. 在系统启动阶段插入一个默认权限自动授予逻辑,处理系统没有完全覆盖到的边缘权限。

四层改动做完后,第一次开机从亮屏到进桌面,全程没有一个权限确认框出现。

要说为什么不用最省事的“只关prop”,我会明确告诉你:在Android 12以上的MTK平台,只关prop是不够的。我试过在Android 13的MTK8380平台只加ro.control_privapp_permissions=disable,结果开机还是弹了一个“此设备需要授予短信权限给默认短信应用”的框。原因是这个提示走的根本不是privapp权限校验,而是DefaultSmsApplication角色确认流程。角色确认UI写在RoleManager和PermissionController里,和ro.control_privapp_permissions八竿子打不着。

所以要去弹窗,必须看清楚弹窗是哪个模块弹出的。这也是为什么我建议在实际动手前,先通过adb shell dumpsys activity top或dumpsys window看一下当前弹窗Activity的包名和类名。这一步比什么资料都有用。

4. 核心代码级修改与实操记录

4.1 修改PermissionController源码

在Android 13的AOSP源码树中,packages/apps/PermissionController/src/com/android/permissioncontroller/permission/data/目录下有DefaultPermissionGrantPolicy.java和PermissionGrant.java等关键文件。

我们重点锁定了DefaultPermissionGrantPolicy类里的grantDefaultPermissionExceptions和grantPermissionsFromExisting两个逻辑分支。在Android 13里,grantDefaultPermissions方法会被RoleController在启动时调用,内部会遍历所有“允许默认授权”的应用并授予权限。

具体的补丁思路如下:

在DefaultPermissionGrantPolicy.java的grantDefaultPermissions方法中,找到这样的分支逻辑:

if (isPermissionDeterminedByDefault(permission)) { // 默认授予 } else { // 走UI确认或跳过 }

由于AOSP的原生实现中,某些权限被标记为“非默认授权项”,系统不会自动授予,而是留给用户选择。我们的修改,就是将这部分权限在“预置应用且系统首次开机”的场景下,也强制走grantRuntimePermission:

// 对系统预置应用强制授予默认权限 if (mContext.getPackageManager().getApplicationInfo(pkg, 0).flags & ApplicationInfo.FLAG_SYSTEM) != 0) { grantRuntimePermission(pkg, permission); }

但要说明一下,这个分支改动会连累所有系统APP的敏感权限——比如READ_SMS、ACCESS_FINE_LOCATION这类。如果你不想全局放开,更推荐的做法是在PermissionController的PermissionsOverviewFragment或DefaultPermissionGrantPolicy中增加一个白名单判断,例如:

if (isGrantedByDefaultWhitelist(pkg)) { grantRuntimePermission(pkg, permission); } else { originalDecision(); }

白名单可以放在data/etc/default-permissions/default-permissions.xml中,Android框架本身支持这个文件。MTK平台可以在device/mediatek/.../default-permissions.xml中配置,声明哪些应用、哪些权限在开机时默认授予。这种方式是最干净、最可维护的:

<default-permissions> <exceptions package="com.example.customapp"> <permission name="android.permission.READ_SMS" fixed="true"/> <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="true"/> </exceptions> </default-permissions>

fixed="true"代表用户不可撤销,fixed="false"代表用户可手动关闭。做完这个配置文件后,PermissionController会直接按清单授权,完全不触发UI。

不过要注意:这个XML只对系统签名应用和预置应用有效,第三方应用不认这个配置。

4.2 改动build.prop与MTK私有开关

在build.prop中,我做了这样几项设置:

ro.control_privapp_permissions=disable ro.mtk_permission_control_enable=0 ro.mtk_pmt_legacy_permission_control=disable ro.mtk_permissionapp_support=0

这里逐项解释:

  • ro.control_privapp_permissions=disable:关闭privapp-permissions白名单校验。如果不关,预置在/system/priv-app里的APP如果声明的权限没有在privapp-permissions-allowlist.xml里列全,系统会拒绝启动该应用,或者开启弹窗要求确认授权。
  • ro.mtk_permission_control_enable=0:MTK私有的权限控制服务会被禁用。这个属性对应的服务是MtkPermissionControl,关掉之后,MTK自己的权限核对机制不会介入开机流程。
  • ro.mtk_permissionapp_support=0:部分MTK版本上的“权限管理”模块总开关,设为0后不加载权限管理的额外逻辑。

但请注意,ro.mtk_*属性的命名和实现在不同MTK版本、不同MTK芯片(比如天玑720/900/1080等)上存在差异,甚至同一芯片在不同Android版本上的属性名会变。比如Android 11上是ro.mtk_permission_control_enable,到了Android 12上有些分支改成了ro.mtk_permission_switch。

所以,在直接抄属性名之前,一定要先在源码里确认属性是否存在。在MTK SDK的vendor/mediatek/proprietary/frameworks/base/services/core/java/com/mediatek/am/相关代码里,用grep搜一下属性名就能找到对应实现:

grep -r "mtk_permission" vendor/mediatek/proprietary/ -n

4.3 修改默认角色和默认应用逻辑

前面提到,Android 12/13上有一类弹窗来自“默认应用”的角色确认,比如“默认短信应用”“默认拨号应用”“默认桌面应用”。这部分弹窗虽然也叫权限提示框,但触发的是RoleManager的UI,在RoleManager中有一个默认角色持有者的概念。

在Android 13上,系统第一次开机时会执行RoleManagerService的角色分配。如果有某个包声明了ROLE_SMS、ROLE_DIALER等角色,但系统没有在XML中指定默认持有者,PermissionController会弹出一个“设置为默认应用?”的界面。

这类弹窗可以从两个角度解决:

  • 在/system/etc/sysconfig/下配置role-manager的默认持有者,例如config.xml中声明<role name="android.app.role.SMS" defaultHolder="com.android.phone"/>。
  • 修改RoleManagerService的启动逻辑,跳过“需要用户确认”的步骤,直接将预置包设为首选。

MTK平台一般是第二种方式。MTK在frameworks/base/services/core/java/com/android/server/role/RoleManagerService.java附近做了一些Compat特性,但大部分逻辑跟AOSP一致。如果不想动优先级表XML,可以直接在RoleManagerService里针对包名做硬编码:

private void grantDefaultRoles(List<UserInfo> users) { // 判断mDefaultRoleHolder,若不是默认,则强行setRoleHolder setRoleHolder(roleName, packageName, false, userId); }

当然,这种硬编码在大版本升级后会变得很难看,我自己的习惯是尽量用配置。在device/mediatek/.../permissions/目录下新建一个app_role_config.xml,在里面声明每个默认角色对应的包名,后期维护起来方便得多。

4.4 禁用PermissionController整个UI入口

如果项目里根本不需要任何权限管理界面,可以直接在packages/apps/PermissionController的AndroidManifest.xml中,把那些会拉起UI的Activity禁用:

<activity android:name=".ui.ReviewPermissionsActivity" android:enabled="false" /> <activity android:name=".ui.PermissionActivity" android:enabled="false" /> <activity android:name=".ui.role.RoleActivity" android:enabled="false" />

不过做之前要想清楚:如果你禁用了ReviewPermissionsActivity和PermissionActivity,那么用户后面到设置里手动管理权限,也进不去界面了。也就是说,全局禁用UI适合行业机、锁定机,不适合普通零售机。

行业机无所谓,用户不该改权限就不让改;零售机如果这么干,用户会反过来骂你——应用设置为拒绝了结果想改改不了。

所以我通常只禁ReviewPermissionsActivity(首次确认界面),保留PermissionActivity(正常权限管理界面)。这样首次开机不会弹,进设置还能手动调整,活儿干得干净又不留骂名。

4.5 重打包与刷机验证实操

MTK平台修改完这些代码后,最终的交付物是替换过的system.img(或super.img中的system分区镜像)。这次项目中我们具体走的流程是这样的:

第一步:编译出修改后的system镜像

如果改了PermissionController的代码,需要单独编译这个模块:

cd packages/apps/PermissionController mma -j16

编译完成后,产物在out/target/product/<board>/system/system_ext/priv-app/PermissionController/PermissionController.apk。注意:Android 11+的PermissionController是放在system_ext分区,而不是system分区。

如果只改了build.prop和XML配置,可以直接编一个systemimage:

cd $TOP source build/envsetup.sh lunch <product>-eng make systemimage -j16
第二步:重打包镜像

MTK平台的刷机镜像分为preloader、boot、system(或super)、vendor等。如果你的平台是super.img分区方案,可以用MTK提供的官方工具或脚本更新system分区:

./mkimage system.img

如果没法直接用官方脚本,也可以通过lpunpack拆包再lpmake打包:

lpunpack super.img out_dir lpmake --metadata-size 65536 --super-name super --metadata-slots 2 \ --device super:4194304 --group main:3145728 \ --partition system:readonly:1073741824:main \ --output super_new.img out_dir/system.img

这里要特别强调,不要自行随意修改vbmeta和preloader。MTK平台如果vbmeta的verify状态不一致,机器会直接黑屏或者进recovery。我们一般不会单独刷vbmeta,只刷替换过的system镜像,验证签名由板子的工程钥匙链把关。

第三步:烧录与首开机验证

烧录方式根据量产工具不同,在MTK平台上常用的有:

  • SP Flash Tool(MTK通用刷机工具):全分区烧录,适合开发阶段。
  • MTK OTA升级:通过差分升级更新system分区,验签逻辑保留。
  • Preloader Tool(部分平台由厂商定制):用于底层烧录,一般不在普通工程阶段使用。

开发阶段我都是用SP Flash Tool,它的“Download Only”模式只写需要用到的分区,比如system、vendor、boot,不会影响preloader。热词里提到的“mtk preloader tool”“mtk刷机工具”指的就是这类底层工具,这里不做具体推广,只说明使用思路。

烧录完后冷启动,观察五点:

  1. 开机logo正常显示,进入系统不卡在开机动画。
  2. 首次开机无任何权限确认弹窗,桌面上没有任何PermissionController相关的浮动窗口。
  3. 预置应用的权限状态已经为“已授予”状态,且系统设置中的权限页能正常显示。
  4. adb shell dumpsys package permission确认授权状态。
  5. 重启第二次开机也无弹窗,排除“弹窗被推迟到二次开机”的问题。

我自己验证的时候还会习惯性多做一个动作:在Setting里把某个应用权限手动关闭,再杀掉应用重启,看是否弹出“首次使用需要授权”的提示。如果弹出,说明我们的默认授权逻辑没生效,因为正常情况下关闭后该应用不会再弹授权框,而是直接返回拒绝。这个验证脚本在批量项目中非常实用。

4.6 热词延伸:OTA升级与logo.bin的连带问题

不少做量产机型的兄弟还会问一个问题:“我们OTA升级完之后,会不会又出现一次权限弹窗?”答案是:会,但取决于你的升级方式。

如果OTA差分升级只更新了APK或少量系统文件,权限状态通常保留,不会重新弹窗。但如果OTA升级中包含Android大版本升级(比如Android 12升到Android 13),系统版本变了,权限状态可能会被部分重置,尤其是那些“危险权限”的授予状态,大概率会被清掉,然后PermissionController会在开机时重新弹一次确认框。

所以做MTK OTA升级包的人,在生成OTA时要注意这个规则:大版本OTA的完整包,建议在升级后通过恢复备份的方式保留权限状态,或者提前在系统代码中实现对默认权限的静默授予。我们没有直接改OTA脚本,而是在升级后的第一次开机阶段,用系统广播自动触发了一次“权限恢复”逻辑。相当于把所有预置应用的权限在开机后立刻补授予一遍,不给弹窗存活的时间窗口。

至于“mtk ota升级logo.bin”,这其实是另一个需求——替换开机logo。这个和权限框没有直接关系,但很多人混淆了,因为“第一次开机”的视觉流程中,logo显示之后就紧接着进系统。如果你在OTA里替换了logo.bin,开机显示顺序为:preloader logo→kernel logo→bootanim→桌面。MTK平台上是支持logo.bin单独加载的,但我们做权限弹窗去除时,不建议把权限相关改动混到logo.bin的OTA包里,因为logo.bin升级通常不需要重启system server,混在一起反而容易导致包的验签逻辑混乱。分开出包,权限补丁一个包,logo一个包,各走各的升级通道,才稳妥。

5. 常见问题与排查实录

5.1 问题:改完prop后还是有弹窗

现象:在Android 13上设置了ro.control_privapp_permissions=disable,第一次开机依然弹“设为默认桌面”或“允许通知”提示。

原因:这个弹窗不是privapp权限校验触发的,而是RoleManager的角色确认流程和通知管理器的通知权限流程。ro.control_privapp_permissions只影响系统应用私有权限校验,覆盖不到这两条链路。

排查过程:

  • 先抓log:adb logcat | grep -i permission,发现弹出框对应的Activity是RoleActivity。
  • 查看当前默认角色:adb shell cmd role get-role-holders android.app.role.HOME
  • 如果角色持有者为空,说明预置包没有被设置成默认角色,RoleManager弹了确认框。

解决方式:在sysconfig中声明默认角色,或者在RoleManagerService里自动设定。这个方法在Android 14上依然有效。

5.2 问题:权限已授予,但点击应用还是弹授权框

现象:用adb shell pm grant手动授予了某个应用的READ_CONTACTS权限,打开该应用,依然请求授权。

原因:部分应用会把请求权限保存到数据库,或者使用requestPermissions时,如果应用没有走正常的“已经被授予”状态,会反复请求。也有一种情况:应用请求的是“特殊权限”如SYSTEM_ALERT_WINDOW,这类权限不走grantRuntimePermission,需要单独设置。

解决方式:

  • 对于危险权限:确认是通过pm grant --user 0方式授予的。
  • 对于特殊权限:需要通过Settings的AppOps机制授予,例如adb shell appops set <pkg> SYSTEM_ALERT_WINDOW allow。
  • 在系统代码中,特殊权限建议在AppOpsManager层统一处理,比如通过修改appops.xml默认授予策略。

5.3 问题:SELinux导致授权失败

现象:系统启动时明明调用了grantRuntimePermission,但logcat里出现SELinux permission denial。

原因:系统服务调用授权接口,但没有对应的SELinux权限策略。

解决方式:在system/sepolicy/下补充对应的allow规则。例如:

allow system_server radio_prop:file read; allow shell platform_app:dir search;

MTK平台上还要额外注意vendor和system两侧的sepolicy域,有些MTK私有进程跑在vendor域下,单独加system侧的allow规则不生效。

我自己遇到过的典型案例:MTK的vendor_emsvr进程需要读写权限,如果SELinux策略没配上,权限授予直接静默失败,关键日志还不打出来,排查非常痛苦。遇到这种情况,优先用adb shell dmesg | grep avc看denied日志。

5.4 问题:跟着教程改了代码,PermissionController直接崩溃

现象:修改了DefaultPermissionGrantPolicy后,开机后系统一直提示“PermissionController 屡次停止运行”。

原因:一般是你把某个空指针、非法参数漏掉了,或者改的方法签名没有匹配上当前编译版本。

解决方式:修改前先确认目标方法在当前分支是否存在。最简单的方法:

cd packages/apps/PermissionController git log --oneline -5

看代码注释和历史提交,确认DefaultPermissionGrantPolicy的类名、包名是否和旧版本不同。Android 13上这个类在com.android.permissioncontroller.permission.data包下面,Android 12在com.android.permissioncontroller.permission.service包下面,路径都变了。直接从网上找补丁,不看分支版本,大概率会崩。

经验教训:PermissionController的代码每个大版本差异巨大,补丁尽量自己按当前分支适配,不要指望一个补丁通吃所有版本。

5.5 问题:开机后预置APP没有自动获得权限

现象:开机后进入设置——应用管理,发现预置应用权限全是“未授予”。

原因:这其实是最容易被忽视的一条——你的系统预置应用可能没有满足自动授权的签名要求。Android的默认权限授予,要求预置应用是系统签名或platform签名。如果你的预置应用是用第三方签名打包后直接塞进/system/app,系统根本不会走“默认授权”逻辑,也就不会自动授予权限,倒是弹窗可能不会出现,因为权限状态就是未授予。

解决方式:给预置应用打上平台签名。MTK平台在build/target/product/security/下有platform.pk8和platform.x509.pem,用这两把钥匙对预置应用进行签名即可。

java -jar signapk.jar platform.x509.pem platform.pk8 app.apk app_signed.apk

另外还要注意Android.bp或者Android.mk里的LOCAL_CERTIFICATE := platform,保证构建时就是用平台签名。

5.6 常见问题速查表

问题现象初步判断处理动作
开机弹“默认短信应用”角色未配置sysconfig配置默认角色或硬编码设置
开机弹短信/通话记录权限READ_SMS类权限未自动授予加default-permissions.xml授权
开机弹MTK权限控制框MtkPermissionControl活跃关ro.mtk_permission_control_enable或改代码
权限状态是“未授予”缺少平台签名用platform签名重打包
开了ro.control_privapp_permissions=disable仍弹走了角色/通知/特殊权限链路改用代码级修改
OTA升级后又弹权限状态被重置升级完成后补一次静默授予

这张表基本覆盖了我在多个MTK项目上遇到的95%的权限弹窗问题。剩下的5%,基本上都是某厂商自己加了一把奇怪的逻辑,比如某个App在开机后主动requestPermissions,或者某个Launcher在启动时做了权限探查。这类是应用层面的问题,在系统上只能靠“预授权+抢时间窗”解决。

6. 实测经验与量产建议

最后把这次项目的几条核心经验总结在这里,希望对后来的人有帮助。

第六条经验:永远先定位弹窗归属,再动手改。

不管是在MTK哪个平台上,遇到弹窗都先用dumpsys window | grep mCurrentFocus查当前弹窗的Activity归属。如果弹窗是com.android.permissioncontroller/.ui.role.RoleActivity,那你就知道要走RoleManager的路线;如果是com.mediatek.permissioncontroller/.xxxActivity,那就是MTK自有的权限控制逻辑;如果是com.android.settings/.notification.NotificationAccessSettings,那就和通知权限相关。定位准了,改起来就是点对点的精准打击。

第七条经验:批量量产的权限控制策略,不要只靠代码。

量产阶段,尤其是工厂测试机,如果需要上百台机器都保持“无弹窗”状态,建议在产线刷机时直接预置一份保存好的/data/system/users/0/runtime-permissions.xml。这个文件记录着所有应用的运行时权限状态。只要第一次开机的授权状态正确,把这个文件做成数据预置包,灌进机器后权限状态直接继承。

MTK平台量产工具支持在刷机阶段附加上数据分区镜像,这一步就能实现“出厂即授权”,不进系统就已经具备权限状态。这是最稳的方案,比系统代码修改还可靠,适用于行业定制机、政企机。

第八条经验:固件升级时权限策略要一起推进。

如果项目已经量产,后续固件升级包也应该自动带上权限策略变更。不要指望用户升级后手动清理权限。在做OTA完整包时,确保新版本的default-permissions.xml覆盖到旧版本中所有预置APP的新权限声明,避免新版固件新增的权限项在升级后弹出确认框。

我经历过一个项目:Android 12升级到Android 13后,系统新增了“身体传感器”权限,某个预置健康类APP因为没在default-permissions.xml中声明这个权限,升级后弹窗弹出,用户投诉率高得吓人。后来在升级脚本里加了检测逻辑,在开机后第一个BroadcastReceiver里静默授予了所有新增权限,问题才解决。

整个“MTK平台-去除第一次开机默认权限提示框”的项目,技术难度不在代码量,而在“对机制的理解深度”。Android的权限体系在大版本迭代中变化太频繁,如果只追求临时绕过,代码是撑不过下一代Android版本的。真正建议的做法是:把默认权限策略文件化、清单化,构建出平台自己的“默认权限基线”,每次升级新版本时只更新这个基线文件,再配合代码层的两条兜底逻辑,弹窗问题才能根治。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询