Flutter插件跨框架场景下onRequestPermissionsResult未被调用
抽离后的MyClass无法收到onRequestPermissionsResult回调的核心原因非常明确:Android系统的权限请求结果只会派发给当前真正处于前台、被系统托管的Activity实例。
你写的继承AppCompatActivity的MyClass本质是个完全孤立的普通类实例:它既没有在AndroidManifest中注册,也没有走系统的Activity启动流程挂载到任务栈上,系统根本感知不到这个实例的存在,自然不可能把权限结果回调给它。
原先Flutter桥接实现能正常收到回调,和你是否实现Activity相关接口没有任何关系:你在绑定阶段调用binding.addRequestPermissionsResultListener(this),本质是把桥接类注册到了Flutter引擎持有的、当前正在前台运行的宿主Activity的回调分发链路里,权限结果会由宿主Activity派发给所有注册的监听器,所以能正常触发。
你参考的官方示例逻辑仅适用于普通App的页面Activity场景——示例里的MainActivity是真正被系统启动、挂载到任务栈、在前台展示的实例,当然能收到系统回调,和插件依附宿主运行的场景逻辑完全不同。
不要尝试自己实现独立的Activity子类承接权限回调,按以下两种方案抽离即可实现核心逻辑一次编写多端复用:
方案1:薄适配层转发(兼容性最优,推荐)
核心权限类不需要继承任何Activity基类,只承载通用业务逻辑:
- 对外提供通用的权限状态校验、权限请求、结果解析(判断授权/拒绝/永久拒绝、跳转应用设置页)等纯逻辑方法
- 定义统一的权限结果回调接口,不耦合任何跨端框架的API
各跨端框架的桥接层仅需要实现极薄的适配逻辑,单端适配代码不超过20行:
- Flutter侧:通过
ActivityAware生命周期拿到当前前台宿主Activity传入核心类,调用binding.addRequestPermissionsResultListener注册监听,把收到的权限结果直接转发给核心类处理 - React Native侧:通过NativeModule拿到当前ReactActivity实例传入核心类,重写Activity的
onRequestPermissionsResult方法转发结果 - Capacitor/Ionic侧:通过Plugin类拿到当前托管的Activity实例传入核心类,在插件自带的权限回调方法中转发结果
该方案下90%以上的权限相关业务逻辑都收敛在核心类中,适配层仅做参数和回调的转发,没有重复代码,同时完全遵循各跨端框架的生命周期规则,不会出现机型兼容性问题。
方案2:透明Activity中转(适配成本最低)
如果希望尽可能减少各端的适配代码,可以在核心库内实现一个无UI的透明Activity:
- 在库的AndroidManifest中注册该透明Activity,配置透明无UI的主题避免界面闪烁
- 发起权限请求时,通过传入的Context启动这个透明Activity,在Activity内部调用
ActivityCompat.requestPermissions发起请求 - 在透明Activity自身的
onRequestPermissionsResult中拿到权限结果,通过本地广播或静态回调把结果传回给调用方,之后立即finish自身销毁
该方案下各跨端框架不需要做任何权限回调的转发适配,只要能拿到应用Context就能调用权限申请逻辑;缺点是会多一次Activity启动的开销,需要针对部分厂商ROM做好透明主题的适配,避免出现启动时的闪屏问题。
内容的提问来源于stack exchange,提问作者user1816142

