From 41f9dd7e4b78200671b73d38e6d32c9674225ba0 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Sun, 28 Jun 2015 07:34:25 +0900 Subject: [PATCH] Fix Android Platform bootstrap. First of all, java.io.File.createtempFile() causes "permission denied" error unless it is explicitly passed a path that is known to be writable. http://stackoverflow.com/questions/3660572/android-createtempfile-throws-permission-denied To fix this, we need Android's Context instance, which is expected to be supplied by AndroidSuppport.setApplication() method (which is specific to Android version build). However, this File.createTempFile() is called by Platform, and Platform class is already initialized when AndroidSupport is getting initialized. So, the entire Platform initialization cycle is broken for Android now. To fix this issue, I had to make API breaking change to add another room for Android's Application (Context) outside this Platform loop so that it can be safely initialized. --- src/main/java/org/bridj/AndroidSupport.java | 36 +++++++------------ .../java/org/bridj/AndroidWorkaround.java | 19 ++++++++++ src/main/java/org/bridj/Platform.java | 6 +++- 3 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 src/main/java/org/bridj/AndroidWorkaround.java diff --git a/src/main/java/org/bridj/AndroidSupport.java b/src/main/java/org/bridj/AndroidSupport.java index 2cda3283..45b69213 100644 --- a/src/main/java/org/bridj/AndroidSupport.java +++ b/src/main/java/org/bridj/AndroidSupport.java @@ -49,32 +49,20 @@ */ public class AndroidSupport extends PlatformSupport { - private volatile Application app; - - AndroidSupport() { - } - - synchronized void setApp(Application application) { - if (this.app != null && application != null && this.app != application) { - throw new IllegalArgumentException("Android Application has already been set to a different value : " + this.app); - } - - this.app = application; - } - - public static void setApplication(Application application) { - ((AndroidSupport) PlatformSupport.getInstance()).setApp(application); + Application app() + { + return AndroidWorkaround.getApplication(); } String adviseToSetApp() { - return app == null ? "" : "Please use AndroidSupport.setApplication(Application). "; + return app() == null ? "" : "Please use AndroidSupport.setApplication(Application). "; } volatile AndroidClassDefiner classDefiner; synchronized File getCacheDir() throws FileNotFoundException { File cacheDir = null; - if (app != null) { - cacheDir = app.getCacheDir(); + if (app() != null) { + cacheDir = app().getCacheDir(); } if (cacheDir == null || !cacheDir.isDirectory() || !cacheDir.canWrite()) { @@ -103,11 +91,11 @@ String getLibFileName(String libName) { synchronized File getNativeLibraryDir(String someBundledNativeLibraryName) throws FileNotFoundException { //String someKnownResource = File f = null; - if (app != null) { + if (app() != null) { try { // ApplicationInfo.nativeLibraryDir is only available from API level 9 and later // http://developer.android.com/reference/android/content/pm/ApplicationInfo.html#nativeLibraryDir - f = (File) ApplicationInfo.class.getField("nativeLibraryDir").get(app.getApplicationInfo()); + f = (File) ApplicationInfo.class.getField("nativeLibraryDir").get(app().getApplicationInfo()); } catch (Throwable th) { } } @@ -124,8 +112,8 @@ synchronized File getNativeLibraryDir(String someBundledNativeLibraryName) throw } synchronized File getApplicationDataDir(String someKnownResource) throws FileNotFoundException { - if (app != null) { - return new File(app.getApplicationInfo().dataDir); + if (app() != null) { + return new File(app().getApplicationInfo().dataDir); } else { return new File(new File(Environment.getDataDirectory(), "data"), getPackageName(someKnownResource)); } @@ -142,8 +130,8 @@ public synchronized NativeLibrary loadNativeLibrary(String name) throws IOExcept } synchronized String getPackageName(String someKnownResource) throws FileNotFoundException { - if (app != null) { - return app.getPackageName(); + if (app() != null) { + return app().getPackageName(); } else { URL resource = Platform.getResource(someKnownResource); if (resource == null) { diff --git a/src/main/java/org/bridj/AndroidWorkaround.java b/src/main/java/org/bridj/AndroidWorkaround.java new file mode 100644 index 00000000..9716ee82 --- /dev/null +++ b/src/main/java/org/bridj/AndroidWorkaround.java @@ -0,0 +1,19 @@ +package org.bridj; + +import android.app.Application; + +/** + * Created by atsushi on 15/06/28. + */ +public class AndroidWorkaround { + private static Application app; + + public static void setApplication(Application application) { + app = application; + } + + public static Application getApplication() + { + return app; + } +} diff --git a/src/main/java/org/bridj/Platform.java b/src/main/java/org/bridj/Platform.java index 16ad0a6d..d054c5b2 100644 --- a/src/main/java/org/bridj/Platform.java +++ b/src/main/java/org/bridj/Platform.java @@ -710,7 +710,11 @@ static File extractEmbeddedLibraryResource(String name) throws IOException { static File createTempDir(String prefix) throws IOException { File dir; for (int i = 0; i < maxTempFileAttempts; i++) { - dir = File.createTempFile(prefix, ""); + if (Platform.isAndroid()) { + dir = AndroidWorkaround.getApplication().getDir(prefix, 0); + } else { + dir = File.createTempFile(prefix, ""); + } if (dir.delete() && dir.mkdirs()) { return dir; }