Android(安卓)开机如何跨过Luancher界面直接显示定制的app?
16lz
2021-01-26
问题背景
我们知道android启动后会先到Launcher主界面,但是对于定制开发机来说一般是开机后自启一个app。
从app收到开机广播后一般会有2秒左右的时间应用才起来,所以中间有2-3秒停留在Launcher界面上,这样看起来怪怪的。
分析
首先看为什么会首先启动Laucnher
在AMS执行到systemReady的时候,会启动startHomeActivityLocked的方法
public void systemReady(final Runnable goingCallback) { .... startHomeActivityLocked(currentUserId, "systemReady"); ....}
这个方法实际是去寻找了CATEGORY_HOME属性的app,我们看一下Luancher的Manifest文件
果然有HOME的属性
# 解决办法:
- 在开机广播中加入priority属性,这样能提高收到开机广播的顺序。
- 修改Laucnher apk的category,去掉HOME的属性,把自己的app改为HOME,这样开机就直接启动自己的app了。这样做的缺点是不方便用户切到主界面去做其他操作,app得提供去laucnher的入口,同时还得考虑原本home按键的安排;也得考虑一直点击返回按钮后的安排;默认这两个按钮都会返回到HOME属性的app。
还有没有其他办法呢?
我考虑一种解决办法是延长开机动画的时间,让开机动画掩盖Laucnher的启动,当应用app收到开机广播启动后,再停止开机动画,这样就可以无缝切换了。
frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java 中,内部类KeyguardShowDelegate中有个onDrawn回调,可以在回调中去停止动画。具体方案是在回调中延时并查询前台进程,如果起来了就可以停止动画了。
// A delegate class to map a particular invocation with a ShowListener object. private final class KeyguardShowDelegate extends IKeyguardDrawnCallback.Stub { private DrawnListener mDrawnListener; private int cnt_seconds = 0; KeyguardShowDelegate(DrawnListener drawnListener) { mDrawnListener = drawnListener; } @Override public void onDrawn() throws RemoteException { if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****"); //keyguard drawn complete ,can exit bootanim try { cnt_seconds = 0; while( !isActivityForeground() && cnt_seconds < WAIT_SENSETIME_APP_TIME){ Thread.sleep(1000); cnt_seconds++; } //ensure app has launch completed Thread.sleep(1000);} catch (Exception e) {} android.os.SystemProperties.set("service.bootanim.exit", "1"); SystemService.stop("bootanim");android.os.SystemProperties.set("sys.bootvideo.closed", "1"); } if (mDrawnListener != null) { mDrawnListener.onDrawn(); } hideScrim(); } };
isActivityForeground()根据实际情况自己去实现就好了,这里给个例子。
private boolean isActivityForeground() { ActivityManager am = (ActivityManager) mContext.getSystemService( Context.ACTIVITY_SERVICE); List list = am.getRunningTasks(1); if (list != null && list.size() > 0) { ComponentName cpn = list.get(0).topActivity;Log.d(TAG,cpn.getClassName()); if ( cpn.getClassName().startsWith("com.xx.xxx") ) { Log.d(TAG," app is foreground!"); return true; } } Log.d(TAG," app is background!"); return false;}
更多相关文章
- Android开发学习笔记:Intent的简介以及属性的详解
- Android(安卓)属性系统
- Android(安卓)应用自动启动的两种方法(开机自启动 与 另一个应用
- 一起来学习Android自定义控件1
- android启动第一个界面时即闪屏的核心代码(两种方式)
- android 开机启动流程分析(10)init 部分整体总结
- Android属性动画简析
- Android启动service下载失败后stopService,重新启动service下载出
- 重拾Android之路之Activity的四种启动模式