一)需求场景
实现HDMIN插入后自启HDMIN对应的app
针对需求讲一下实际应用:
- 机器开启自启某个服务:单独apk 实现了某些功能但是没有界面,在服务里面。那么开机实现自启功能。
- 开启检测外设,实现如果插入就调用对应的app:比如 开启自启HDMIN软件,在HDMIN线接入情况下,定时检测,然后打开HDMIN、投屏;
- 在接入HDMIN线情况下打开HDMIN、投屏软件;在插入U盘情况下 打开U盘歌曲等。
二)掌握技能
通过这篇总结,必须了解 驱动节点检测技能。驱动节点可以理解为驱动映射的文件,这个文件写入值提供给上层判断状态。
应用端驱动节点检测与设置
应用中,如何了解硬件状态,通过直接读取GPIO口数据,涉及到读取文件方式而已。通过什么方式来读写呢?不就是通过流方式吗,下面给出工具类。
StreamUtils.kt 通过流的方式读取和写入
FileUtils.java 通过流的方式读取和写入
不同的平台,如果有root 权限,且shell 环境,是可以通过 echo 来进行写入设置状态,比如如下:
"echo 1 > sys/devices/platform/bt_pwr/bt_pwr";
工具类已经打包上传,可下载参考:
Framework开机自启服务-应用-自动执行-循环检测功能
framework 驱动节点检测与设置
类比应用端是一个机制的,只不过环境放在了Framework层或者系统应用层来实现,和应用端其实是一摸一样的。
读取:循环读取值,监控值的状态
设置:通过流的方式设置值。参考工具类:FileUtils.java
writeFileString readFileContent 方法
工具类已经打包上传,可下载参考:
Framework开机自启服务-应用-自动执行-循环检测功能
三)方案思路
- 循环检测HDMIN状态,判断HDMIN线是否插入,如果插入启动HDMIN对应的app
- 循环检测机制放在哪里呢? 那就放在系统服务里面,自己可以考虑放在哪个服务里面而已。
自己最近在处理SystemUI相关,那就放在SystemUI服务里面吧? 具体放在哪个服务呢?哈哈,那就放到入口服务吧:
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\SystemUIService.java
SystemUIService 系统启动,在这个服务里面启动所有的相关服务:
public void startServicesIfNeeded() {
String[] names = SystemUIFactory.getInstance().getSystemUIServiceComponents(getResources());
startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
}
对SystemUI的了解,建议参考以前的博文,基本了解下SystemUI基本内容:
参考文章截屏功能添加中的资料参考:Android12 SystemUI QS面板新增截屏功能
四)实际项目案例
HDMIN线插入后自启对应应用
onCreate 方法中 循环检查HDMIN状态,开启线程 判断当前顶层app,如果不是投屏 HDMIN相关app,那么就启动。
// wangfangchen add
Log.d(SystemUIApplication.TAG," to heckHDminHandler:");
checkHDminHandler.removeCallbacksAndMessages(null);
checkHDminHandler.postDelayed(checkHDMINState,5000);
// wangfangchen end
// wangfangchen add
Runnable checkHDMINState=new Runnable() {
@Override
public void run() {
Log.d(SystemUIApplication.TAG," to check hdmin");
String hdminStatePath = "/sys/class/fise_hdmiin_state_irq/fise_hdmiin_state_irq_enable";
try {
String hdMinState = com.android.systemui.util.Utils.read(hdminStatePath);
Log.d(SystemUIApplication.TAG,"hdMinState ="+hdMinState);
if(hdMinState == null || hdMinState.toString().trim().equals("")){
Log.d(SystemUIApplication.TAG,"=== hdMinState is null continue to check ");
checkHDminHandler.removeCallbacksAndMessages(null);
checkHDminHandler.postDelayed(checkHDMINState,6000);
return;
}
Log.d(SystemUIApplication.TAG," hdMinState:"+hdMinState);
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = activityManager.getRunningAppProcesses();
if (runningProcesses != null && !runningProcesses.isEmpty()) {
ActivityManager.RunningAppProcessInfo topProcess = runningProcesses.get(0);
String packageName = topProcess.processName;
Log.d(SystemUIApplication.TAG,"==="+ packageName+" hdMinState:"+hdMinState);
if(hdMinState.endsWith("0")&&!packageName.equals("aaa.abc.camera")&&
!packageName.equals("com.google.android.setupwizard")&&!packageName.equals("com.google.android.gms")
){
launchApp(getApplicationContext(),"aaa.abc.camera");
}
}
} catch ( Exception e) {
e.printStackTrace();
}
checkHDminHandler.postDelayed(this,6000);
}
};
public static void launchApp(Context context, String packageName) {
try {
Intent intent = new Intent();
PackageManager packageManager = context.getPackageManager();
intent = packageManager.getLaunchIntentForPackage(packageName);
if (null != intent) {
context.startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// wangfangchen end
开机后弹出悬浮菜单
参考我自己的博文,和这个就是一摸一样的实现方案了。
系统实现悬浮窗-菜单-悬浮按钮功能