文章目录

  • 一、 Activity 中的 getApplication() 方法分析
  • 二、 ActivityThread 中的 H 处理 消息及 handleLaunchActivity 方法操作
  • 三、 ActivityThread 中的 performLaunchActivity 方法
  • 四、 LoadedApk 中的 mApplication 成员
  • 五、 ActivityThread 涉及源码
  • 六、 Instrumentation 涉及源码
  • 七、 LoadedApk 涉及源码

一、 Activity 中的 getApplication() 方法分析


在 Activity 中调用 getApplication() 方法 , 获取 Application 的过程分析 ;

下面就是调用的 Activity 的 getApplication() 方法 , 其获取的是 Application mApplication 成员 ;

而 mApplication 成员是在 attach() 方法中赋值的 ;

public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback, WindowControllerCallback,AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {@UnsupportedAppUsageprivate Application mApplication;/** Return the application that owns this activity. */public final Application getApplication() {return mApplication;}@UnsupportedAppUsagefinal void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {attachBaseContext(context);mApplication = application;}
}

参考源码路径 : frameworks/base/core/java/android/app/Activity.java

二、 ActivityThread 中的 H 处理 消息及 handleLaunchActivity 方法操作


在 ActivityThread 中 , 创建并启动一个 Activity , H ( Handler 子类 ) 接到一个 LAUNCH_ACTIVITY 消息 , 在相应的处理该 LAUNCH_ACTIVITY 消息的 handleMessage 方法中 , 调用了 handleLaunchActivity 方法 ;

public final class ActivityThread {private class H extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");final ActivityClientRecord r = (ActivityClientRecord) msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);// ★ 调用 handleLaunchActivity 方法处理该消息handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;} // switch} // handleMessage} // private class H extends Handler}

参考路径 : frameworks/base/core/java/android/app/ActivityThread.java

三、 ActivityThread 中的 performLaunchActivity 方法


handleLaunchActivity 方法中调用了 performLaunchActivity 方法 , 在该方法中通过 mInstrumentation.newActivity 创建 Activity , Instrumentation 创建 Activity 是通过反射进行的 ;

performLaunchActivity 方法中创建了 Activity 后 , 就调用了 Activity 的 attach 方法 , 为 Activity 中的 Application mApplication 成员赋值 ;

                activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);

在调用的 activity.attach 中第六个参数 app 就是设置的 Application , app 的创建代码如下 , 这里是传入 Activity attach 方法中的 Application , 赋值给 Activity 中的 mApplication 成员 , packageInfo 就是 LoadedApk , LoadedApk 的 makeApplication 直接使用的就是 LoadedApk 中的 mApplication 成员 ;

Application app = r.packageInfo.makeApplication(false, mInstrumentation);

主要源码 :

public final class ActivityThread {private class H extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");final ActivityClientRecord r = (ActivityClientRecord) msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);// ★ 调用 handleLaunchActivity 方法处理该消息handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;} // switch} // handleMessage} // private class H extends Handlerprivate void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// ★ 此处创建了一个 ActivityActivity a = performLaunchActivity(r, customIntent);}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");ActivityInfo aInfo = r.activityInfo;ContextImpl appContext = createBaseContextForActivity(r);// ★ 声明 ActivityActivity activity = null;try {java.lang.ClassLoader cl = appContext.getClassLoader();// ★ 创建 Activity , 与创建 Application 类似activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);} catch (Exception e) {}try {// ★ 这里是传入 Activity attach 方法中的 Application , 赋值给 Activity 中的 mApplication 成员Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {appContext.setOuterContext(activity);// ★ 此处调用了 Activity 的 attach 方法 , 给 Activity 中的 mApplication 成员赋值activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);return activity;}}

参考路径 : frameworks/base/core/java/android/app/ActivityThread.java

四、 LoadedApk 中的 mApplication 成员


LoadedApk 中的 mApplication 成员已经替换成了自定义的 Application , 不再是代理的 Application , 因此从 Activity 中获取的 Application 是已经替换后的用户自定义的 Application , 不是代理 Application ;

Application 已经执行完毕 , Application 替换操作是在 Application 的 onCreate 方法中执行的 , 此处的 Activity 执行肯定在 Application 创建完毕之后执行的 ;

主要源码 :

public final class LoadedApk {public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {// ★ 如果之前创建过 Application , 就直接使用if (mApplication != null) {return mApplication;}}
}

参考路径 : frameworks/base/core/java/android/app/LoadedApk.java

五、 ActivityThread 涉及源码


public final class ActivityThread {private class H extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");final ActivityClientRecord r = (ActivityClientRecord) msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);// ★ 调用 handleLaunchActivity 方法处理该消息handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;} // switch} // handleMessage} // private class H extends Handlerprivate void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();mSomeActivitiesChanged = true;if (r.profilerInfo != null) {mProfiler.setProfiler(r.profilerInfo);mProfiler.startProfiling();}// Make sure we are running with the most recent config.handleConfigurationChanged(null, null);if (localLOGV) Slog.v(TAG, "Handling launch of " + r);// Initialize before creating the activityWindowManagerGlobal.initialize();// ★ 此处创建了一个 ActivityActivity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);if (!r.activity.mFinished && r.startsNotResumed) {// The activity manager actually wants this one to start out paused, because it// needs to be visible but isn't in the foreground. We accomplish this by going// through the normal startup (because activities expect to go through onResume()// the first time they run, before their window is displayed), and then pausing it.// However, in this case we do -not- need to do the full pause cycle (of freezing// and such) because the activity manager assumes it can just retain the current// state it has.performPauseActivityIfNeeded(r, reason);// We need to keep around the original state, in case we need to be created again.// But we only do this for pre-Honeycomb apps, which always save their state when// pausing, so we can not have them save their state when restarting from a paused// state. For HC and later, we want to (and can) let the state be saved as the// normal part of stopping the activity.if (r.isPreHoneycomb()) {r.state = oldState;}}} else {// If there was an error, for any reason, tell the activity manager to stop us.try {ActivityManager.getService().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}}private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);}ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);}ContextImpl appContext = createBaseContextForActivity(r);// ★ 声明 ActivityActivity activity = null;try {java.lang.ClassLoader cl = appContext.getClassLoader();// ★ 创建 Activity , 与创建 Application 类似activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();if (r.state != null) {r.state.setClassLoader(cl);}} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to instantiate activity " + component+ ": " + e.toString(), e);}}try {// ★ 这里是传入 Activity attach 方法中的 Application , 赋值给 Activity 中的 mApplication 成员Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (localLOGV) Slog.v(TAG, "Performing launch of " + r);if (localLOGV) Slog.v(TAG, r + ": app=" + app+ ", appName=" + app.getPackageName()+ ", pkg=" + r.packageInfo.getPackageName()+ ", comp=" + r.intent.getComponent().toShortString()+ ", dir=" + r.packageInfo.getAppDir());if (activity != null) {CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());Configuration config = new Configuration(mCompatConfiguration);if (r.overrideConfig != null) {config.updateFrom(r.overrideConfig);}if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}appContext.setOuterContext(activity);// ★ 此处调用了 Activity 的 attach 方法 , 给 Activity 中的 mApplication 成员赋值activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback);if (customIntent != null) {activity.mIntent = customIntent;}r.lastNonConfigurationInstances = null;checkAndBlockForNetworkAccess();activity.mStartedActivity = false;int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onCreate()");}r.activity = activity;r.stopped = true;if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}if (!r.activity.mFinished) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}if (!r.activity.mFinished) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onPostCreate()");}}}r.paused = true;mActivities.put(r.token, r);} catch (SuperNotCalledException e) {throw e;} catch (Exception e) {if (!mInstrumentation.onException(activity, e)) {throw new RuntimeException("Unable to start activity " + component+ ": " + e.toString(), e);}}return activity;}}

参考路径 : frameworks/base/core/java/android/app/ActivityThread.java

六、 Instrumentation 涉及源码


Instrumentation 中创建 Activity 的 newActivity 方法 ;

public class Instrumentation {/*** Perform instantiation of an {@link Activity} object.  This method is intended for use with* unit tests, such as android.test.ActivityUnitTestCase.  The activity will be useable* locally but will be missing some of the linkages necessary for use within the system.* * @param clazz The Class of the desired Activity* @param context The base context for the activity to use* @param token The token for this activity to communicate with* @param application The application object (if any)* @param intent The intent that started this Activity* @param info ActivityInfo from the manifest* @param title The title, typically retrieved from the ActivityInfo record* @param parent The parent Activity (if any)* @param id The embedded Id (if any)* @param lastNonConfigurationInstance Arbitrary object that will be* available via {@link Activity#getLastNonConfigurationInstance()* Activity.getLastNonConfigurationInstance()}.* @return Returns the instantiated activity* @throws InstantiationException* @throws IllegalAccessException*/public Activity newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id,Object lastNonConfigurationInstance) throws InstantiationException, IllegalAccessException {Activity activity = (Activity)clazz.newInstance();ActivityThread aThread = null;activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,info, title, parent, id,(Activity.NonConfigurationInstances)lastNonConfigurationInstance,new Configuration(), null /* referrer */, null /* voiceInteractor */,null /* window */, null /* activityConfigCallback */);return activity;}}

参考路径 : frameworks/base/core/java/android/app/Instrumentation.java

七、 LoadedApk 涉及源码


LoadedApk 中相关源码 :

public final class LoadedApk {public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {// ★ 如果之前创建过 Application , 就直接使用if (mApplication != null) {return mApplication;}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");Application app = null;String appClass = mApplicationInfo.className;if (forceDefaultAppClass || (appClass == null)) {appClass = "android.app.Application";}try {java.lang.ClassLoader cl = getClassLoader();if (!mPackageName.equals("android")) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"initializeJavaContextClassLoader");initializeJavaContextClassLoader();Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);appContext.setOuterContext(app);} catch (Exception e) {if (!mActivityThread.mInstrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to instantiate application " + appClass+ ": " + e.toString(), e);}}mActivityThread.mAllApplications.add(app);mApplication = app;if (instrumentation != null) {try {instrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!instrumentation.onException(app, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}}// Rewrite the R 'constants' for all library apks.SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();final int N = packageIdentifiers.size();for (int i = 0; i < N; i++) {final int id = packageIdentifiers.keyAt(i);if (id == 0x01 || id == 0x7f) {continue;}rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);return app;}}

参考路径 : frameworks/base/core/java/android/app/LoadedApk.java

【Android 安全】DEX 加密 ( Application 替换 | 分析 Activity 组件中获取的 Application | ActivityThread | LoadedApk )相关推荐

  1. 【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application 二 )

    文章目录 一. ActivityThread 中的 installProvider 方法 ( 创建 ContentProvider 内容提供者 ) 二. installProvider 方法的第三分支 ...

  2. 【Android 安全】DEX 加密 ( Application 替换 | 分析 BroadcastReceiver 组件中调用 getApplication() 获取的 Application )

    文章目录 一. Service 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 RECEIVER 消息 三. ActivityThread 中的 ...

  3. 【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application )

    文章目录 一. ContentProvider 创建过程分析 二. ActivityThread 中的 H 处理 BIND_APPLICATION 消息 三. ActivityThread 中的 ha ...

  4. 【Android 安全】DEX 加密 ( Application 替换 | 分析 Service 组件中调用 getApplication() 获取的 Application 是否替换成功 )

    文章目录 一. Service 中的 getApplication() 方法分析 二. ActivityThread 中的 H 处理 CREATE_SERVICE 消息 三. ActivityThre ...

  5. 在组件中获取Application

    首先项目是组件化了的,其次有一个library组件,用做基础组件. 然后在基础组件里面新建一个BaseApplication作为Application基类.然后在主工程里面新建一个XXApplicat ...

  6. 调用Android系统自带相机拍照,从相册中获取图片

    一,前言: 在日常的手机应用开发过程中,经常会遇到上传图片的需求,像上传头像之类的,这就需要调用系统的相机,相册获取照片.但是在Android 系统7.0之后认为这种操作是不安全的,这篇文章主要就是记 ...

  7. android设置提交的隐藏域以及在onItemClick中获取对应的数据

    在ui  的xml文件上添加一个文本隐藏域 <TextView android:id="@+id/novelUrl"android:layout_width="wr ...

  8. android 媒体的uri,安卓 - 从相对路径+显示名称中获取媒体的URI或ID

    我尝试添加音频文件,val values = ContentValues().apply { put(MediaStore.Audio.Media.RELATIVE_PATH, libraryPart ...

  9. android回收站目录详解,android - 如何在回收站适配器外部的回收站视图中获取当前商品的位置 - 堆栈内存溢出...

    我在整个屏幕上显示一个回收站视图,该回收站视图只有一个图像视图,我想知道如何在回收站适配器之外获取屏幕上显示的imageview的位置. 我试图实现一个接口,但结果不准确.我想立即保存当前位置. 我的 ...

最新文章

  1. Oracle审计--AUD$占用空间较大处理方案
  2. java 集成grizzly_java – 在Grizzly上使用JaaS和Jersey
  3. 使用Google App Engine、Google Closure Library与Clojure编写HTML5应用
  4. jqGrid的autoencode参数设置为true在客户端可能引发的编码问题
  5. Google Apps – Framework, Phonesky, GmsCore w/ AOSP Build.
  6. 使用Mutex进行线程处理
  7. word List 17
  8. 黑鸭宣布开源项目-年度新秀
  9. c语言编写记账程序,C语言会计记账管理系统
  10. Ubuntu18.04 上 ESP8285 的 esp-at release_v2.2.0.0 编译环境搭建
  11. C语言:解决九宫格问题
  12. 推荐几款网页截图工具可以全屏截图,也可对图片编辑
  13. Node.js 网页瘸腿稍强点爬虫再体验
  14. Windows11 出现桌面管理器dwm.exe占用内存过高的解决方法
  15. Histromap of World History: The rise and fall of peoples and notions for 4000 years
  16. java编写三角形面积_用Java描述一个三角形,提供计算三角形面积方法.三角形的三个边长从键盘输入....
  17. TK1安装Caffe
  18. 【2018NOIP普及组】T2:龙虎斗 试题解析
  19. 时间复杂度分析:递归算法
  20. cobbler一键装机流程

热门文章

  1. Qt下的OpenGL 编程(3)绘制平面几何体
  2. 生活中的算法---公交换乘
  3. 无法删除xxx文档/文件夹:找不到指定的路径。请确定指定的路径是否正确
  4. 使用JDBC连接SQL Server 2000 命名实例(Named Instance)
  5. c++ 动态规划(数塔)
  6. 通过angular.js实现MVC的基本步骤
  7. python---微信聊天机器人
  8. http://www.himigame.com/mac-cocoa-application/893.html
  9. 奖牌分配/Median Pyramid Hard
  10. https的基本原理,看完你的程序员女朋友再也不和你提分手了