Prevent VerifyError when loading FileCompat.
Classes which contain calls to platform specific methods cause problems, because the dexer will go looking for that method even if you put a guard condition checking the build number. However, if you lazily load a class depdending on the version number, then older API devices wont try and load it, and no VerifyError occurs.
This commit is contained in:
parent
08af7ee157
commit
2fe91bc35e
@ -19,7 +19,7 @@ public class FileCompat {
|
|||||||
|
|
||||||
if (Compatibility.hasApi(21)) {
|
if (Compatibility.hasApi(21)) {
|
||||||
symlinkOs(source, dest);
|
symlinkOs(source, dest);
|
||||||
} else if (Compatibility.hasApi(19)) {
|
} else if (Compatibility.hasApi(15)) {
|
||||||
symlinkLibcore(source, dest);
|
symlinkLibcore(source, dest);
|
||||||
} else {
|
} else {
|
||||||
symlinkRuntime(source, dest);
|
symlinkRuntime(source, dest);
|
||||||
@ -28,8 +28,15 @@ public class FileCompat {
|
|||||||
return dest.exists();
|
return dest.exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moved into a separate class rather than just a method, so that phones without API 21 will
|
||||||
|
* not attempt to load this class at runtime. Otherwise, using the Os.symlink method will cause
|
||||||
|
* a VerifyError to be thrown at runtime when the FileCompat class is first used.
|
||||||
|
*/
|
||||||
|
private static class Symlink21 {
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
protected static void symlinkOs(SanitizedFile source, SanitizedFile dest) {
|
public void symlink(SanitizedFile source, SanitizedFile dest) {
|
||||||
try {
|
try {
|
||||||
android.system.Os.symlink(source.getAbsolutePath(), dest.getAbsolutePath());
|
android.system.Os.symlink(source.getAbsolutePath(), dest.getAbsolutePath());
|
||||||
} catch (ErrnoException e) {
|
} catch (ErrnoException e) {
|
||||||
@ -37,6 +44,13 @@ public class FileCompat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(21)
|
||||||
|
protected static void symlinkOs(SanitizedFile source, SanitizedFile dest) {
|
||||||
|
new Symlink21().symlink(source, dest);
|
||||||
|
}
|
||||||
|
|
||||||
protected static void symlinkRuntime(SanitizedFile source, SanitizedFile dest) {
|
protected static void symlinkRuntime(SanitizedFile source, SanitizedFile dest) {
|
||||||
String commands[] = {
|
String commands[] = {
|
||||||
"/system/bin/ln",
|
"/system/bin/ln",
|
||||||
@ -58,8 +72,10 @@ public class FileCompat {
|
|||||||
Object os = Class.forName("libcore.io.Libcore").getField("os").get(null);
|
Object os = Class.forName("libcore.io.Libcore").getField("os").get(null);
|
||||||
Method symlink = os.getClass().getMethod("symlink", String.class, String.class);
|
Method symlink = os.getClass().getMethod("symlink", String.class, String.class);
|
||||||
symlink.invoke(os, source.getAbsolutePath(), dest.getAbsolutePath());
|
symlink.invoke(os, source.getAbsolutePath(), dest.getAbsolutePath());
|
||||||
} catch (InvocationTargetException | NoSuchMethodException | ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {
|
} catch (Exception e) {
|
||||||
// Do nothing
|
// Should catch more specific exceptions than just "Exception" here, but there are
|
||||||
|
// some which come from libcore.io.Libcore, which we don't have access to at compile time.
|
||||||
|
Log.e(TAG, "Could not symlink " + source.getAbsolutePath() + " to " + dest.getAbsolutePath() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user