|
19 | 19 | import io.objectbox.BoxStore;
|
20 | 20 | import org.greenrobot.essentials.io.IoUtils;
|
21 | 21 |
|
| 22 | +import javax.annotation.Nonnull; |
22 | 23 | import javax.annotation.Nullable;
|
23 | 24 | import java.io.BufferedInputStream;
|
24 | 25 | import java.io.BufferedOutputStream;
|
|
29 | 30 | import java.io.InputStream;
|
30 | 31 | import java.io.InputStreamReader;
|
31 | 32 | import java.io.OutputStream;
|
| 33 | +import java.lang.reflect.Field; |
32 | 34 | import java.lang.reflect.InvocationTargetException;
|
33 | 35 | import java.lang.reflect.Method;
|
34 | 36 | import java.net.URL;
|
35 | 37 | import java.net.URLConnection;
|
| 38 | +import java.util.Arrays; |
36 | 39 |
|
37 | 40 | /**
|
38 | 41 | * Separate class, so we can mock BoxStore.
|
@@ -106,12 +109,22 @@ public class NativeLibraryLoader {
|
106 | 109 | }
|
107 | 110 | } catch (UnsatisfiedLinkError e) {
|
108 | 111 | String osArch = System.getProperty("os.arch");
|
109 |
| - String sunArch = System.getProperty("sun.arch.data.model"); |
110 |
| - String message = String.format( |
111 |
| - "[ObjectBox] Loading native library failed, please report this to us: " + |
112 |
| - "vendor=%s,os=%s,os.arch=%s,model=%s,android=%s,linux=%s,machine=%s", |
113 |
| - vendor, osName, osArch, sunArch, android, isLinux, getCpuArchOSOrNull() |
114 |
| - ); |
| 112 | + String message; |
| 113 | + if (android) { |
| 114 | + message = String.format( |
| 115 | + "[ObjectBox] Android failed to load native library," + |
| 116 | + " check your APK/App Bundle includes a supported ABI or use ReLinker" + |
| 117 | + " (vendor=%s,os=%s,os.arch=%s,SUPPORTED_ABIS=%s)", |
| 118 | + vendor, osName, osArch, getSupportedABIsAndroid() |
| 119 | + ); |
| 120 | + } else { |
| 121 | + String sunArch = System.getProperty("sun.arch.data.model"); |
| 122 | + message = String.format( |
| 123 | + "[ObjectBox] Loading native library failed, please report this to us: " + |
| 124 | + "vendor=%s,os=%s,os.arch=%s,model=%s,linux=%s,machine=%s", |
| 125 | + vendor, osName, osArch, sunArch, isLinux, getCpuArchOSOrNull() |
| 126 | + ); |
| 127 | + } |
115 | 128 | throw new LinkageError(message, e); // UnsatisfiedLinkError does not allow a cause; use its super class
|
116 | 129 | }
|
117 | 130 | }
|
@@ -262,6 +275,32 @@ private static boolean loadLibraryAndroid() {
|
262 | 275 | return true;
|
263 | 276 | }
|
264 | 277 |
|
| 278 | + /** |
| 279 | + * Return a string containing a list of ABIs that are supported by the current Android device. |
| 280 | + * If the Android device is below API level 21 (Android 5) or if looking up the value fails, |
| 281 | + * returns an empty string. |
| 282 | + */ |
| 283 | + @Nonnull |
| 284 | + private static String getSupportedABIsAndroid() { |
| 285 | + String[] supportedAbis = null; |
| 286 | + //noinspection TryWithIdenticalCatches |
| 287 | + try { |
| 288 | + Class<?> build = Class.forName("android.os.Build"); |
| 289 | + Field supportedAbisField = build.getField("SUPPORTED_ABIS"); |
| 290 | + supportedAbis = (String[]) supportedAbisField.get(null); |
| 291 | + } catch (NoSuchFieldException ignored) { |
| 292 | + } catch (IllegalAccessException ignored) { |
| 293 | + } catch (ClassNotFoundException ignored) { |
| 294 | + } |
| 295 | + // note: can't use multi-catch (would compile to ReflectiveOperationException, is K+ (19+) on Android) |
| 296 | + |
| 297 | + if (supportedAbis != null) { |
| 298 | + return Arrays.toString(supportedAbis); |
| 299 | + } else { |
| 300 | + return ""; |
| 301 | + } |
| 302 | + } |
| 303 | + |
265 | 304 | public static void ensureLoaded() {
|
266 | 305 | }
|
267 | 306 | }
|
0 commit comments