注册

Android通知栏适配调研-放弃RemoteViews

问题描述:


项目的通知栏的RemoteViews背景图有些厂商颜色不对,需要一个适配方案,来适配所有机型。


项目现状:


目前的方案是,创建一个新的通知,通过这个通知来获取底色。


image.png


其中有一个字段是获取是否是暗黑模式,这段代码是先用按位或忽略掉透明度,系统的字体颜色不会有特别高的同名度,所以这里理论上没什么问题,然后计算两个三维向量的距离,距离越近,颜色越接近。


image.png


这里是有误差的,目标向量距离灰色向量rgb(127.5,127.5,127.5)的最大值约为220,而不是180,就会造成纯白色rgb(255,2555,255)的标题字体颜色,理应是黑色背景才能看到,但却被识别成非暗黑模式。


image.png


误判了暗黑模式,这里的背景就颜色就会出问题了。


image.png


目前项目的解决方案是通过设置RemoteViews的background颜色去做,这里需要适配的问题由RemoteViews实现机制产生:RemoteViews被设计具有跨进城通信的属性,通过Binder传递到SystemService进程,根据它的包名来拿相应的应用的资源,为了提高效率,系统没有直接通过Binder去支持所有的View和View操作,那这里对普通view生效的xml属性,很有可能厂商对系统修改源码后没有完全的适配,可能就不能对其全部生效。


比如对android:background属性进行设置在部分机型上就不会生效,但下面这段代码可以。


RemoteView?.setInt(R.id.ll_root, "setBackgroundColor", ContextCompat.getColor(context, R.color.color_367AF6))

接下来来看项目如何设置颜色。


image.png


然后来看拿到暗黑模式的布尔字段后,会设置为#FFFFFFFF/#00000000这两个颜色,这两个颜色都是有问题的,首先暗黑模式情况下,#00000000(百分百透明的黑色)不一定会正确解析为透明色,类似问题为启动icon解析时,透明色解析为黑色背景,具体还要观察各厂商系统对源码的修改。


image.png


#FFFFFFFF这个颜色也是不对的,不是每个通知栏的背景都是白色,而且这个颜色也不一定会作为背景色,下面鸿蒙系统上就没有生效为白色。


image.png


来观察下不同时期的通知样式,可以发现不是每个时期都是固定颜色底色,有白有黑有灰,那就要动态的获取背景色来设置RemoteVies的背景色,下图以安卓1-7为示例。


image.png


接着还要考虑不同的系统版本对Notification的改动,如安卓8.0以上加入了Channel这一特性,项目的通知最后是要有一步渠道检查的。这里或许要额外对安卓13的有权限上的适配。


image.png


同时如果要考虑通知栏高度的问题的话,以安卓12为例,自定义通知的显示区域比安卓11有调整,折叠态高度上限为64dp,展开时高度上限为256dp,且系统强制显示通知的小图标。所以要考虑到ui层面对高度是否有要求,再来适配各个版本的RemoteViews的高度。下图为展开时示例。


image.png


以上,这个方案做不到适合所有机型,要适配所有机型确实是不是个简单的事情。


尝试过程:


核心问题为RemoteViews的背景色不能完美适配所有厂商。首先原安卓系统(非厂商自定义)不需要对其有特定的设置,自动跟随主题颜色;厂商自定义安卓系统,则各不相同,如小米则不会自动更改RemoteViews的颜色。


首先尝试获取背景色,我开始的尝试方式是沿用之前的方式,即build一个Notification,通过遍历其中的text,发现不是所有的都能拿到,参考其他文章列出的类似的表格如下:



虎牙项目目前的方案是,如果没拿到字体,默认就是字体为黑色,这个方法安卓7.0之后就失效了。安卓7.0+修改了Notification,采用 @android:color/primary_text_dark已经获取不到颜色值了。


那既然不能完美解决,这里我使用反编译工具,观察各厂商的逆向工程(以小米为例),这里需要花费大量的时间来阅读源码(前公司的代码真的看不懂= =),最后看到其他文章给出一个方案是在manifest加上这一句才会生效。


<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
复制代码

以上,RemoteViews的确拥有高自定义ui的特性,但很难找到一个方案来适配所有国内厂商的机型,因为Google设计通知栏,或者说其他任何的系统组件的伊始就没考虑过自定以rom的因素。



解决方案:


1.  不使用RemoteViews,改用其他方案解决


2.  使用RemoteViews


先说第一个,如果仅仅是虎牙目前的通知栏用途的话,确实没有使用复杂ui,使用RemoteViews的收益好像不足以掩盖bug多这个缺点。直播间的通知栏提醒完全可以用addAction方法来代替:


image.png


其他简单场景的情况下:



第二个,如果坚持使用RemoteViews,基本上网络上大部分的相关的文章我都翻过了,我也没看到业界更好的办法,大概只能反编译去看看抖音和微信是怎么做的吧。


作者:刘某的前端日记
链接:https://juejin.cn/post/7205025712171302973
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册