提交 1b7cfbf7 编写于 作者: S superq_sky

Optimized process of copying native libs.

上级 ad024b1b
......@@ -47,7 +47,6 @@ import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.support.annotation.NonNull;
......@@ -147,22 +146,7 @@ public final class LoadedPlugin {
private Application mApplication;
// void dumpClass(Class cls) {
// Log.w(TAG, "########################################");
// Log.w(TAG, "cls: " + cls.getName());
// Log.w(TAG, "cls.super: " + cls.getSuperclass());
// Log.w(TAG, "field size: " + cls.getDeclaredFields().length);
// Log.w(TAG, "method size: " + cls.getDeclaredMethods().length);
//
// for (Field f : cls.getDeclaredFields()) {
// Log.w(TAG, "field: " + f.getType().getName() + " " + f.getName());
// }
// for (Method m : cls.getDeclaredMethods()) {
// Log.w(TAG, "method: " + m.getReturnType() + " " + m.getName() + " " + Arrays.toString(m.getParameterTypes()));
// }
// }
LoadedPlugin(PluginManager pluginManager, Context context, File apk) throws PackageParser.PackageParserException {
LoadedPlugin(PluginManager pluginManager, Context context, File apk) throws Exception {
this.mPluginManager = pluginManager;
this.mHostContext = context;
this.mLocation = apk.getAbsolutePath();
......@@ -172,14 +156,6 @@ public final class LoadedPlugin {
this.mPackageInfo.applicationInfo = this.mPackage.applicationInfo;
this.mPackageInfo.applicationInfo.sourceDir = apk.getAbsolutePath();
// dumpClass(PackageParser.class);
// dumpClass(this.mPackage.getClass());
// try {
// dumpClass(Class.forName("android.content.pm.PackageParser$SigningDetails"));
// } catch (ClassNotFoundException e) {
// Log.w(TAG, e);
// }
if (Build.VERSION.SDK_INT == 27 && Build.VERSION.PREVIEW_SDK_INT != 0) { // Android P Preview
this.mPackageInfo.signatures = this.mPackage.mSigningDetails.signatures;
} else {
......@@ -239,25 +215,18 @@ public final class LoadedPlugin {
Map<ComponentName, ActivityInfo> receivers = new HashMap<ComponentName, ActivityInfo>();
for (PackageParser.Activity receiver : this.mPackage.receivers) {
receivers.put(receiver.getComponentName(), receiver.info);
try {
BroadcastReceiver br = BroadcastReceiver.class.cast(getClassLoader().loadClass(receiver.getComponentName().getClassName()).newInstance());
for (PackageParser.ActivityIntentInfo aii : receiver.intents) {
this.mHostContext.registerReceiver(br, aii);
}
} catch (Exception e) {
e.printStackTrace();
BroadcastReceiver br = BroadcastReceiver.class.cast(getClassLoader().loadClass(receiver.getComponentName().getClassName()).newInstance());
for (PackageParser.ActivityIntentInfo aii : receiver.intents) {
this.mHostContext.registerReceiver(br, aii);
}
}
this.mReceiverInfos = Collections.unmodifiableMap(receivers);
this.mPackageInfo.receivers = receivers.values().toArray(new ActivityInfo[receivers.size()]);
}
private void tryToCopyNativeLib(File apk) {
Bundle metaData = this.mPackageInfo.applicationInfo.metaData;
if (metaData != null && metaData.getBoolean("VA_IS_HAVE_LIB")) {
PluginUtil.copyNativeLib(apk, mHostContext, mPackageInfo, mNativeLibDir);
}
private void tryToCopyNativeLib(File apk) throws Exception {
PluginUtil.copyNativeLib(apk, mHostContext, mPackageInfo, mNativeLibDir);
}
public String getLocation() {
......
......@@ -23,15 +23,13 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Keep;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextThemeWrapper;
import com.didi.virtualapk.PluginManager;
......@@ -46,10 +44,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
......@@ -186,68 +180,98 @@ public class PluginUtil {
return null;
}
}
public static void copyNativeLib(File apk, Context context, PackageInfo packageInfo, File nativeLibDir) {
public static void copyNativeLib(File apk, Context context, PackageInfo packageInfo, File nativeLibDir) throws Exception {
long startTime = System.currentTimeMillis();
ZipFile zipfile = new ZipFile(apk.getAbsolutePath());
try {
String cpuArch;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cpuArch = Build.SUPPORTED_ABIS[0];
for (String cpuArch : Build.SUPPORTED_ABIS) {
if (findAndCopyNativeLib(zipfile, context, cpuArch, packageInfo, nativeLibDir)) {
return;
}
}
} else {
cpuArch = Build.CPU_ABI;
}
boolean findSo = false;
ZipFile zipfile = new ZipFile(apk.getAbsolutePath());
ZipEntry entry;
Enumeration e = zipfile.entries();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
if (entry.isDirectory())
continue;
if(entry.getName().endsWith(".so") && entry.getName().contains("lib/" + cpuArch)){
findSo = true;
break;
if (findAndCopyNativeLib(zipfile, context, Build.CPU_ABI, packageInfo, nativeLibDir)) {
return;
}
}
e = zipfile.entries();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
if (entry.isDirectory() || !entry.getName().endsWith(".so"))
findAndCopyNativeLib(zipfile, context, "armeabi", packageInfo, nativeLibDir);
} finally {
zipfile.close();
Log.d("NativeLib", "Done! +" + (System.currentTimeMillis() - startTime) + "ms");
}
}
private static boolean findAndCopyNativeLib(ZipFile zipfile, Context context, String cpuArch, PackageInfo packageInfo, File nativeLibDir) throws Exception {
Log.d("NativeLib", "Try to copy plugin's cup arch: " + cpuArch);
boolean findLib = false;
boolean findSo = false;
byte buffer[] = null;
String libPrefix = "lib/" + cpuArch + "/";
ZipEntry entry;
Enumeration e = zipfile.entries();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
String entryName = entry.getName();
if (entryName.charAt(0) < 'l') {
continue;
}
if (entryName.charAt(0) > 'l') {
break;
}
if (!findLib && !entryName.startsWith("lib/")) {
continue;
}
findLib = true;
if (!entryName.endsWith(".so") || !entryName.startsWith(libPrefix)) {
continue;
}
if (buffer == null) {
findSo = true;
Log.d("NativeLib", "Found plugin's cup arch dir: " + cpuArch);
buffer = new byte[8192];
}
String libName = entryName.substring(entryName.lastIndexOf('/') + 1);
Log.d("NativeLib", "verify so " + libName);
File libFile = new File(nativeLibDir, libName);
String key = packageInfo.packageName + "_" + libName;
if (libFile.exists()) {
int VersionCode = Settings.getSoVersion(context, key);
if (VersionCode == packageInfo.versionCode) {
Log.d("NativeLib", "skip existing so : " + entry.getName());
continue;
if((findSo && entry.getName().contains("lib/" + cpuArch)) || (!findSo && entry.getName().contains("lib/armeabi/"))){
String[] temp = entry.getName().split("/");
String libName = temp[temp.length - 1];
System.out.println("verify so " + libName);
File libFile = new File(nativeLibDir.getAbsolutePath() + File.separator + libName);
String key = packageInfo.packageName + "_" + libName;
if (libFile.exists()) {
int VersionCode = Settings.getSoVersion(context, key);
if (VersionCode == packageInfo.versionCode) {
System.out.println("skip existing so : " + entry.getName());
continue;
}
}
FileOutputStream fos = new FileOutputStream(libFile);
System.out.println("copy so " + entry.getName() + " of " + cpuArch);
copySo(zipfile.getInputStream(entry), fos);
Settings.setSoVersion(context, key, packageInfo.versionCode);
}
}
zipfile.close();
} catch (IOException e) {
e.printStackTrace();
FileOutputStream fos = new FileOutputStream(libFile);
Log.d("NativeLib", "copy so " + entry.getName() + " of " + cpuArch);
copySo(buffer, zipfile.getInputStream(entry), fos);
Settings.setSoVersion(context, key, packageInfo.versionCode);
}
if (!findLib) {
Log.d("NativeLib", "Fast skip all!");
return true;
}
return findSo;
}
private static void copySo(InputStream input, OutputStream output) throws IOException {
private static void copySo(byte[] buffer, InputStream input, OutputStream output) throws IOException {
BufferedInputStream bufferedInput = new BufferedInputStream(input);
BufferedOutputStream bufferedOutput = new BufferedOutputStream(output);
int count;
byte data[] = new byte[8192];
while ((count = bufferedInput.read(data, 0, 8192)) != -1) {
bufferedOutput.write(data, 0, count);
while ((count = bufferedInput.read(buffer)) > 0) {
bufferedOutput.write(buffer, 0, count);
}
bufferedOutput.flush();
bufferedOutput.close();
......
......@@ -11,7 +11,7 @@ def gitUrl = 'https://github.com/didi/VirtualAPK' // Git仓库的url
group = GROUP_ID
archivesBaseName = 'core'
version = "0.9.4-dev"
version = "0.9.5-dev"
install {
......
......@@ -51,7 +51,7 @@ dependencies {
// the following aars are also compiled in host project, so they will be filterd when build plugin apk.
// but, wo can still visit their Class and Resources.
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.didi.virtualapk:core:0.9.4-dev'
compile 'com.didi.virtualapk:core:0.9.5-dev'
}
apply plugin: 'com.didi.virtualapk.plugin'
......
......@@ -41,7 +41,7 @@ apply plugin: 'com.didi.virtualapk.host'
Compile VirtualAPK in application module of `build.gradle`.
``` java
compile 'com.didi.virtualapk:core:0.9.4-dev'
compile 'com.didi.virtualapk:core:0.9.5-dev'
```
Initialize `PluginManager` in `YourApplication::attachBaseContext()`.
......
......@@ -49,7 +49,7 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.didi.virtualapk:core:0.9.4-dev'
compile 'com.didi.virtualapk:core:0.9.5-dev'
// compile project (':CoreLibrary')
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册