一、前言
在Android16车载定制项目中,产品需求:在应用列表新增独立投屏快捷图标,点击直达系统投屏设置;若系统裁剪投屏模块,自动降级跳转到WiFi/蓝牙无线设置。 本次通过新增中转Activity+注册桌面入口的轻量方案实现,改动仅5个文件,无侵入原有桌面逻辑,兼容原生AOSP、精简车载固件。
二、Patch整体变更清单
- 新增矢量图标:ic_cast.xml(未连接投屏)、ic_cast_connected.xml(投屏已连接)
- 新增中转页面:CastShortcutActivity.java(无UI,仅做跳转分发)
- 修改AndroidManifest.xml:注册LAUNCHER桌面图标入口
- 修改strings.xml:增加多语言投屏名称文本
变更文件列表:vendor/partner_gms/
apps/SearchLauncher/AndroidManifest.xml
apps/SearchLauncher/quickstep/res/drawable/ic_cast.xml(新建)
apps/SearchLauncher/quickstep/res/drawable/ic_cast_connected.xml(新建)
apps/SearchLauncher/quickstep/src/com/android/searchlauncher/CastShortcutActivity.java(新建)
apps/SearchLauncher/res/values/strings.xml
三、分文件完整修改逻辑
3.1 res/values/strings.xml:新增图标显示文字
修改逻辑
单独定义投屏名称字符串资源,统一管理、支持多语言包翻译,不硬编码文字。
修改片段
<!-- 原有内容省略 -->
<!-- Cast shortcut icon label
投屏快捷方式图标下方展示文字,Launcher读取label字段渲染 -->
<string name="cast_app_name">Cast</string>
3.2 新增矢量图标 ic_cast.xml(默认未投屏状态)
修改逻辑
遵循Android 24dp标准系统图标规范,矢量图适配所有分辨率;黑色图标作为桌面默认展示图标,预留连接状态图标用于后续动态切换。
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 The Android Open Source Project
开源协议声明,AOSP所有资源必须携带版权头
Licensed under the Apache License, Version 2.0
-->
<!-- vector矢量图标根标签,适配dp缩放,无像素模糊 -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" <!-- 图标标准宽24dp,系统快捷图标统一尺寸 -->
android:height="24dp" <!-- 图标标准高24dp -->
android:viewportWidth="24.0" <!-- 矢量画布逻辑宽度 -->
android:viewportHeight="24.0"><!-- 矢量画布逻辑高度 -->
<!-- 投屏图形路径,黑色填充,未连接投屏默认样式 -->
<path
android:fillColor="#FF000000"
android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z" />
</vector>
3.3 新增矢量图标 ic_cast_connected.xml(投屏连接状态)
修改逻辑
图形轮廓和默认图标完全一致,仅修改填充色为白色;预留资源,后续可监听投屏连接状态动态替换图标,本次Patch暂未做状态切换逻辑。
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 The Android Open Source Project
Apache开源版权声明
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" <!-- 图标尺寸和默认图标保持统一 -->
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<!-- 投屏连接成功白色样式,填充色引用系统白色 -->
<path
android:fillColor="@android:color/white"
android:pathData="M19,7H5v1.63c3.96,1.28 7.09,4.41 8.37,8.37H19V7zM1,14v2c2.76,0 5,2.24 5,5h2C8,17.13 4.87,14 1,14zM1,10v2c4.97,0 9,4.03 9,9h2C12,14.92 7.07,10 1,10zM21,3H3C1.9,3 1,3.9 1,5v3h2V5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2V5C23,3.9 22.1,3 21,3" />
</vector>
3.4 核心中转页面 CastShortcutActivity.java(新增文件)
修改逻辑
- 无布局、无界面,仅作为中转跳板;
- 跳转逻辑对齐SystemUI下拉状态栏投屏Tile长按行为,统一产品交互;
- 增加异常捕获,兼容裁剪固件(无Cast设置页面),自动降级无线设置;
- 跳转后立即finish,不占用Activity返回栈,无残留页面。
CastShortcutActivity 完整源码
/*
* Copyright (C) 2024 The Android Open Source Project
* AOSP标准开源版权头
* Licensed under the Apache License, Version 2.0
*/
package com.android.searchlauncher;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
/**
* 投屏快捷方式中转Activity
* 功能:桌面点击Cast图标后,跳转系统投屏设置
* 对齐SystemUI QS面板投屏Tile长按交互逻辑
* 无任何UI界面,透明中转,跳转后自动销毁自身
*/
public class CastShortcutActivity extends Activity {
/**
* Activity生命周期入口,所有跳转逻辑写在此处
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 1. 优先跳转系统原生投屏设置页面
// Settings.ACTION_CAST_SETTINGS 系统标准投屏设置Action
Intent castIntent = new Intent(Settings.ACTION_CAST_SETTINGS);
// FLAG_ACTIVITY_NEW_TASK:新开任务栈,不依附当前桌面栈
// FLAG_ACTIVITY_CLEAR_TOP:清空目标页面之上所有页面,简化返回栈
castIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
// 尝试启动投屏设置
startActivity(castIntent);
} catch (Exception e) {
// 异常捕获场景:固件裁剪投屏模块、无投屏硬件、GMS缺失
// 降级方案:跳转到无线设置(WiFi/蓝牙,间接满足投屏需求)
Intent fallbackWifiIntent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
fallbackWifiIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(fallbackWifiIntent);
}
// 跳转完成,立即销毁当前中转Activity
// 用户返回时直接回到桌面,不会出现空白中转页面
finish();
}
}
3.5 AndroidManifest.xml 注册桌面快捷入口(关键修改)
修改逻辑
通过MAIN + LAUNCHER标准intent-filter,告知系统在应用列表生成独立图标; 配置透明无标题主题,隐藏空白中转页面; exported=true允许Launcher组件读取该图标信息。
修改片段
<!-- 原有Activity省略 -->
<!-- Cast Shortcut Activity
投屏快捷方式注册配置,桌面图标生成核心配置
-->
<activity
<!-- 对应我们新建的中转Activity完整类名 -->
android:name="com.android.searchlauncher.CastShortcutActivity"
<!-- 图标下方展示文字,引用strings资源 -->
android:label="@string/cast_app_name"
<!-- 桌面展示图标,使用默认未连接投屏矢量图 -->
android:icon="@drawable/ic_cast"
<!-- 允许外部组件(Launcher)访问此页面,必须配置true -->
android:exported="true"
<!-- 透明无标题主题,中转页面不需要显示任何UI,避免黑屏弹窗 -->
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<!-- LAUNCHER过滤器:系统识别此Activity为桌面可展示应用图标 -->
<intent-filter>
<!-- 应用启动标准Action -->
<action android:name="android.intent.action.MAIN" />
<!-- 标记需要在Launcher应用列表展示图标 -->
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
四、完整业务执行流程(时序拆解)
- 系统编译打包,解析SearchLauncher的AndroidManifest;
- 识别携带
MAIN+LAUNCHER过滤器的CastShortcutActivity; - Launcher桌面加载全部应用,列表自动渲染:图标ic_cast、文字Cast;
- 用户点击桌面Cast图标,系统启动透明中转Activity;
- Activity onCreate执行跳转逻辑:
- 存在投屏模块:打开投屏设置页面;
- 固件裁剪投屏:捕获异常,跳转无线设置;
- 中转页面执行finish()销毁;
- 用户返回按键直接回到桌面,无空白中转页残留。
将图标添加到桌面Hotseat-101中


五、方案优缺点分析
优势
- 轻量化低侵入:仅新增中转页面,不修改原有Launcher桌面、Quickstep逻辑,无回归风险;
- 交互统一:跳转逻辑复用系统原生Action,和下拉状态栏投屏按钮行为完全一致;
- 高兼容适配:异常降级逻辑兼容无GMS、无投屏硬件、精简车载固件;
- 资源解耦:图标、文字、跳转逻辑分层,后续修改仅改动对应文件;
- 无权限额外申请:跳转系统设置属于普通应用权限,不需要platform签名、priv-app特权。
待扩展优化点(可二次开发)
- 增加投屏状态监听(MediaRouter),动态切换ic_cast/ic_cast_connected图标;
- 增加权限预校验,无WiFi权限时弹出提示弹窗;
- 支持桌面长按快捷菜单;
- 补充多语言strings翻译包;
- 支持分屏、车载副屏适配。