google-code-export / nativelibs4java

Automatically exported from code.google.com/p/nativelibs4java
1 stars 1 forks source link

Android support for BridJ #69

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
As of BridJ 0.4.2, BridJ ships with an experimental android arm32 binary, but 
it hasn't been tested yet.

As Atsushi Eno found out (see 
http://groups.google.com/group/nativelibs4java/browse_thread/thread/1adfd9adb150
e10c), android library jars cannot contain .so files. His patch 
(https://gist.github.com/1013707) proposes to just lookup the .so in the path 
on Android. 

This should be merged in BridJ, with maybe a .jar that contains no binary at 
all (bridj-x.x-stripped.jar ?) and an arm32 binary renamed to 
libbridj-android-arm32-arm.so (and correct 
System.loadLibrary("bridj-android-arm32-arm") code), so that binaries for 
multiple architectures can coexist in the same directory.

Original issue reported on code.google.com by olivier.chafik@gmail.com on 9 Jun 2011 at 9:33

GoogleCodeExporter commented 9 years ago
As also reported by Atsushi Eno, the class generation and loading scheme used 
by BridJ (ASM + ClassLoader.defineClass) does not work on Android.

Fortunately, others have implemented class-to-dex conversion code, as for 
instance in Clojure (Eclipse Public License 1.0) :
https://github.com/exterm/clojure/blob/android_runtime_bytecode/src/jvm/clojure/
lang/Android.java

Also see this Android issue for other options :
http://code.google.com/p/android/issues/detail?id=6322

What needs to be seen is whether available code is licensed or licensable as 
BSD (or can be legally included in BridJ with a composite license), or if we 
need to reimplement that wheel :-)

Original comment by olivier.chafik@gmail.com on 10 Jun 2011 at 8:29

GoogleCodeExporter commented 9 years ago
Another example of Dex wrapper :
https://github.com/headius/dexclient/blob/master/src/DexClient.java

Original comment by olivier.chafik@gmail.com on 10 Jun 2011 at 2:36

GoogleCodeExporter commented 9 years ago
Hello,

This should be mostly fixed by revision #2085 (class-to-dex conversion using 
shipped dex tool) and revision #2086 (loading of binary from path).

What I don't know, though, is whether it's actually needed to embed dx.jar into 
BridJ or if it's already available at run-time on any Android device (it adds 
up quite a bit of space to the JAR, most of which could be stripped away, but 
still...)

Cheers
--
Olivier

Original comment by olivier.chafik@gmail.com on 12 Jun 2011 at 5:34

GoogleCodeExporter commented 9 years ago
There's still a couple of issues to fix. I still don't get the latest code 
working, will continue investigation...

- org/bridj/android_arm32_arm/** should be also excluded from 
SNAPSHOT-android.jar, as it is not allowed for eclipse android app project to 
have shared libraries in referenced .jar (it is probably apkbuilder limitation).

- rev. #2086 first tries to load (lib)bridj_android(.so) and then 
(lib)bridj(.so), but the first attempt results in 
java.lang.UnsatisfiedLinkError ("Library bridj_android not found"). Since it is 
an Error, the following catch block doesn't work. I temporarilly removed the 
first attempt 

- I'm still getting some SEGV https://gist.github.com/1022341 I'm wondering 
what line #3 "unable to find field 
Lorg/bridj/MethodCallInfo;.javaCallback:Lorg/bridj/Callback;" indicates.

Original comment by atsushi...@gmail.com on 13 Jun 2011 at 5:15

GoogleCodeExporter commented 9 years ago
I looked for dx.jar on my HTC Desire, but could not find it. Since it is rather 
a dev. tool that does not premise to be placed on a device, I think it is not 
part of the set of "shipped in device" files.

Original comment by atsushi...@gmail.com on 13 Jun 2011 at 5:20

GoogleCodeExporter commented 9 years ago
Hello Atsushi,

Thanks for your feedback :-)

- Good call for the Error, I've updated the code...
- For the library bundling issue, I'm testing things out... I'm not getting 
warnings yet (with sdk r10, all in command-line), but maybe renaming the .so 
into .so_ might do the trick otherwise... ? (See my current test code : 
http://code.google.com/p/nativelibs4java/source/browse/trunk/libraries/Runtime/B
ridJ/src/main/cpp/android-test/?r=2103). My goal right now is first to test an 
all-integrated program on the emulator, then to prepare a separate BridJ shared 
Android library which programs can depend upon.

- The MethodCallInfo vs. javaCallback issue would be that you haven't updated 
the binary / the code with which you build the binary : there was a very recent 
change that had me recompile all binaries (including Android's 
http://code.google.com/p/nativelibs4java/updates/list).

Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 13 Jun 2011 at 9:40

GoogleCodeExporter commented 9 years ago
Hello Atsushi,

It now WORKS ! (at least, on my emulator)

I've added a small test project (derived from helloworld-jni sample) that 
builds it own library with the NDK + SDK :
http://code.google.com/p/nativelibs4java/source/browse/trunk/libraries/Runtime/B
ridJ/src/main/cpp/android-test/

To build and deploy on a running emulator, go to that directory and type 
'./build.sh package emulator start'

Native apps *must* be in lib/armeabi/*
BridJ can be included in any Ant-based Android project by putting its 
bridj-x.x-android.jar file in a directory (say, "lib") and adding the following 
property to the build.property file : jar.libs.dir=lib
This way, it will be in the classpath of the project (to build the Java files) 
and will be converted properly by dex (and the libbridj.so resource will be 
properly preserved).

TODO package BridJ as an .apk ?
TODO write a detailed example on the wiki

Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 13 Jun 2011 at 1:13

GoogleCodeExporter commented 9 years ago
I have updated the wiki with instructions on how to use BridJ on Android :

http://code.google.com/p/bridj/wiki/Download

Original comment by olivier.chafik@gmail.com on 13 Jun 2011 at 1:57

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
FYI, callbacks are still not working... Added code that generates a .zip file 
with classes.dex as you did in your project, but it persists in saying it does 
not find the class...

Original comment by olivier.chafik@gmail.com on 13 Jun 2011 at 4:21

GoogleCodeExporter commented 9 years ago
After couple of attempts to build, I got hello-jni sample working too (no 
callbacks either). hello-jni.c needs a cosmetic fix:

Index: jni/hello-jni.c
===================================================================
--- jni/hello-jni.c (リビジョン 2111)
+++ jni/hello-jni.c (作業コピー)
@@ -33,6 +33,6 @@
 int addTwoInts(int a, int b) {
    return a + b;
 }
-int passTwoIntsToCallback(int a, int b, int (cb*)(int, int)) {
+int passTwoIntsToCallback(int a, int b, int (*cb)(int, int)) {
    return cb(a, b);
 }

While I got hello-jni working, I'm now getting method resolution failure... any 
idea why it happens?

E/CPPRuntime( 6021): Failed to get address of method public static native int 
nativeandroid.unistd.jnaerated.unistdLibrary.access(org.bridj.Pointer,int)
W/dalvikvm( 6021): No implementation found for native 
Lnativeandroid/unistd/jnaerated/unistdLibrary;.access (Lorg/bridj/Pointer;I)I
...
E/AndroidRuntime( 6021): FATAL EXCEPTION: main
E/AndroidRuntime( 6021): java.lang.UnsatisfiedLinkError: access
E/AndroidRuntime( 6021):    at 
nativeandroid.unistd.jnaerated.unistdLibrary.access(Native Method)

Original comment by atsushi...@gmail.com on 14 Jun 2011 at 6:09

GoogleCodeExporter commented 9 years ago
OK, I got a fix for my issue. I'm not sure why it is needed, but BridJ.java 
first checks if the library is "c" (libc) and if it is, then it tries to load 
"null" library (I mean, null path, 0 handle and 0 symbols). Thus bridj could 
not find my unistd binding.

The attached patch fixes this issue.

Original comment by atsushi...@gmail.com on 15 Jun 2011 at 9:06

Attachments:

GoogleCodeExporter commented 9 years ago
Fixed the "class not found" issue too. It was due to incorrect parent 
ClassLoader passed to DexClassLoader. The attached patch should fix it.

Original comment by atsushi...@gmail.com on 15 Jun 2011 at 10:13

Attachments:

GoogleCodeExporter commented 9 years ago
I'm still not getting hello-jni callback version working. It is because the 
regex Pattern in BrisJ.getNativeLibrary() does not match the actual URL 
returned by getResource(). My HTC Desire returns the resource path like this:

jar:file:/mnt/asec/com.example.hellojni-1/pkg.apk!/lib/armeabi/libhello-jni.so

Bridj.java seems to have a premised URL probably assumed by emulator.

Original comment by atsushi...@gmail.com on 15 Jun 2011 at 10:23

GoogleCodeExporter commented 9 years ago
Olivier, finally, I got callback working! :-)

Though my patch this time involves packageName hack. I added one additional 
mandatory call for Android users to set packageName in BridJ class: 
setAndroidAppPackage(getApplication().getPackageName()

I think it is not very imposing requirement - would you have better idea?

Original comment by atsushi...@gmail.com on 15 Jun 2011 at 3:48

Attachments:

GoogleCodeExporter commented 9 years ago
Hello Atsushi,

Thanks a lot for all your input !

I've applied your suggestions (up to comment 14) in revision #2114 and revision 
#2115.
It should work with your URL as well as with that of the emulator, but *might* 
or might not break with other actual devices. 
Your latest patch is interesting, but I'd like to take some time to convince 
myself it's compulsory ;-)

Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 15 Jun 2011 at 4:28

GoogleCodeExporter commented 9 years ago
Building upon your proposal, maybe we'd benefit even more from setting the 
Application directly, actually...
See http://developer.android.com/reference/android/app/Application.html

Application.getApplicationInfo().nativeLibraryDir would give us the information 
we need in a very clean way...

Likewise, Application.getCacheDir() could replace the ugly cacheDir resolution 
in AndroidClassDefiner's constructor...

We'd just have to enforce that AndroidSupport.setApplication(app) was called 
before any library is registered (throwing an IllegalThreadStateException if it 
hasn't been called yet).

What do you think about it ?

Original comment by olivier.chafik@gmail.com on 15 Jun 2011 at 4:35

GoogleCodeExporter commented 9 years ago
Ahh, that's an interesting discovery, but sadly ApplicationInfonativeLibraryDir 
is available only after API Level 9 (gingerbread).

Original comment by atsushi...@gmail.com on 15 Jun 2011 at 6:14

GoogleCodeExporter commented 9 years ago
Hello Atsushi,

I still cannot get callbacks to work on the emulator, so I did some *blind* 
refactoring (revision 2116)... Hope I didn't break everything on your side...
I added code that uses ApplicationInfo. nativeLibraryDir through reflection 
when it is available, and uses the existing hacks otherwise.
Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 16 Jun 2011 at 8:25

GoogleCodeExporter commented 9 years ago
That's a couple of nice changes, I love it :) Here is a patch to get correct 
"/data/data/{packagename}" directory that I think works better. It uses 
ApplicationInfo.dataDir (available since API Level 1).

It seems that Environment.getDataDirectory() only returns the File for "/data", 
not "/data/data".

Original comment by atsushi...@gmail.com on 16 Jun 2011 at 12:07

Attachments:

GoogleCodeExporter commented 9 years ago
Hi Atsushi,

Excellent, thanks ! (see revision #2117).
Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 16 Jun 2011 at 4:06

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Does this issue still need to be open? I find no issue in android support 
itself.

Original comment by atsushi...@gmail.com on 27 Jun 2011 at 9:23

GoogleCodeExporter commented 9 years ago
Hi Atsushi,

Perfect then, let's close it !
Cheers
--
zOlive

Original comment by olivier.chafik@gmail.com on 27 Jun 2011 at 11:07