第一个Apk程序的启动
来源:互联网 发布:sap hana数据库优势 编辑:程序博客网 时间:2024/06/08 05:03
Ams启动分析
上节介绍了ZygoteInit.java 启动后加载了若干服务但是我们看到手机启动后显示的是一个Activity 也就是系统启动的第一个apk程序 那么这个apk是怎么样启动的呢
此文就是探索下这个奥秘。在柯元旦老师的文章中提到过当 Ams启动成功后在会发送一个Intent来启动第一个程序,通过阅读代码确实如此!
哈这里主要设置了
在这里通过PackageManager搜索到了Action为 Intent.ACTION_MAIN ,Category为Intent.CATEGORY_HOME的Activity,并且启动搜索到的Activity就可以了。至此第一要启动的
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
上节介绍了ZygoteInit.java 启动后加载了若干服务但是我们看到手机启动后显示的是一个Activity 也就是系统启动的第一个apk程序 那么这个apk是怎么样启动的呢
此文就是探索下这个奥秘。在柯元旦老师的文章中提到过当 Ams启动成功后在会发送一个Intent来启动第一个程序,通过阅读代码确实如此!
首先来看下 Ams程序吧。Ams的入口程序为 main函数
public static final Context main(int factoryTest) { AThread thr = new AThread(); thr.start(); synchronized (thr) { while (thr.mService == null) { try { thr.wait(); } catch (InterruptedException e) { } } } ActivityManagerService m = thr.mService; mSelf = m; ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; Context context = at.getSystemContext(); m.mContext = context; m.mFactoryTest = factoryTest; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep"); m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch"); m.mLaunchingActivity.setReferenceCounted(false); m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); synchronized (thr) { thr.mReady = true; thr.notifyAll(); } m.startRunning(null, null, null, null); return context; }
在此函数中首先实例了 AThread 类,从名字看这个类是个线程类,Ams的实例就是是在此类中new的。
static class AThread extends Thread { ActivityManagerService mService; boolean mReady = false; public AThread() { super("ActivityManager"); } public void run() { Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); ActivityManagerService m = new ActivityManagerService(); synchronized (this) { mService = m; notifyAll(); } synchronized (this) { while (!mReady) { try { wait(); } catch (InterruptedException e) { } } } Looper.loop(); } }
从代码中可以看到 线程还创建了一个Looper,AThread线程启动以后等待Ams 的实例完成,然后进入Looper循环。Ams 实例完成后通过ActivityThread.getSystemContext()获取一个Context,这个context是个ApplicationContext 然后在获去PowerManager、至此Ams的实例准本工作基本完成。在main方法最后调用startRunning方法
public final void startRunning(String pkg, String cls, String action, String data) { synchronized(this) { if (mStartRunning) { return; } mStartRunning = true; mTopComponent = pkg != null && cls != null ? new ComponentName(pkg, cls) : null; mTopAction = action != null ? action : Intent.ACTION_MAIN; mTopData = data; if (!mSystemReady) { return; } } systemReady(null); }
哈这里主要设置了
mTopComponent
mTopAction
mTopData当然最重要的是mTopAction,mTopAction被设置成了 Intent.ACTION_MAIN
然后继续调用了systemReady(null);
在systemReady中最后调用了 resumeTopActivityLocked(null);
private final boolean resumeTopActivityLocked(HistoryRecord prev) { // Find the first activity that is not finishing. HistoryRecord 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... return startHomeActivityLocked(); } ...... ....省略很多代码}
由于Ams刚启动所以mHistory里面没有HistoryRecord记录这样就会调用startHomeActivityLocked()方法 手机的第一apk程序正是在这里实现的启动的。
private boolean startHomeActivityLocked() { 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 = intent.resolveActivityInfo(mContext.getPackageManager(), STOCK_PM_FLAGS); if (aInfo != null) { intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don't do this if the home app is currently being // instrumented. ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid); if (app == null || app.instrumentationClass == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false); } } return true; }
在这里通过PackageManager搜索到了Action为 Intent.ACTION_MAIN ,Category为Intent.CATEGORY_HOME的Activity,并且启动搜索到的Activity就可以了。至此第一要启动的
Activity就找到并且启动了.
只要我们在自己的activity中加入
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
也可以成为第一启动的程序
这里我是在android_2.1的源码中调试跟踪的
我还下载了4.0的源码 4.0 与2.1的源码并不一样但是 意思是一样的 4.0多了一个ActivityStack包装类 2.1中关于Activity的处理都放到了 ActivityStack Ams更像一个代理了
- 第一个Apk程序的启动
- android设置开机启动第一个运行的apk
- android 启动第一个程序
- 内核启动第一个程序
- 如何让你的APK成为开机自启动第一个APK,让它成为你的Launcher吧
- 使用aapt查看apk包名和第一个启动的activity
- 一个apk中启动另个apk的启动代码
- OSWorkflow的第一个程序
- 我的第一个程序
- 我的第一个程序
- 我的第一个程序
- ibatis的第一个程序
- 我的第一个程序
- ibatis的第一个程序
- servlet 的第一个程序
- Android的第一个程序
- UNP的第一个程序
- C#的第一个程序
- plsql简单的切割字符串函数
- 消费者对Surface Pro观点不一
- rhel6中制作iso镜像并刻盘
- 成就PHP高手!五个必由之路
- C++代码内存泄漏检测
- 第一个Apk程序的启动
- byte数据的常用操作函数
- 在PHP中有urldecode()等函数来解决网页URL编码解码问题
- C# GDI+编程(五)
- Ajax调用后台方法的几种写法(一)
- ※设计模式※→☆创建型模式☆============Singleton模式(一)
- Oracle中表被删除或数据被错误修改后的恢复方法
- 自定义 Qt 窗口标题栏
- [设计模式]学习设计模式之一(简单工厂模式)