一、 了解桌面(Launcher)的启动过程
1. 内核—>Zygote—> SystemServer—>ActivityManager—>Launcher。最终是在ActivityManager里启动的Launcher。
对应的源代码:\frameworks\base\services\java\com\android\server\am\ActivityStack.java
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
ActivityOptions.abort(options);
return mService.startHomeActivityLocked(mCurrentUser);
}
}
.....
}
若没有其他activity就启动mService.startHomeActivityLocked(mCurrentUser);。开机时当然还没有其他的Activity。
2 startHomeActivityLocked函数路径: frameworks\base\services\java\com\android\server\am\ActivityManagerService.java
boolean startHomeActivityLocked(int userId) {
if (mHeadless) {
// Added because none of the other calls to ensureBootCompleted seem to fire
// when running headless.
ensureBootCompleted();
return false;
}
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
Intent intent = new Intent(
mTopAction,
mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mMainStack.startActivityLocked(null, intent, null, aInfo,
null, null, 0, 0, 0, 0, null, false, null);
}
}
return true;
}
函数创建一个CATEGORY_HOME的Intent,然后向PackageManagerService 查询带有CATEGORY类型为HOME的Activity,
最后启动这个Activity。
Launcher的APP源码中AndroidManifest.xml文件中有描述:
<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"/>
</intent-filter>
二、简易实现自定义桌面
根据Launcher的原理,可以将自定义的Activity作为桌面,及将自己的Activity描述里加上:
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
,然后重启机器时选择自己的Activity为桌面。
不足:安装APP后需要重启机器,并在首次重启时选择自己的activity为默认桌面。
三、通过启动广播自动打开APP
Android系统启动后会发送广播,在APP里写一个BroadcastReceiver,收到广播后启动对应的activity或者server。
public class BootBroadcastReceiver extends BroadcastReceiver{
private static final String BOOT_ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
if(arg1.getAction().equals(BOOT_ACTION)) {
Intent firstActivityIntent = new Intent(arg0, MainActivity.class);
firstActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(firstActivityIntent);
}
}
}
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name="com.example.autoinittest.BootBroadcastReceiver" >
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>