MTKAndroid12-13-开机应用自启功能实现
开机自启指定应用需求实现:最近有个有个客户提到这样的需求,私下自己折腾实现下
文章目录
- 思路
- 参考资料
- 实现方案
- 源码修改文件路径
- 源码具体修改内容
- 源码解读分析
- 配置文件 Manifest.xml
- 启动类-QuickstepLauncher
- BaseQuickstepLauncher
- 熟悉的- Launcher
- Launcher 配置熟悉理解
- Launcher onCreate
- 思考
- 验证
- 总结
思路
- 基本上大家思路都是监听开机广播 RECEIVE_BOOT_COMPLETED ,然后在开机广播里面启动自己或者启动别的app。 或者 系统Launcher 是客户自己做得情况下,自己在Launcher 里面启动指定的app
- 如果系统是用的Launcher3,那么就在Launcher 启动地方添加启动指定app 逻辑。 设置指定app 逻辑可以在任何地方实现。设定的值和launcher3 有一个数据共享即可。
方案一: 是应用来实现的,如果仅仅是监听开机广播,好处是不用借助于系统。弊端是:不同平台不同Android版本,开机广播发送并不一定及时或者收不到或者多次发送,总有一些小bug.
方案二: 需要借助于系统Launcher3来实现了
参考资料
参考资料不一定对解决当前需求、问题有用。但是如果是初学开发者,还是希望且有必要在解决问题同时,了解最基本原理,熟悉最基本的业务逻辑和应用框架。
Launcher3 相关资料参考
菜鸟成长之路-源码分析专栏
Android Launcher3 简介
Launcher3 高端定制
Launcher3 开发
Launcher3 Android Code Search在线源码查看
Launcher3 xref 在线源码查看
Launcher3 RK 源码查看
Launcher3 解析
Launcher3 AndroidP AS版本
谷歌Launcher3 Android13源码修改
Launcher3 和 Launcher3QuickStep 区别
Android14 不分Launcher3修改
Launcher3 LoaderTask 的数据加载
Android14 浅析Launcher
Android O Launcher3-Workspace加载
Framework 层Settings.System, Settings.Secure和Settings.Global存储及应用
实现方案
核心思想就是在Launcher onCreate 方法里面,读取客户设置的应用包名值,如果存在就获取包名的intent,然后跳转过去。
源码修改文件路径
/vendor/mediatek/proprietary/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
源码具体修改内容
在Launcher.java 的onCreate 方法中,添加如下内容:
Log.e(TAG, "onCreate modify start ");String ziQiAppPkg = "";try {ziQiAppPkg = Settings.Secure.getString(this.getContentResolver(),"ziQiAppPkg");} catch (Exception e) {Log.d(TAG," Exception shezhi moren value kong zifuchuan ");Settings.Secure.putString(this.getContentResolver(),"ziQiAppPkg","");e.printStackTrace();}Log.e(TAG, "onCreate ziQiAppPkg value:"+ziQiAppPkg);if(TextUtils.isEmpty(ziQiAppPkg)){Log.e(TAG, "onCreate ziQiAppPkg no value:");}else{Intent launchIntent = getPackageManager().getLaunchIntentForPackage(ziQiAppPkg);if (launchIntent != null) {Log.e(TAG, "onCreate zhunbei start app value:"+ziQiAppPkg);startActivity(launchIntent);} else {Log.d(TAG," app pkg:"+ziQiAppPkg+" zanwei anzhuang");} }Log.e(TAG, "onCreate modify end ");
截图如下:
源码解读分析
配置文件 Manifest.xml
在首页先获取当前到底是什么界面Activity ,然后去配置文件看看相关信息
DisPlay:/ $ dumpsys activity top | grep ACTIVITYACTIVITY com.android.settings/.SubSettings 8877f54 pid=1447ACTIVITY com.android.launcher3/.uioverrides.QuickstepLauncher 25cc517 pid=1526
那么就去Manifest 配置文件中看看配置信息:这个Activity 配置了 HOME 属性,那应该就是这个Activity了
<!--Main launcher activity. When extending only change the name, and keep all theattributes and intent filters the same--><activityandroid:name="com.android.launcher3.uioverrides.QuickstepLauncher"android:launchMode="singleTask"android:clearTaskOnLaunch="true"android:stateNotNeeded="true"android:windowSoftInputMode="adjustPan"android:screenOrientation="unspecified"android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"android:resizeableActivity="true"android:resumeWhilePausing="true"android:taskAffinity=""android:exported="true"android:enabled="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.MONKEY"/><category android:name="android.intent.category.LAUNCHER_APP" /></intent-filter><meta-dataandroid:name="com.android.launcher3.grid.control"android:value="${packageName}.grid_control" /></activity>
启动类-QuickstepLauncher
查看类声明:
类声明 public class QuickstepLauncher extends BaseQuickstepLauncher {
从类上面看,并没有onCreate 方法,一些基本的View / service 相关方法
那就看父类 操作 BaseQuickstepLauncher
BaseQuickstepLauncher
看一下类声明:
看类说明如下:扩展 Launcher ,提供特别的具体的功能。 这里简单看下,暂不扩展讨论
/*** Extension of Launcher activity to provide quickstep specific functionality*/
public abstract class BaseQuickstepLauncher extends Launcherimplements NavigationModeChangeListener {
熟悉的- Launcher
这里就是我们熟悉的Launcher了,好多需求和源码分析都是从这里分析的。
Launcher 配置熟悉理解
看Manifest.xml 配置的Home 属性
备注:为什么好多源码分析都是从这里分析的,一方面这里确实是入口、且它也有自己的Menifest 配置的Home 属性。但是部分Launcher的配置,这个类并没有配置Activity,而是作为一个父类来展开的。比如我们通过以下名称查看Launcher 顶层Activity:
DisPlay:/ $ dumpsys activity top | grep ACTIVITYACTIVITY com.android.settings/.SubSettings 8877f54 pid=1447ACTIVITY com.android.launcher3/.uioverrides.QuickstepLauncher 25cc517 pid=1526
但是我们看到Manifest.xml 里面Launcher也有配置,为啥我们adb 启动Launcher 时候,无法启动 找不到。如下:
E:\work\yuanma\android12\Launcher3>adb shell am start -n com.android.launcher3/.Launcher
Starting: Intent { cmp=com.android.launcher3/.Launcher }
Error type 3
Error: Activity class {com.android.launcher3/com.android.launcher3.Launcher} does not exist.E:\work\yuanma\android12\Launcher3>adb shell am start -n com.android.launcher3/com.android.launcher3.Launcher
Starting: Intent { cmp=com.android.launcher3/.Launcher }
Error type 3
Error: Activity class {com.android.launcher3/com.android.launcher3.Launcher} does not exist.E:\work\yuanma\android12\Launcher3>adb shell am start -n com.android.launcher3/com.android.launcher3.Launcher
Starting: Intent { cmp=com.android.launcher3/.Launcher }
Error type 3
Error: Activity class {com.android.launcher3/com.android.launcher3.Launcher} does not exist.
那是因为我们源码编译的Manifest 不是这个包含Launcher Activity 的 Manifest.xml 啊
Launcher onCreate
Launcher3 开发基本上都会从这个入口来熟悉 了解,这里以前了解过,可以看看相关资料参考。 我们直接在onCreate 方法实现即可。
思考
如何实现设置的值在Launcher 启动的时候读取到,读取到指定的应用值才能够自启动指定的app?
这里我给出自己的想法
- 通过数据库,ContentProvider 调用。Launcher 里面读取另外app 设置的值,存储在另外app 的数据库中
- 通过本地文件,比如:本地文件写值, Launcher 读取文件里面值
- 通过属性:系统写一个属性值,属性值对应的value 值。设置app自启的应用负责写入值、修改值。Launcher 里面负责读取值,然后自启指定app
- 通过系统数据库来实现,和属性比较相似。Framework 层Settings.System, Settings.Secure和Settings.Global存储来实现 参考:Framework 层Settings.System, Settings.Secure和Settings.Global存储及应用
验证
上面在实现方案中已经说明如何实现,实际测试验证可以直接写代码验证,在 Framework 层Settings.System, Settings.Secure和Settings.Global存储及应用 资料中有现成的Demo, 也可以用adb 命令来验证下。 实际效果ok, 有人会问 Launcher 死掉岂不是 直接进入了指定自启的App ? 对于系统Launcher3 而言,这个问题不用考虑了。
总结
- 这里从系统角度 给出了应用自启的一个解决方案,建议不要用开机广播实现
- 涉及到的知识点需要了解基本的Launcher3 源码 和 Settings.System, Settings.Secure和Settings.Global存储的应用