Android SystemUI QS模块

时间:2024-10-08 10:32:11

下拉菜单增加一个自定义磁贴

1、新建Tile.java。

在\frameworks\base\packages\SystemUI\src\com\android\systemui\qs\tile路径下创建一个类
![](/img_convert/#averageHue=#2d2c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=756&id=uedfdfd84&margin=[object Object]&name=&originHeight=756&originWidth=1059&originalType=binary&ratio=1&rotation=0&showTitle=true&size=113814&status=done&style=none&taskId=uea070926-44af-45e7-a50f-a3ff05249a7&title=新建DesignNewTile&width=1059 “新建DesignNewTile”)

2、添加操作类-controller类。

这边以我复刻的便捷式热点为例,定义了带有QSHost和磁贴的操作类(具体需要的操作看客户需求,自己可以先实现简单的操作,例如长按和单击之后的操作),接口和接口的实现,然后我们的Tile类中即可使用
private final HotspotController mHotspotController;//检索热点和相关信息
private final DataSaverController mDataSaverController;//数据控制
![](/img_convert/#averageHue=#2e2d2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=532&id=bTw0Y&margin=[object Object]&name=&originHeight=532&originWidth=785&originalType=binary&ratio=1&rotation=0&showTitle=false&size=74234&status=done&style=none&taskId=u7f8ef339-e7a5-41d0-997c-1d635454e50&title=&width=785)
HotspotController——HotspotControllerImpl
![](/img_convert/#averageHue=#2f2d2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=379&id=ubd540870&margin=[object Object]&name=&originHeight=379&originWidth=815&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44124&status=done&style=none&taskId=u254ada6d-9ded-428b-badf-1fa5cc795ef&title=&width=815)
![](/img_convert/#averageHue=#2e2c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=691&id=l6JWM&margin=[object Object]&name=&originHeight=691&originWidth=858&originalType=binary&ratio=1&rotation=0&showTitle=false&size=106831&status=done&style=none&taskId=u32639000-ea76-402e-a602-dcf412669b7&title=&width=858)
DataSaverController——DataSaverControllerImpl
![](/img_convert/#averageHue=#2e2c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=811&id=u3b1c52a7&margin=[object Object]&name=&originHeight=811&originWidth=848&originalType=binary&ratio=1&rotation=0&showTitle=false&size=108920&status=done&style=none&taskId=uc71d0461-7e57-423d-8f0b-01c3f22c0f9&title=&width=848)

3、实现QSTileImpl的抽象方法。

QSTileImpl——快速设置Tile基类,继承它以创建一个新Tile。状态管理在主机提供的 Looper 上完成。QS模块应该在 handleUpdateState 中更新状态。影响状态的回调应该使用 refreshState 来触发 tile looper 上的另一个状态更新传递。

a.如果磁贴(Tile)不支持长按,则需要设置()中的参数为false,(),支持长按的话可以去实现对应长按的抽象方法

public abstract Intent getLongClickIntent();
![](/img_convert/#averageHue=#2d2c2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=366&id=u80bca3f5&margin=[object Object]&name=&originHeight=366&originWidth=763&originalType=binary&ratio=1&rotation=0&showTitle=false&size=40693&status=done&style=none&taskId=u7d6db763-e0c5-43fb-b82c-1659b51bf0b&title=&width=763)

b.若tile改变状态时(无论从控制器还是用户点击),模块在handleUpdateState ()方法中更新状态,需要执行刷新状态方法refreshState()触发tile looper上另一个状态更新传递。其中还有状态监听和状态更改可详细查看源码。

![](/img_convert/#averageHue=#2c2c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=273&id=ue640a7a7&margin=[object Object]&name=&originHeight=273&originWidth=817&originalType=binary&ratio=1&rotation=0&showTitle=false&size=41135&status=done&style=none&taskId=ud11f78bf-2e0a-4b84-9410-e72ca4648a7&title=&width=817)
![](/img_convert/#averageHue=#302e2d&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=131&id=ubabde40c&margin=[object Object]&name=&originHeight=131&originWidth=713&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17503&status=done&style=none&taskId=u41ec4311-9ce3-4ecf-abba-88accab46b5&title=&width=713)
![](/img_convert/#averageHue=#2e2c2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=368&id=uba323d48&margin=[object Object]&name=&originHeight=368&originWidth=689&originalType=binary&ratio=1&rotation=0&showTitle=false&size=48994&status=done&style=none&taskId=ucef62c3c-316a-4ec7-b7e3-5a61cb3af91&title=&width=689)
![](/img_convert/#averageHue=#2f2d2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=675&id=u4e7fcbdf&margin=[object Object]&name=&originHeight=675&originWidth=826&originalType=binary&ratio=1&rotation=0&showTitle=false&size=90816&status=done&style=none&taskId=uee065a39-438e-4c7e-a272-e6cb0db67df&title=&width=826)

c.若只是用handleUpdateState修改state,这个方法可以通过polling控制器或者通过修改arg参数实现

![](/img_convert/#averageHue=#3c3f41&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=405&id=uc3d6c1f4&margin=[object Object]&name=&originHeight=405&originWidth=495&originalType=binary&ratio=1&rotation=0&showTitle=false&size=51143&status=done&style=none&taskId=ub26d774d-9ce1-4d75-b745-82d2ef50942&title=&width=495)
![](/img_convert/#averageHue=#312f2d&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=66&id=u890bd40c&margin=[object Object]&name=&originHeight=66&originWidth=638&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8236&status=done&style=none&taskId=u3aa636da-6a2b-49e2-8e72-25067ec1a03&title=&width=638)

d.如果控制器不是一个CallbackController,从控制器通过attaching/dettaching响应handleSetListening

![](/img_convert/#averageHue=#2f2d2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=421&id=u97b207a3&margin=[object Object]&name=&originHeight=421&originWidth=794&originalType=binary&ratio=1&rotation=0&showTitle=false&size=64372&status=done&style=none&taskId=u4dd728fa-9c46-4774-bc28-cf7b5acffb0&title=&width=794)
![](/img_convert/#averageHue=#2e2d2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=392&id=u10b6a78e&margin=[object Object]&name=&originHeight=392&originWidth=659&originalType=binary&ratio=1&rotation=0&showTitle=false&size=47897&status=done&style=none&taskId=u0b4d6316-9724-4332-aea8-6f60bfee252&title=&width=659)

e.实现isAvailable()方法,当Tile不需要被创建的时候设置为false

![](/img_convert/#averageHue=#2d2c2c&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=153&id=u4382ec82&margin=[object Object]&name=&originHeight=153&originWidth=779&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17067&status=done&style=none&taskId=ua16ebf80-7324-4dc9-9070-d42333f046b&title=&width=779)
![](/img_convert/#averageHue=#3c3f41&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=222&id=u14d1857c&margin=[object Object]&name=&originHeight=222&originWidth=500&originalType=binary&ratio=1&rotation=0&showTitle=false&size=28778&status=done&style=none&taskId=u4c1fe095-6a4c-487a-814a-835e75404b8&title=&width=500)

4、QSFactoryImpl中的实现。

a.需要注入对应类型的提供器Provider

![](/img_convert/#averageHue=#322d2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=685&id=u8e6b1c24&margin=[object Object]&name=&originHeight=685&originWidth=770&originalType=binary&ratio=1&rotation=0&showTitle=false&size=185020&status=done&style=none&taskId=u3a24e1f1-4a6e-4216-af08-c627454d1ff&title=&width=770)
![](/img_convert/#averageHue=#312c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=707&id=u8d13e99a&margin=[object Object]&name=&originHeight=707&originWidth=822&originalType=binary&ratio=1&rotation=0&showTitle=false&size=137977&status=done&style=none&taskId=u9896d70a-3add-4117-8e7e-c1e30aeeacd&title=&width=822)

b.为Tile添加唯一字符串

![](/img_convert/#averageHue=#2e2d2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=280&id=u777ac35c&margin=[object Object]&name=&originHeight=280&originWidth=512&originalType=binary&ratio=1&rotation=0&showTitle=false&size=30619&status=done&style=none&taskId=u179ad446-c783-4b2c-96a8-215bd9e415e&title=&width=512)

5、配置属性。

在文件Z:\k630_64\frameworks\base\packages\SystemUI\res\values中的文件中进行一些配置属性的修改,quick_settings_tiles_stock和quick_settings_tiles_default。前者包含所有Tile字符串标签,系统所有和创建的,后者只包含用户定制和所需要的,重置后能得到的。但是这两个配置属性都被overlay中的文件属性覆盖了,我们的手机会先使用overlay中的属性,再去找apk中的配置属性。(属性被覆盖了)
![](/img_convert/#averageHue=#2c2c2b&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=540&id=ua02e0221&margin=[object Object]&name=&originHeight=540&originWidth=1546&originalType=binary&ratio=1&rotation=0&showTitle=false&size=81316&status=done&style=none&taskId=u6109f9dd-4bf5-401c-a0d4-efbc1ce896a&title=&width=1546)
所以我们找到如下overlay的文件夹进行属性的增删
/vendor/tinno/k630_64/trunk/overlay/vendor/partner_gms/overlay/gms_overlay/frameworks/base/packages/SystemUI/res/values/
![](/img_convert/#averageHue=#f9f8f6&clientId=u0ea6c1e7-69fb-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=330&id=u18bb7b34&margin=[object Object]&name=&originHeight=330&originWidth=1912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=45357&status=done&style=none&taskId=uda5df412-303a-40bb-9919-2c7fe0041eb&title=&width=1912)

PS:ADB测试方法。

还有一种测试方法就是通过ADB的方式put进去属性,查看是否添加成功。如果java代码中的config文件夹已修改,但是不生效,可以通过ADB看看属性。其实我们也可以很清楚的看到磁贴的顺序和java代码中的config文件有所不同,overlay中的属性能够一一对应,这下就明朗了。
ADB命令:(通过以下命令查看效果)
adb shell settings get secure sysui_qs_tiles //获取tile字符
adb shell settings put secure sysui_qs_tiles wifi,singlehand,bt,dnd,lte1,lte2,flashlight,rotation,battery,cell,airplane,cast,screenrecord,dataswitch //put写入tile字符