Android APK免安装启动
Android APK免安装启动
在讲诉具体实现之前说一下涉及的知识点
Java虚拟机启动流程
启动Java虚拟机,创建ClassLoader,将java字节码加载进入ClassLoader,随即找到入口函数,执行。当需要创建一个对象的时候,向Java虚拟机发送一个请求,Java虚拟机接收到请求以后,首先在内存中进行寻找,若存在,则解析class,找到相应的方法执行。若内存中不存在,则让ClassLoader对相应的.class文件通过import 路径进行加载到内存中,然后进行解析,找到对应的方法执行。(ClassLoader实际上为虚拟机的一个部分,Java虚拟机并不会一次性将java字节码中的所有class文件进行加载,是需要什么,在内存中寻找不到的时候,再通过ClassLoader将对应的.class文件通过路径方式,加载进入内存,供他人使用)。Android dalvik虚拟机对于ClassLoader的处理与Java虚拟机类似。
在说之前,先提出一个问题:
我们知道DexClassLoader加载的Activity是没有生命周期的,而我们知道dalvik对于类的查找以及加载流程了,那么我们是不是可以将我们加载的dex让Android虚拟机帮我们管理呢,因为虚拟机要加载类同样也是通过ClassLoader进行加载的。
**
这便有产生一个想法,Android程序运行过程中,所需要的类都是采用上述方式进行加载,那么可不可以找到虚拟机中的ClassLoader,将需要动态加载的dex或者APK文件进行加载,便于去寻找。
首先找到ZygoteInit.java文件 这个是创建应用进程的入口
static void invokeStaticMain(ClassLoader loader,
119 String className, String[] argv)
120 throws ZygoteInit.MethodAndArgsCaller {
121 Class cl;
122
123 try {
124 cl = loader.loadClass(className);
125 } catch (ClassNotFoundException ex) {
126 throw new RuntimeException(
127 "Missing class when invoking static main " + className,
128 ex);
129 }
130
131 Method m;
132 try {//在此处调用ActivityThread.java的main方法
133 m = cl.getMethod("main", new Class[] { String[].class });
134 } catch (NoSuchMethodException ex) {
135 throw new RuntimeException(
136 "Missing static main on " + className, ex);
137 } catch (SecurityException ex) {
138 throw new RuntimeException(
139 "Problem getting static main on " + className, ex);
140 }
141
142 int modifiers = m.getModifiers();
143 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
144 throw new RuntimeException(
145 "Main method is not public and static on " + className);
146 }
147
148 /*
149 * This throw gets caught in ZygoteInit.main(), which responds
150 * by invoking the exception's run() method. This arrangement
151 * clears up all the stack frames that were required in setting
152 * up the process.
153 */
154 throw new ZygoteInit.MethodAndArgsCaller(m, argv);
155 }
在此处创建了一个新的ActivityThread对象
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
现在我们看一下ActivityThread实例中的变量
// These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
// NOTE: The activity and window managers need to call in to
// ActivityThread to do things like update resource configurations,
// which means this lock gets held while the activity and window managers
// holds their own lock. Thus you MUST NEVER call back into the activity manager
// or window manager or anything that depends on them while holding this lock.
final ArrayMap> mPackages
= new ArrayMap>();
final ArrayMap> mResourcePackages
= new ArrayMap>();
final ArrayList mRelaunchingActivities
= new ArrayList();
我们看见其中有mPackages,mResourcePackages, mRelaunchingActivities其他两个不用理会,我们关注mPackages,我们转而进入LoadedApk.java;去看看里面有什么东西。
/**
75 * Local state maintained about a currently loaded .apk.
76 * @hide
77 */
78 public final class LoadedApk {
79
80 private static final String TAG = "LoadedApk";
81
82 private final ActivityThread mActivityThread;
83 private ApplicationInfo mApplicationInfo;
84 final String mPackageName;
85 private final String mAppDir;
86 private final String mResDir;
87 private final String[] mSplitAppDirs;
88 private final String[] mSplitResDirs;
89 private final String[] mOverlayDirs;
90 private final String[] mSharedLibraries;
91 private final String mDataDir;
92 private final String mLibDir;
93 private final File mDataDirFile;
94 private final ClassLoader mBaseClassLoader;
95 private final boolean mSecurityViolation;
96 private final boolean mIncludeCode;
97 private final boolean mRegisterPackage;
98 private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
99 Resources mResources;
100 private ClassLoader mClassLoader;
101 private Application mApplication;
102
103 private final ArrayMap> mReceivers
104 = new ArrayMap>();
105 private final ArrayMap> mUnregisteredReceivers
106 = new ArrayMap>();
107 private final ArrayMap> mServices
108 = new ArrayMap>();
109 private final ArrayMap> mUnboundServices
110 = new ArrayMap>();
111
112 int mClientCount = 0;
113
114 Application getApplication() {
115 return mApplication;
116 }
在上述的变量中我们发现有一个非final类型的ClassLoader对象,在这里楼主做了一些求证,为了证明该ClassLoader对象是我所需要的,我将日