android通过广播设置默认启动器

摘要:android允许用户选择默认的启动器,满足各类业务使用场景。如果不加launcher属性,只要是有activity界面的app均能设置为默认启动器。本文通过广播的方式,内部调用设置默认启动器的流程,并且可以选择是否直接启动来实现。

1.预研

博主使用的是sprd平台/android 10的代码,通过对于原生设置默认启动器的代码追踪,定位实现方案放在PermissionController中。
PermissionController官方文档

2.定义广播并添加收发权限

Index: packages/apps/PermissionController/AndroidManifest.xml
===================================================================
--- packages/apps/PermissionController/AndroidManifest.xml	(版本 1951)
+++ packages/apps/PermissionController/AndroidManifest.xml	(版本 1965)
@@ -307,6 +307,13 @@<receiver android:name="com.android.packageinstaller.incident.ApprovalReceiver"android:exported="false" />+        <receiver android:name="com.android.permissioncontroller.role.service.SetDefaultHomeAppReceiver"
+                  android:exported="true">
+           <intent-filter>
+                <action android:name="android.intent.action.SET_DEFAULT_HOME_APP" />
+            </intent-filter>
+        </receiver>
+</application></manifest>

后台允许广播收发权限可以自行定位代码,此处仅做记录。

Index: frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
===================================================================
--- frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java	(版本 1951)
+++ frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java	(版本 1965)
@@ -90,6 +90,8 @@sBackgroundActionWhiteListArraySet.add("android.intent.action.SET_DEFAULT_HOME_APP");}

3.方案实现

设置前判断app是否已安装,是否符合默认启动器规则。
设置完成后通过boolean extra决定是否直接启动。

Index: packages/apps/PermissionController/src/com/android/packageinstaller/role/service/SetDefaultHomeAppReceiver.java
===================================================================
--- packages/apps/PermissionController/src/com/android/packageinstaller/role/service/SetDefaultHomeAppReceiver.java	(不存在的)
+++ packages/apps/PermissionController/src/com/android/packageinstaller/role/service/SetDefaultHomeAppReceiver.java	(版本 1965)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.role.service;
+
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Process;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.packageinstaller.role.model.Role;
+import com.android.packageinstaller.role.model.Roles;
+import com.android.packageinstaller.role.ui.DefaultAppViewModel;
+
+import java.util.List;
+
+/**
+ * {@link BroadcastReceiver} to reset default home app.
+ */
+public class SetDefaultHomeAppReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "SetDefaultHomeAppReceiver";
+
+    private DefaultAppViewModel mViewModel;
+
+    @Override
+    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
+        String action = intent.getAction();
+
+        String packageName = intent.getStringExtra("packageName");
+        if (packageName == null) {
+            Log.d(TAG, "onReceive::invalid parameter!");
+            return;
+        }
+        if (!isPackageExist(context, packageName)) {
+            Log.d(TAG, "onReceive::package: " + packageName + " is not exist!");
+            return;
+        }
+        if (!isHomeApp(context, packageName)) {
+            Log.d(TAG, "onReceive::package: " + packageName + " is not home app!");
+            return;
+        }
+        Log.d(TAG, "onReceive::set default home app: " + packageName);
+        Role role = Roles.get(context).get("android.app.role.HOME");
+        CharSequence confirmationMessage = role.getConfirmationMessage(packageName, context);
+        if (confirmationMessage != null) {
+            // do nothing.
+        } else {
+            Application application = (Application) context.getApplicationContext();
+            mViewModel = new DefaultAppViewModel(role, Process.myUserHandle(), application);
+            setDefaultApp(packageName);
+
+            if (intent.getBooleanExtra("startActivity", true)) {
+                launchHomeActivityByPackageName(context, packageName);
+            }
+        }
+    }
+
+    private void setDefaultApp(@NonNull String packageName) {
+        mViewModel.setDefaultApp(packageName);
+    }
+
+    public boolean isPackageExist(Context context, String targetPackage) {
+        PackageManager packageManager = context.getPackageManager();
+        try {
+            packageManager.getPackageInfo(targetPackage, PackageManager.GET_ACTIVITIES);
+            return true;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    public boolean isHomeApp(Context context, String packageName) {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addCategory(Intent.CATEGORY_DEFAULT);
+ 
+        PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> resolveInfos = pm.queryIntentActivities(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            if (resolveInfo.activityInfo.packageName.equals(packageName)) {
+                return true;
+            }
+        } 
+        return false;
+    }
+
+    private void launchHomeActivityByPackageName(Context context, String packageName) {
+        PackageManager packageManager = context.getPackageManager();
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+ 
+        List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(homeIntent, 0);
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            if (resolveInfo.activityInfo.packageName.equals(packageName)) {
+                ActivityInfo activityInfo = resolveInfo.activityInfo;
+                ComponentName componentName = new ComponentName(activityInfo.applicationInfo.packageName, activityInfo.name);
+                Intent intent = new Intent(Intent.ACTION_MAIN);
+                intent.addCategory(Intent.CATEGORY_LAUNCHER);
+                intent.setComponent(componentName);
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivity(intent);
+                return;
+            }
+        }
+
+        Log.d(TAG, "No home activity found for package: " + packageName);
+    }
+}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19343.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java SE】JDBC

JDBC&#xff08;Java DataBase Connectivity&#xff09;是一套用于在 Java 中操作关系型数据库的 API。它允许开发者使用统一的 Java 代码来访问不同的关系型数据库。 JDBC 的本质&#xff1a;JDBC 是由官方&#xff08;Sun 公司&#xff09;定义的一套接口规范&#xff0c;…

西电数据库课设|设计学籍管理系统

前言&#xff1a;ER图和逻辑结构图不准确&#xff0c;因为在后期实际建表的过程中有改动&#xff0c;去除了一些列和外键关系&#xff0c;但是我懒得返回去改图了&#xff0c;所以还是需要自己情况画图&#xff0c;还有学生信息我忘记加性别什么的&#xff0c;这个比较简单&…

优维HAO案例:500强旗下全牌照综合性券商CMDB平台项目

撰文&#xff1a;鹿小U / 制图&#xff1a;脾气超好 某中国500强集团旗下的HS公司&#xff0c;是一家具有一定行业影响力的综合性证券公司。在近年来的发展进程中&#xff0c;该公司坚定不移地持续推进财富管理转型工作&#xff0c;将 ETF 的财富管理以及机构经纪业务作为公司…

github进不去解决办法-误打误撞进去了

我的要求不高&#xff0c;就算麻烦&#xff0c;只要能进去就行&#xff0c;但是我找了很多的办法&#xff0c;xbox下载助手、watt Toolkit、更改host文件、fastgithub…最终还是没有用 绝望之际随便进了一个当时找的fastgithub连接 结果显示不是专用链接 然后看了该博主的文章…

RHCE——WEB服务器的部署及优化

URL组成 <scheme>://<user>:<password><host>:<port>/<path>:<params>?<query>#<frag> scheme 方案 访问服务器以获取资源时要使用哪种协议 user 用户 某些方案访问资源时需要的用户名 pass…

day03(单片机高级)RTOS

目录 RTOS(实时操作系统) 裸机开发模式 轮询方式 前后台&#xff08;中断方式&#xff09; 改进&#xff08;前后台&#xff08;中断&#xff09;&#xff09;定时器 裸机进一步优化 裸机的其他问题 RTOS的概念 什么是RTOS 为什么要使用 RTOS RTOS的应用场景 RTOS的…

基于SSM的毕业论文管理系统【附源码】

基于SSM的毕业论文管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统结构设计 4.2 系统顺序图设计 4.3 系统数据库设计 5 系统的实现 5.1 登录模块的实现 5.2 学生管理模块的实现 5.3 导师管理模块的实现 5.4 课题管理模块的实现 …

擎耀数字车灯CAN/LIN总线网络定向数据采集控制解决方案实施流程

2024年是数字车灯崛起的元年&#xff0c;随着车辆的智能化和网络化程度不断提高&#xff0c;车载网络系统&#xff08;如CAN总线&#xff09;成为连接各个电子控制单元&#xff08;ECU&#xff09;的重要纽带。车灯作为车辆重要的安全组件之一&#xff0c;其工作状态直接影响到…

【C++之STL】摸清 string 的模拟实现(上)

文章目录 1. 为什么要模拟实现&#xff1f;2. 基本框架搭建3. 构造函数3. 1 默认构造/from c_str3. 2 拷贝构造3. 2. 1 深浅拷贝 3. 3 fill3. 4 迭代器区间构造 4. 容量操作4. 1 size()和capacity()和empty()4. 2 clear()4. 3 resize()4. 4 reserve() 1. 为什么要模拟实现&…

视频直播5G CPE解决方案:ZX7981PG/ZX7981PMWIFI6网络覆盖

方案背景 视频直播蓬勃发展的当下&#xff0c;传统直播网络联网方式的局限性越来越明显。目前传统直播的局限性主要集中在以下几个方面&#xff1a; 传统直播间网络架构条件有限&#xff0c;可连接WIFI数量少&#xff0c;多终端同时直播难以维持&#xff1b;目前4G网络带宽有限…

input file结合vue3和vant实现上传图片效果,并显示上传进度百分比%

这里写自定义目录标题 采用的dom结构是input file&#xff0c;label事件绑定&#xff0c;一下为代码传入参数为uploadNum实现效果如图上传中&#xff0c;图片1上传成功&#xff0c;图片2 采用的dom结构是input file&#xff0c;label事件绑定&#xff0c;一下为代码 传入参数为…

SELECT 语句详解

开发准备 注:如果你是从上一节直接进入本节进行学习的,请先删除上一节建立的数据库mysql_shiyan,删除语句为DROP DATABASE mysql_shiyan;。在正式开始本实验内容之前,需要先下载相关数据库表,搭建好一个名为mysql_shiyan 的数据库(有三张表:department,employee,projec…

重力传感器算法概述!

一、核心技术 高精度重力测量技术&#xff1a; 无人机重力传感器的核心技术之一是能够高精度地测量重力加速度数据。这通常依赖于先进的传感器设计和制造工艺&#xff0c;以确保传感器具有高度的灵敏度和稳定性。 例如&#xff0c;中国船舶第七〇七研究所自主研发的低空重力…

炼码LintCode--数据库题库(级别:中等;数量:更新中~)--刷题笔记_03

目录 炼码LintCode--数据库题库&#xff08;级别&#xff1a;中等&#xff1b;数量&#xff1a;更新中~&#xff09;--刷题笔记_033617 更换连续两个人的座位&#xff08;case when&#xff09;题&#xff1a;sql&#xff1a;解释&#xff1a; 3615 数据中位数&#xff08;窗…

【stm入门学习SPI_铁头山羊系列教程】

stm入门学习SPI_铁头山羊教程 1.SPI总线1.电路结构与通信协议2.SPI的特点&#xff1a;3. 极性 相位4. 4中时钟模式5. 比特位的传输模式6.数据宽度 2. SPI引脚IO引脚初始化 1.SPI总线 1.电路结构与通信协议 主机向从机NSS引脚发送低电压&#xff0c;选中该从机。 主机通过向MOS…

RK3568平台开发系列讲解(platform虚拟总线驱动篇)实验:点亮一个LED

🚀返回专栏总目录 文章目录 一、设备树二、平台驱动三、应用沉淀、分享、成长,让自己和他人都能有所收获!😄 📢xxx 程序编写的主要内容为添加 LED 灯的设备树节点、在驱动程序中使用 of 函数获取设备节点中的属性,编写测试应用程序。 • 首先向设备树添加 LED 设备节点…

Spring Boot 与腾讯云 MySQL 监听 Binlog 数据变化,并使用 UI 展示页面效果

引言 在现代的分布式系统和微服务架构中&#xff0c;数据同步和变更监控是保证系统一致性和实时性的核心问题之一。MySQL 数据库的 binlog&#xff08;二进制日志&#xff09;功能能够记录所有对数据库的修改操作&#xff0c;如插入&#xff08;INSERT&#xff09;、更新&…

菜鸟驿站二维码/一维码 取件识别功能

特别注意需要引入 库文 ZXing 可跳转&#xff1a; 记录【WinForm】C#学习使用ZXing.Net生成条码过程_c# zxing-CSDN博客 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static System.Net.…

PlantUML——时序图

PlantUML时序图 背景 时序图&#xff08;Sequence Diagram&#xff09;&#xff0c;又名序列图、循序图&#xff0c;是一种UML交互图&#xff0c;用于描述对象之间发送消息的时间顺序&#xff0c;显示多个对象之间的动态协作。时序图的使用场景非常广泛&#xff0c;几乎各行各…

算法——链表相交(leetcode23)

链表相交这题就是找出两个相交链表相交的节点并返回 如上图假设上方第一个节点是链表A的头结点下方第一个节点是链表B的头结点 解法有以下两种 方法一(移动长链表指针后同步移动两个链表的指针直至相等) 也就是先遍历链表A和链表B的长度接着得到链表A和B长度的差值然后领长链…