Skip to content

Commit 5f52de2

Browse files
Android: load native lib using ReLinker if it and Context available.
If ReLinker is available and BoxStore was built with an Android Context will load the native JNI library using ReLinker.
1 parent 883b58d commit 5f52de2

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStore.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
@ThreadSafe
6060
public class BoxStore implements Closeable {
6161

62+
/** Android Context used for native library loading. */
63+
@Nullable public static Object context;
64+
6265
private static final String VERSION = "2.4.0-2019-01-08";
6366
private static BoxStore defaultStore;
6467

@@ -186,6 +189,7 @@ public static boolean isObjectBrowserAvailable() {
186189
private final TxCallback failedReadTxAttemptCallback;
187190

188191
BoxStore(BoxStoreBuilder builder) {
192+
context = builder.context;
189193
NativeLibraryLoader.ensureLoaded();
190194

191195
directory = builder.directory;

objectbox-java/src/main/java/io/objectbox/BoxStoreBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public class BoxStoreBuilder {
6666
/** BoxStore uses this */
6767
File directory;
6868

69+
/** Android Context used for native library loading. */
70+
@Nullable
71+
Object context;
72+
6973
/** Ignored by BoxStore */
7074
private File baseDirectory;
7175

@@ -174,6 +178,8 @@ public BoxStoreBuilder androidContext(Object context) {
174178
if (context == null) {
175179
throw new NullPointerException("Context may not be null");
176180
}
181+
this.context = context;
182+
177183
File baseDir = getAndroidBaseDir(context);
178184
if (!baseDir.exists()) {
179185
baseDir.mkdir();

objectbox-java/src/main/java/io/objectbox/internal/NativeLibraryLoader.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,21 @@
2525
import java.io.IOException;
2626
import java.io.InputStream;
2727
import java.io.OutputStream;
28+
import java.lang.reflect.Method;
2829
import java.net.URL;
2930
import java.net.URLConnection;
3031

32+
import io.objectbox.BoxStore;
33+
3134
/**
3235
* Separate class, so we can mock BoxStore.
3336
*/
3437
public class NativeLibraryLoader {
38+
39+
private static final String OBJECTBOX_JNI = "objectbox-jni";
40+
3541
static {
36-
String libname = "objectbox-jni";
42+
String libname = OBJECTBOX_JNI;
3743
String filename = libname + ".so";
3844
boolean isLinux = false;
3945
// For Android, os.name is also "Linux", so we need an extra check
@@ -68,11 +74,15 @@ public class NativeLibraryLoader {
6874
System.err.println("File not available: " + file.getAbsolutePath());
6975
}
7076
try {
71-
System.loadLibrary(libname);
77+
if (!android || !loadLibraryAndroid(libname)) {
78+
System.loadLibrary(libname);
79+
}
7280
} catch (UnsatisfiedLinkError e) {
7381
if (!android && isLinux) {
7482
// maybe is Android, but check failed: try loading Android lib
75-
System.loadLibrary("objectbox-jni");
83+
if (!loadLibraryAndroid(OBJECTBOX_JNI)) {
84+
System.loadLibrary(OBJECTBOX_JNI);
85+
}
7686
} else {
7787
throw e;
7888
}
@@ -113,6 +123,27 @@ private static void checkUnpackLib(String filename) {
113123
}
114124
}
115125

126+
@SuppressWarnings("BooleanMethodIsAlwaysInverted") // more readable
127+
private static boolean loadLibraryAndroid(String libname) {
128+
if (BoxStore.context == null) {
129+
return false;
130+
}
131+
132+
try {
133+
Class<?> context = Class.forName("android.content.Context");
134+
Class<?> relinker = Class.forName("com.getkeepsafe.relinker.ReLinker");
135+
// ReLinker.loadLibrary(Context context, String library)
136+
Method loadLibrary = relinker.getMethod("loadLibrary", context, String.class);
137+
138+
loadLibrary.invoke(null, BoxStore.context, libname);
139+
} catch (ReflectiveOperationException e) {
140+
// note: do not catch Exception as it will swallow ReLinker exceptions useful for debugging
141+
return false;
142+
}
143+
144+
return true;
145+
}
146+
116147
public static void ensureLoaded() {
117148
}
118149
}

0 commit comments

Comments
 (0)