根Acitivity的启动过程(1) Launcher 向ActivityManagerService发送一个启动MainActivity的进程间通信请求

来源:互联网 发布:pc记账软件 编辑:程序博客网 时间:2024/04/30 09:28

Activity有两种

  • 由Launcher启动的根actvity
  • 由activity启动的子activity

根activity在配置文件中声明

<action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" />

根Activity的启动过程

  • 首先PackageManagerService负责应用程序的安装
    1 对manifest配置文件解析,保存各个组件信息
    2 Launcher(也是一个Activity)在启动过程中向PackageManageService查询所有action=”action.Main” category = intent.CATEGORY_LAUNCHER 的activity
    3 为符合条件的每个activity创建快捷图标,并将信息和图标绑定起来

  • 在点击图标的时候执行Launcher的startActivitySafely方法

    boolean startActivitySafely(View v, Intent intent, Object tag) {        boolean success = false;        try {            success = startActivity(v, intent, tag);        } catch (ActivityNotFoundException e) {            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);        }        return success;    }
  • 接着执行startActivity(View v, Intent intent, Object tag)
    boolean startActivity(View v, Intent intent, Object tag) {        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//启动标志位设置为1,在新的任务中启动        try {            // Only launch using the new animation if the shortcut has not opted out (this is a            // private contract between launcher and may be ignored in the future).            boolean useLaunchAnimation = (v != null) &&                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);            if (useLaunchAnimation) {                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,                        v.getMeasuredWidth(), v.getMeasuredHeight());                startActivity(intent, opts.toBundle());// 带启动动画(缩放和弹出动画)            } else {                startActivity(intent);            }            return true;        } catch (SecurityException e) {            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();            Log.e(TAG, "Launcher does not have the permission to launch " + intent +                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +                    "or use the exported attribute for this activity. "                    + "tag="+ tag + " intent=" + intent, e);        }        return false;    }
  • 执行startActivity(intent)
public void startActivity(Intent intent){    startActivityForResult(intent,-1);//不需要知道返回结果}
  • 接着看一下startActivityForResult
    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {        if (mParent == null) {            Instrumentation.ActivityResult ar =                mInstrumentation.execStartActivity(                    this, mMainThread.getApplicationThread(), mToken, this,                    intent, requestCode, options);            if (ar != null) {                mMainThread.sendActivityResult(                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),                    ar.getResultData());            }            if (requestCode >= 0) {                // If this start is requesting a result, we can avoid making                // the activity visible until the result is received.  Setting                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the                // activity hidden during this time, to avoid flickering.                // This can only be done when a result is requested because                // that guarantees we will get information back when the                // activity is finished, no matter what happens to it.                mStartedActivity = true;            }        } else {            if (options != null) {                mParent.startActivityFromChild(this, intent, requestCode, options);            } else {                // Note we want to go through this method for compatibility with                // existing applications that may have overridden it.                mParent.startActivityFromChild(this, intent, requestCode);            }        }    }

mInstrumentation是Activity的成员变量,用来监控应用程序与系统之间的交互操作。

mInstrumentation.execStartActivity 有个ApplicationThread参数是ActivityThread的内部类型weiApplicationThread的Binder本地对象,mInstrumentation最终将这个ApplicationThread传递给ActivityManagerService,AMS通过它通知Launcher进入pause状态。
mToken(IBinder)是一个Binder代理对象,指向了AMS中ActivityRecord的Binder本地对象,ActivityRecord用来维护组建的运行状态和信息,这样AMS就可以获得Launcher组件的信息了。
- 接着看mInstrumentation.execStartActivity

    public ActivityResult execStartActivity(            Context who, IBinder contextThread, IBinder token, Activity target,            Intent intent, int requestCode, Bundle options) {        IApplicationThread whoThread = (IApplicationThread) contextThread;        if (mActivityMonitors != null) {            synchronized (mSync) {                final int N = mActivityMonitors.size();                for (int i=0; i<N; i++) {                    final ActivityMonitor am = mActivityMonitors.get(i);                    if (am.match(who, null, intent)) {                        am.mHits++;                        if (am.isBlocking()) {                            return requestCode >= 0 ? am.getResult() : null;                        }                        break;                    }                }            }        }        try {            intent.setAllowFds(false);            intent.migrateExtraStreamToClipData();            int result = ActivityManagerNative.getDefault()                .startActivity(whoThread, intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target != null ? target.mEmbeddedID : null,                        requestCode, 0, null, null, options);            checkStartActivityResult(result, intent);        } catch (RemoteException e) {        }        return null;    }

ActivityManagerNative.getDefault().startActivity 获得一个AMS代理,最终调用ActivityManagerProxy.startActivity

   public int startActivity(IApplicationThread caller, Intent intent,            String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, String profileFile,            ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        intent.writeToParcel(data, 0);        data.writeString(resolvedType);        data.writeStrongBinder(resultTo);        data.writeString(resultWho);        data.writeInt(requestCode);        data.writeInt(startFlags);        data.writeString(profileFile);        if (profileFd != null) {            data.writeInt(1);            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);        } else {            data.writeInt(0);        }        if (options != null) {            data.writeInt(1);            options.writeToParcel(data, 0);        } else {            data.writeInt(0);        }        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);// 向AMS发送进程间通信        reply.readException();        int result = reply.readInt();        reply.recycle();        data.recycle();        return result;    }

这样通过ActivityManagerProxy向AMS发送一个进程间通信请求,启动activity。

0 0
原创粉丝点击